diff -r bdde36cd9048 Lib/inspect.py --- a/Lib/inspect.py Mon Apr 14 10:28:58 2014 -0400 +++ b/Lib/inspect.py Tue Apr 15 13:37:13 2014 -0400 @@ -808,6 +808,11 @@ pass return lines[:blockfinder.last] +def _line_number_helper(code_obj, lines, lnum): + line_offsets = list(code_obj.co_lnotab[1::2]) + end_line = sum(line_offsets) + lnum + 1 + return lines[lnum:end_line], lnum + 1 + def getsourcelines(object): """Return a list of source lines and starting line number for an object. @@ -816,10 +821,19 @@ corresponding to the object and the line number indicates where in the original source file the first line of code was found. An OSError is raised if the source code cannot be retrieved.""" + lines, lnum = findsource(object) - if ismodule(object): return lines, 0 - else: return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): + return lines, 0 + elif iscode(object): + return _line_number_helper(object, lines, lnum) + elif isfunction(object): + return _line_number_helper(object.__code__, lines, lnum) + elif ismethod(object): + return _line_number_helper(object.__func__.__code__, lines, lnum) + else: + return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. diff -r bdde36cd9048 Lib/test/inspect_fodder2.py --- a/Lib/test/inspect_fodder2.py Mon Apr 14 10:28:58 2014 -0400 +++ b/Lib/test/inspect_fodder2.py Tue Apr 15 13:37:13 2014 -0400 @@ -109,3 +109,19 @@ #line 109 def keyword_only_arg(*, arg): pass + +@wrap(lambda: None) +def func114(): + return 115 + +@wrap() +class DecoratedClass: + pass + +@wrap(lambda: None) +class DecoratedLambdaClass: + pass + +class ClassWithMethod: + def method(self): + pass diff -r bdde36cd9048 Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Mon Apr 14 10:28:58 2014 -0400 +++ b/Lib/test/test_inspect.py Tue Apr 15 13:37:13 2014 -0400 @@ -357,6 +357,9 @@ finally: linecache.getlines = getlines + def test_getsource_on_code_object(self): + self.assertSourceEqual(mod.eggs.__code__, 12, 18) + class TestDecorators(GetSourceBase): fodderModule = mod2 @@ -366,6 +369,15 @@ def test_replacing_decorator(self): self.assertSourceEqual(mod2.gone, 9, 10) + def test_decorator_with_lambda(self): + self.assertSourceEqual(mod2.func114, 113, 115) + + def test_decorated_class(self): + self.assertSourceEqual(mod2.DecoratedClass, 118, 119) + + def test_decorated_class_with_lambda(self): + self.assertSourceEqual(mod2.DecoratedLambdaClass, 122, 123) + class TestOneliners(GetSourceBase): fodderModule = mod2 def test_oneline_lambda(self): @@ -458,6 +470,9 @@ self.assertRaises(IOError, inspect.findsource, co) self.assertRaises(IOError, inspect.getsource, co) + def test_getsource_on_method(self): + self.assertSourceEqual(mod2.ClassWithMethod.method, 126, 127) + class TestNoEOL(GetSourceBase): def __init__(self, *args, **kwargs): self.tempdir = TESTFN + '_dir'