summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Grönholm <alex.gronholm@nextday.fi>2014-10-10 00:40:47 +0300
committerAlex Grönholm <alex.gronholm@nextday.fi>2014-10-20 13:21:49 +0300
commit235fd14a70d855f5eccb167feccb573494883548 (patch)
tree37024088284b53905272314fb01e8314eecd3936
parent740b66f8c0a43a501438092ca0b3fba326c2491d (diff)
downloadapscheduler-235fd14a70d855f5eccb167feccb573494883548.tar.gz
Modified get_callable_name() to work with a wider variety of callables
-rw-r--r--apscheduler/util.py22
-rw-r--r--tests/test_util.py26
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):