diff options
author | Alex Grönholm <alex.gronholm@nextday.fi> | 2014-10-10 00:40:47 +0300 |
---|---|---|
committer | Alex Grönholm <alex.gronholm@nextday.fi> | 2014-10-20 13:21:49 +0300 |
commit | 235fd14a70d855f5eccb167feccb573494883548 (patch) | |
tree | 37024088284b53905272314fb01e8314eecd3936 | |
parent | 740b66f8c0a43a501438092ca0b3fba326c2491d (diff) | |
download | apscheduler-235fd14a70d855f5eccb167feccb573494883548.tar.gz |
Modified get_callable_name() to work with a wider variety of callables
-rw-r--r-- | apscheduler/util.py | 22 | ||||
-rw-r--r-- | tests/test_util.py | 26 |
2 files changed, 28 insertions, 20 deletions
diff --git a/apscheduler/util.py b/apscheduler/util.py index 9396593..988f942 100644 --- a/apscheduler/util.py +++ b/apscheduler/util.py @@ -194,20 +194,26 @@ def get_callable_name(func): :rtype: str """ - f_self = getattr(func, '__self__', None) or getattr(func, 'im_self', None) + # the easy case (on Python 3.3+) + if hasattr(func, '__qualname__'): + return func.__qualname__ + # class methods, bound and unbound methods + f_self = getattr(func, '__self__', None) or getattr(func, 'im_self', None) if f_self and hasattr(func, '__name__'): - if isinstance(f_self, type): - # class method - clsname = getattr(f_self, '__qualname__', None) or f_self.__name__ - return '%s.%s' % (clsname, func.__name__) - # bound method - return '%s.%s' % (f_self.__class__.__name__, func.__name__) + f_class = f_self if isinstance(f_self, type) else f_self.__class__ + else: + f_class = getattr(func, 'im_class', None) + if f_class and hasattr(func, '__name__'): + return '%s.%s' % (f_class.__name__, func.__name__) + + # class or class instance if hasattr(func, '__call__'): + # class if hasattr(func, '__name__'): - # function, unbound method or a class with a __call__ method return func.__name__ + # instance of a class with a __call__ method return func.__class__.__name__ diff --git a/tests/test_util.py b/tests/test_util.py index 7377ce0..a416297 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -5,6 +5,7 @@ from functools import partial import pytest import pytz import six +import sys from apscheduler.util import ( asint, asbool, astimezone, convert_to_datetime, datetime_to_utc_timestamp, utc_timestamp_to_datetime, @@ -163,9 +164,9 @@ def test_datetime_repr(input, expected): class TestGetCallableName(object): @pytest.mark.parametrize('input,expected', [ (asint, 'asint'), - (DummyClass.staticmeth, 'staticmeth'), + (DummyClass.staticmeth, 'DummyClass.staticmeth' if hasattr(DummyClass, '__qualname__') else 'staticmeth'), (DummyClass.classmeth, 'DummyClass.classmeth'), - (DummyClass.meth, 'meth'), + (DummyClass.meth, 'meth' if sys.version_info[:2] == (3, 2) else 'DummyClass.meth'), (DummyClass().meth, 'DummyClass.meth'), (DummyClass, 'DummyClass'), (DummyClass(), 'DummyClass') @@ -178,26 +179,27 @@ class TestGetCallableName(object): class TestObjToRef(object): - @pytest.mark.parametrize('input', [DummyClass.meth, DummyClass.staticmeth, partial(DummyClass.meth)], - ids=['bound method', 'static method', 'partial/bound method']) + @pytest.mark.parametrize('input', [partial(DummyClass.meth)], ids=['partial/bound method']) def test_no_ref_found(self, input): exc = pytest.raises(ValueError, obj_to_ref, input) assert 'Cannot determine the reference to ' in str(exc.value) @pytest.mark.parametrize('input,expected', [ + pytest.mark.skipif(sys.version_info[:2] == (3, 2), reason="Unbound methods can't be resolved on Python 3.2")( + (DummyClass.meth, 'tests.test_util:DummyClass.meth') + ), (DummyClass.classmeth, 'tests.test_util:DummyClass.classmeth'), + pytest.mark.skipif(sys.version_info < (3, 3), reason="Requires __qualname__ (Python 3.3+)")( + (DummyClass.InnerDummyClass.innerclassmeth, 'tests.test_util:DummyClass.InnerDummyClass.innerclassmeth') + ), + pytest.mark.skipif(sys.version_info < (3, 3), reason="Requires __qualname__ (Python 3.3+)")( + (DummyClass.staticmeth, 'tests.test_util:DummyClass.staticmeth') + ), (timedelta, 'datetime:timedelta'), - ], ids=['class method', 'timedelta']) + ], ids=['unbound method', 'class method', 'inner class method', 'static method', 'timedelta']) def test_valid_refs(self, input, expected): assert obj_to_ref(input) == expected - @minpython(3, 3) - def test_inner_class_method(self): - """Tests that a reference to a class method of an inner class can be discovered.""" - - assert obj_to_ref(DummyClass.InnerDummyClass.innerclassmeth) == \ - 'tests.test_util:DummyClass.InnerDummyClass.innerclassmeth' - class TestRefToObj(object): def test_valid_ref(self): |