diff -r bf5a899a5d7c Lib/inspect.py --- a/Lib/inspect.py Sun Apr 12 17:56:34 2015 -0400 +++ b/Lib/inspect.py Tue Apr 14 18:41:10 2015 -0400 @@ -596,7 +596,7 @@ if hasattr(object, '__file__'): return object.__file__ raise TypeError('{!r} is a built-in class'.format(object)) - if ismethod(object): + while ismethod(object): object = object.__func__ if isfunction(object): object = object.__code__ @@ -772,7 +772,7 @@ else: raise OSError('could not find class definition') - if ismethod(object): + while ismethod(object): object = object.__func__ if isfunction(object): object = object.__code__ diff -r bf5a899a5d7c Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Sun Apr 12 17:56:34 2015 -0400 +++ b/Lib/test/test_inspect.py Tue Apr 14 18:41:10 2015 -0400 @@ -339,6 +339,18 @@ self.assertSourceEqual(git.abuse, 29, 39) self.assertSourceEqual(mod.StupidGit, 21, 50) + def test_getsource_nested_methodtype(self): + """ + Note: MethodType is not intended to be used for methods, but if it + is used on methods, getsource should still locate the source. Refer + to Issue 19956 (http://bugs.python.org/issue19956) + """ + m1 = types.MethodType((lambda self: self), object()) + m2 = types.MethodType(m1, object()) + source1 = inspect.getsource(m1) + source2 = inspect.getsource(m2) + self.assertEqual(source1, source2) + def test_getsourcefile(self): self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile) @@ -353,7 +365,7 @@ def test_getfile(self): self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) - + def test_getfile_class_without_module(self): class CM(type): @property @@ -364,6 +376,13 @@ with self.assertRaises(TypeError): inspect.getfile(C) + def test_getfile_nested_methodtype(self): + m1 = types.MethodType((lambda self: self), object()) + m2 = types.MethodType(m1, object()) + source1 = inspect.getfile(m1) + source2 = inspect.getfile(m2) + self.assertEqual(source1, source2) + def test_getmodule_recursion(self): from types import ModuleType name = '__inspect_dummy' @@ -497,6 +516,13 @@ self.assertRaises(IOError, inspect.findsource, co) self.assertRaises(IOError, inspect.getsource, co) + def test_findsource_nested_methodtype(self): + m1 = types.MethodType((lambda self: self), object()) + m2 = types.MethodType(m1, object()) + source1 = inspect.findsource(m1) + source2 = inspect.findsource(m2) + self.assertEqual(source1, source2) + class TestNoEOL(GetSourceBase): def __init__(self, *args, **kwargs): self.tempdir = TESTFN + '_dir'