Last active
August 29, 2015 14:07
-
-
Save agronholm/a41ec3d990a28ed65a0b to your computer and use it in GitHub Desktop.
Dotted path resolution and tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def get_callable_name(func): | |
| """ | |
| Returns the best available display name for the given function/callable. | |
| :rtype: str | |
| """ | |
| # 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__'): | |
| 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__'): | |
| return func.__name__ | |
| # instance of a class with a __call__ method | |
| return func.__class__.__name__ | |
| raise TypeError('Unable to determine a name for %r -- maybe it is not a callable?' % func) | |
| def obj_to_ref(obj): | |
| """ | |
| Returns the path to the given object. | |
| :rtype: str | |
| """ | |
| try: | |
| ref = '%s:%s' % (obj.__module__, get_callable_name(obj)) | |
| obj2 = ref_to_obj(ref) | |
| if obj != obj2: | |
| raise ValueError | |
| except Exception: | |
| raise ValueError('Cannot determine the reference to %r' % obj) | |
| return ref |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class TestObjToRef(object): | |
| @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=['unbound method', 'class method', 'inner class method', 'static method', 'timedelta']) | |
| def test_valid_refs(self, input, expected): | |
| assert obj_to_ref(input) == expected |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment