Merge "Use __qualname__ where appropriate"
This commit is contained in:
@@ -19,6 +19,9 @@ import functools
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
import six
|
||||
import testtools
|
||||
|
||||
from taskflow import states
|
||||
from taskflow import test
|
||||
from taskflow.tests import utils as test_utils
|
||||
@@ -111,17 +114,22 @@ class GetCallableNameTest(test.TestCase):
|
||||
|
||||
def test_method(self):
|
||||
name = reflection.get_callable_name(Class.method)
|
||||
self.assertEqual(name, '.'.join((__name__, 'method')))
|
||||
self.assertEqual(name, '.'.join((__name__, 'Class', 'method')))
|
||||
|
||||
def test_instance_method(self):
|
||||
name = reflection.get_callable_name(Class().method)
|
||||
self.assertEqual(name, '.'.join((__name__, 'Class', 'method')))
|
||||
|
||||
def test_static_method(self):
|
||||
# NOTE(imelnikov): static method are just functions, class name
|
||||
# is not recorded anywhere in them.
|
||||
name = reflection.get_callable_name(Class.static_method)
|
||||
self.assertEqual(name, '.'.join((__name__, 'static_method')))
|
||||
if six.PY3:
|
||||
self.assertEqual(name,
|
||||
'.'.join((__name__, 'Class', 'static_method')))
|
||||
else:
|
||||
# NOTE(imelnikov): static method are just functions, class name
|
||||
# is not recorded anywhere in them.
|
||||
self.assertEqual(name,
|
||||
'.'.join((__name__, 'static_method')))
|
||||
|
||||
def test_class_method(self):
|
||||
name = reflection.get_callable_name(Class.class_method)
|
||||
@@ -141,6 +149,46 @@ class GetCallableNameTest(test.TestCase):
|
||||
'__call__')))
|
||||
|
||||
|
||||
# These extended/special case tests only work on python 3, due to python 2
|
||||
# being broken/incorrect with regard to these special cases...
|
||||
@testtools.skipIf(not six.PY3, 'python 3.x is not currently available')
|
||||
class GetCallableNameTestExtended(test.TestCase):
|
||||
# Tests items in http://legacy.python.org/dev/peps/pep-3155/
|
||||
|
||||
class InnerCallableClass(object):
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
def test_inner_callable_class(self):
|
||||
obj = self.InnerCallableClass()
|
||||
name = reflection.get_callable_name(obj.__call__)
|
||||
expected_name = '.'.join((__name__, 'GetCallableNameTestExtended',
|
||||
'InnerCallableClass', '__call__'))
|
||||
self.assertEqual(expected_name, name)
|
||||
|
||||
def test_inner_callable_function(self):
|
||||
def a():
|
||||
|
||||
def b():
|
||||
pass
|
||||
|
||||
return b
|
||||
|
||||
name = reflection.get_callable_name(a())
|
||||
expected_name = '.'.join((__name__, 'GetCallableNameTestExtended',
|
||||
'test_inner_callable_function', '<locals>',
|
||||
'a', '<locals>', 'b'))
|
||||
self.assertEqual(expected_name, name)
|
||||
|
||||
def test_inner_class(self):
|
||||
obj = self.InnerCallableClass()
|
||||
name = reflection.get_callable_name(obj)
|
||||
expected_name = '.'.join((__name__,
|
||||
'GetCallableNameTestExtended',
|
||||
'InnerCallableClass'))
|
||||
self.assertEqual(expected_name, name)
|
||||
|
||||
|
||||
class NotifierTest(test.TestCase):
|
||||
|
||||
def test_notify_called(self):
|
||||
|
||||
@@ -21,6 +21,16 @@ import six
|
||||
|
||||
from taskflow.openstack.common import importutils
|
||||
|
||||
try:
|
||||
_TYPE_TYPE = types.TypeType
|
||||
except AttributeError:
|
||||
_TYPE_TYPE = type
|
||||
|
||||
# See: https://docs.python.org/2/library/__builtin__.html#module-__builtin__
|
||||
# and see https://docs.python.org/2/reference/executionmodel.html (and likely
|
||||
# others)...
|
||||
_BUILTIN_MODULES = ('builtins', '__builtin__', 'exceptions')
|
||||
|
||||
|
||||
def _get_members(obj, exclude_hidden):
|
||||
"""Yields the members of an object, filtering by hidden/not hidden."""
|
||||
@@ -86,12 +96,27 @@ def get_class_name(obj, fully_qualified=True):
|
||||
"""
|
||||
if not isinstance(obj, six.class_types):
|
||||
obj = type(obj)
|
||||
if obj.__module__ in ('builtins', '__builtin__', 'exceptions'):
|
||||
return obj.__name__
|
||||
if fully_qualified:
|
||||
return '.'.join((obj.__module__, obj.__name__))
|
||||
try:
|
||||
built_in = obj.__module__ in _BUILTIN_MODULES
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
return obj.__name__
|
||||
if built_in:
|
||||
try:
|
||||
return obj.__qualname__
|
||||
except AttributeError:
|
||||
return obj.__name__
|
||||
pieces = []
|
||||
try:
|
||||
pieces.append(obj.__qualname__)
|
||||
except AttributeError:
|
||||
pieces.append(obj.__name__)
|
||||
if fully_qualified:
|
||||
try:
|
||||
pieces.insert(0, obj.__module__)
|
||||
except AttributeError:
|
||||
pass
|
||||
return '.'.join(pieces)
|
||||
|
||||
|
||||
def get_all_class_names(obj, up_to=object):
|
||||
@@ -115,21 +140,36 @@ def get_callable_name(function):
|
||||
"""
|
||||
method_self = get_method_self(function)
|
||||
if method_self is not None:
|
||||
# this is bound method
|
||||
# This is a bound method.
|
||||
if isinstance(method_self, six.class_types):
|
||||
# this is bound class method
|
||||
# This is a bound class method.
|
||||
im_class = method_self
|
||||
else:
|
||||
im_class = type(method_self)
|
||||
parts = (im_class.__module__, im_class.__name__,
|
||||
function.__name__)
|
||||
elif inspect.isfunction(function) or inspect.ismethod(function):
|
||||
parts = (function.__module__, function.__name__)
|
||||
try:
|
||||
parts = (im_class.__module__, function.__qualname__)
|
||||
except AttributeError:
|
||||
parts = (im_class.__module__, im_class.__name__, function.__name__)
|
||||
elif inspect.ismethod(function) or inspect.isfunction(function):
|
||||
# This could be a function, a static method, a unbound method...
|
||||
try:
|
||||
parts = (function.__module__, function.__qualname__)
|
||||
except AttributeError:
|
||||
if hasattr(function, 'im_class'):
|
||||
# This is a unbound method, which exists only in python 2.x
|
||||
im_class = function.im_class
|
||||
parts = (im_class.__module__,
|
||||
im_class.__name__, function.__name__)
|
||||
else:
|
||||
parts = (function.__module__, function.__name__)
|
||||
else:
|
||||
im_class = type(function)
|
||||
if im_class is type:
|
||||
if im_class is _TYPE_TYPE:
|
||||
im_class = function
|
||||
parts = (im_class.__module__, im_class.__name__)
|
||||
try:
|
||||
parts = (im_class.__module__, im_class.__qualname__)
|
||||
except AttributeError:
|
||||
parts = (im_class.__module__, im_class.__name__)
|
||||
return '.'.join(parts)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user