qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 3/4] migrate-bitmaps-test: Fix pylint warnings


From: Vladimir Sementsov-Ogievskiy
Subject: Re: [PATCH v3 3/4] migrate-bitmaps-test: Fix pylint warnings
Date: Fri, 14 May 2021 19:40:04 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1

14.05.2021 18:43, Max Reitz wrote:
There are a couple of things pylint takes issue with:
- The "time" import is unused
- The import order (iotests should come last)
- get_bitmap_hash() doesn't use @self and so should be a function
- Semicolons at the end of some lines
- Parentheses after "if"
- Some lines are too long (80 characters instead of 79)
- inject_test_case()'s @name parameter shadows a top-level @name
   variable
- "lambda self: mc(self)" were equivalent to just "mc", but in
   inject_test_case(), it is not equivalent, so add a comment and disable
   the warning locally
- Always put two empty lines after a function
- f'exec: cat > /dev/null' does not need to be an f-string

Fix them.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---

[..]

-def inject_test_case(klass, name, method, *args, **kwargs):
+def inject_test_case(klass, suffix, method, *args, **kwargs):
      mc = operator.methodcaller(method, *args, **kwargs)
-    setattr(klass, 'test_' + method + name, lambda self: mc(self))
+    # The lambda is required to enforce the `self` parameter.  Without it,
+    # `mc` would be called without any arguments, and then complain.
+    # pylint: disable=unnecessary-lambda
+    setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
+

Interesting... I decided to experiment a bit, and what I can say now:

The actual reason is that class attrubute of type <class 'function'>, becomes a 
<class 'method'> of the class instance on instantiation.

lambda is a function, so on instantiation we'll have "method", and method can be called 
as obj.method(), and original function will get "self" first argument automatically.

mc is not a function, it's <class 'operator.methodcaller'>, so there is no 
magic, instance of the class doesn't get own method but just a refence to class 
variable instead.

So, let's modify comment to something like:

We want to add function attribute to class, so that it correctly converted to method on 
instantiation. lamba is necessary to "convert" methodcaller object (which is 
callable, but not a function) to function.


with it:
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

==== my expirements =====

# cat x.py
import operator

class X:
    def hello(self, arg):
        print("hello", arg)


mc = operator.methodcaller("hello", "Vova")
lmd = lambda self: mc(self)

print('mc:', type(mc))
print('lmd:', type(lmd))

setattr(X, "test_hello_direct", mc)
setattr(X, "test_hello_lambda", lmd)
X.simply_assigned = lmd

x = X()

x.assigned_to_instance = lmd

print('mc attached:', type(x.test_hello_direct))
print('lmd attached:', type(x.test_hello_lambda))
print('lmd simply assigned:', type(x.simply_assigned))
print('lmd assigned to instance:', type(x.assigned_to_instance))

x.test_hello_lambda()
x.simply_assigned()

print("x.test_hello_lambda is x.simply_assigned", x.test_hello_lambda is 
x.simply_assigned)
print("x.test_hello_lambda is X.test_hello_lambda", x.test_hello_lambda is 
X.test_hello_lambda)
print("x.test_hello_direct is X.test_hello_direct", x.test_hello_direct is 
X.test_hello_direct)
print("X.test_hello_lambda is X.simply_assigned", X.test_hello_lambda is 
X.simply_assigned)
print("X.test_hello_lambda type:", type(X.test_hello_lambda))

try:
    x.assigned_to_instance()
except Exception as e:
    print("assigned to instance call failed:", e)

try:
    x.test_hello_direct()
except Exception as e:
    print("direct call failed:", e)



# python3 x.py
mc: <class 'operator.methodcaller'>
lmd: <class 'function'>
mc attached: <class 'operator.methodcaller'>
lmd attached: <class 'method'>
lmd simply assigned: <class 'method'>
lmd assigned to instance: <class 'function'>
hello Vova
hello Vova
x.test_hello_lambda is x.simply_assigned False
x.test_hello_lambda is X.test_hello_lambda False
x.test_hello_direct is X.test_hello_direct True
X.test_hello_lambda is X.simply_assigned True
X.test_hello_lambda type: <class 'function'>
assigned to instance call failed: <lambda>() missing 1 required positional 
argument: 'self'
direct call failed: methodcaller expected 1 argument, got 0


--
Best regards,
Vladimir



reply via email to

[Prev in Thread] Current Thread [Next in Thread]