bugfix: Allow using staticmethods as jobs (#1458)

main
pwws 4 years ago committed by GitHub
parent 76ac0afbcd
commit 40b90946a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -108,7 +108,7 @@ class Job(object):
job._instance = func.__self__ job._instance = func.__self__
job._func_name = func.__name__ job._func_name = func.__name__
elif inspect.isfunction(func) or inspect.isbuiltin(func): elif inspect.isfunction(func) or inspect.isbuiltin(func):
job._func_name = '{0}.{1}'.format(func.__module__, func.__name__) job._func_name = '{0}.{1}'.format(func.__module__, func.__qualname__)
elif isinstance(func, string_types): elif isinstance(func, string_types):
job._func_name = as_text(func) job._func_name = as_text(func)
elif not inspect.isclass(func) and hasattr(func, '__call__'): # a callable class instance elif not inspect.isclass(func) and hasattr(func, '__call__'): # a callable class instance

@ -125,9 +125,37 @@ class ColorizingStreamHandler(logging.StreamHandler):
def import_attribute(name): def import_attribute(name):
"""Return an attribute from a dotted path name (e.g. "path.to.func").""" """Return an attribute from a dotted path name (e.g. "path.to.func")."""
module_name, attribute = name.rsplit('.', 1) name_bits = name.split('.')
module_name_bits, attribute_bits = name_bits[:-1], [name_bits[-1]]
module = None
# When the attribute we look for is a staticmethod, module name in its
# dotted path is not the last-before-end word
# E.g.: package_a.package_b.module_a.ClassA.my_static_method
# Thus we remove the bits from the end of the name until we can import it
while len(module_name_bits):
try:
module_name = '.'.join(module_name_bits)
module = importlib.import_module(module_name) module = importlib.import_module(module_name)
return getattr(module, attribute) break
except ModuleNotFoundError:
attribute_bits.insert(0, module_name_bits.pop())
if module is None:
raise ValueError(f'Invalid attribute name: {name}')
attribute_name = '.'.join(attribute_bits)
if hasattr(module, attribute_name):
return getattr(module, attribute_name)
# staticmethods
attribute_name = attribute_bits.pop()
attribute_owner_name = '.'.join(attribute_bits)
attribute_owner = getattr(module, attribute_owner_name)
if not hasattr(attribute_owner, attribute_name):
raise ValueError(f'Invalid attribute name: {name}')
return getattr(attribute_owner, attribute_name)
def utcnow(): def utcnow():

@ -143,6 +143,12 @@ class UnicodeStringObject(object):
return u'é' return u'é'
class ClassWithAStaticMethod(object):
@staticmethod
def static_method():
return u"I'm a static method"
with Connection(): with Connection():
@job(queue='default') @job(queue='default')
def decorated_job(x, y): def decorated_job(x, y):

@ -772,6 +772,14 @@ class TestJob(RQTestCase):
self.assertIsNotNone(job.get_call_string()) self.assertIsNotNone(job.get_call_string())
job.perform() job.perform()
def test_create_job_from_static_method(self):
"""test creating jobs with static method"""
queue = Queue(connection=self.testconn)
job = queue.enqueue(fixtures.ClassWithAStaticMethod.static_method)
self.assertIsNotNone(job.get_call_string())
job.perform()
def test_create_job_with_ttl_should_have_ttl_after_enqueued(self): def test_create_job_with_ttl_should_have_ttl_after_enqueued(self):
"""test creating jobs with ttl and checks if get_jobs returns it properly [issue502]""" """test creating jobs with ttl and checks if get_jobs returns it properly [issue502]"""
queue = Queue(connection=self.testconn) queue = Queue(connection=self.testconn)

Loading…
Cancel
Save