I'm trying to use decorator into class and get an error in pylint on line
@start_test_min_pg(min_version_pg="9.5")
No value for argument 'self' in method call
class TestsUnloggedTabled(BaseTester):
some code
def get_pg_version(self):
pg_temp = Postgres(self.host, self.port, self.username, self.password, "postgres")
current_pg_version = pg_temp.query("show server_version")[0][0].split(" ")[0]
print('PG version is: ' + current_pg_version)
return current_pg_version
def start_test_min_pg(self, min_version_pg):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
if LooseVersion(self.get_pg_version()) > LooseVersion(min_version_pg):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
@start_test_min_pg(min_version_pg="9.5")
def test_schema_hashing(self):
do something
The way that you've written your decorator, it needs to be called on an instance of your class to work properly. That is, you'd need to be applying it with:
obj = TestsUnloggedTabled(...)
@obj.start_test_min_pg(min_version_pg="9.5")
def foo():
pass
This obviously can't work when you're applying it to another method in the same class, since you can't create an instance until the class definition ends. So you clearly don't want to be calling the decorator as a method, which means you should not have self
as one of its arguments.
But you do need self
in the implementation of your code later. Where do you get it? Well, the wrapper_repeat
function is what is going to be called on the actual instance, once the class is defined. So its first argument will be that instance, and you can name it self
rather than letting it get collected with the other positional arguments in args
. You do need to remember to pass it along when you call the original function.
def start_test_min_pg(min_version_pg): # no self here
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(self, *args, **kwargs): # put it here instead
if LooseVersion(self.get_pg_version()) > LooseVersion(min_version_pg):
value = func(self, *args, **kwargs) # and pass it along
return value
return wrapper_repeat
return decorator_repeat
Note that I fixed the indentation level of the last two lines of this code, the version in your question won't work correctly (since the decorator factory will return None
). I'm guessing that may be an artifact of copying the code into Stack Overflow, not something that's actually wrong in your real code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.