diff --git a/oslo_utils/reflection.py b/oslo_utils/reflection.py index 330a537b..3333ba67 100644 --- a/oslo_utils/reflection.py +++ b/oslo_utils/reflection.py @@ -56,10 +56,19 @@ def get_member_names(obj, exclude_hidden=True): def get_class_name(obj, fully_qualified=True): """Get class name for object. - If object is a type, fully qualified name of the type is returned. - Else, fully qualified name of the type of the object is returned. - For builtin types, just name is returned. + If object is a type, returns name of the type. If object is a bound + method or a class method, returns its ``self`` object's class name. + If object is an instance of class, returns instance's class name. + Else, name of the type of the object is returned. If fully_qualified + is True, returns fully qualified name of the type. For builtin types, + just name is returned. TypeError is raised if can't get class name from + object. """ + if inspect.isfunction(obj): + raise TypeError("Can't get class name.") + + if inspect.ismethod(obj): + obj = get_method_self(obj) if not isinstance(obj, six.class_types): obj = type(obj) try: diff --git a/oslo_utils/tests/test_reflection.py b/oslo_utils/tests/test_reflection.py index b63ef8bb..cca92b8a 100644 --- a/oslo_utils/tests/test_reflection.py +++ b/oslo_utils/tests/test_reflection.py @@ -321,6 +321,30 @@ class GetClassNameTest(test_base.BaseTestCase): name = reflection.get_class_name(42) self.assertEqual('int', name) + def test_class_method(self): + name = reflection.get_class_name(Class.class_method) + self.assertEqual('%s.Class' % __name__, name) + # test with fully_qualified=False + name = reflection.get_class_name(Class.class_method, + fully_qualified=False) + self.assertEqual('Class', name) + + def test_static_method(self): + self.assertRaises(TypeError, reflection.get_class_name, + Class.static_method) + + def test_unbound_method(self): + self.assertRaises(TypeError, reflection.get_class_name, + mere_function) + + def test_bound_method(self): + c = Class() + name = reflection.get_class_name(c.method) + self.assertEqual('%s.Class' % __name__, name) + # test with fully_qualified=False + name = reflection.get_class_name(c.method, fully_qualified=False) + self.assertEqual('Class', name) + class GetAllClassNamesTest(test_base.BaseTestCase):