@@ -1035,79 +1035,6 @@ class ClassFoundException(Exception):
10351035 pass
10361036
10371037
1038- class _ClassFinder (ast .NodeVisitor ):
1039-
1040- def __init__ (self , cls , tree , lines , qualname ):
1041- self .stack = []
1042- self .cls = cls
1043- self .tree = tree
1044- self .lines = lines
1045- self .qualname = qualname
1046- self .lineno_found = []
1047-
1048- def visit_FunctionDef (self , node ):
1049- self .stack .append (node .name )
1050- self .stack .append ('<locals>' )
1051- self .generic_visit (node )
1052- self .stack .pop ()
1053- self .stack .pop ()
1054-
1055- visit_AsyncFunctionDef = visit_FunctionDef
1056-
1057- def visit_ClassDef (self , node ):
1058- self .stack .append (node .name )
1059- if self .qualname == '.' .join (self .stack ):
1060- # Return the decorator for the class if present
1061- if node .decorator_list :
1062- line_number = node .decorator_list [0 ].lineno
1063- else :
1064- line_number = node .lineno
1065-
1066- # decrement by one since lines starts with indexing by zero
1067- self .lineno_found .append ((line_number - 1 , node .end_lineno ))
1068- self .generic_visit (node )
1069- self .stack .pop ()
1070-
1071- def get_lineno (self ):
1072- self .visit (self .tree )
1073- lineno_found_number = len (self .lineno_found )
1074- if lineno_found_number == 0 :
1075- raise OSError ('could not find class definition' )
1076- elif lineno_found_number == 1 :
1077- return self .lineno_found [0 ][0 ]
1078- else :
1079- # We have multiple candidates for the class definition.
1080- # Now we have to guess.
1081-
1082- # First, let's see if there are any method definitions
1083- for member in self .cls .__dict__ .values ():
1084- if (isinstance (member , types .FunctionType ) and
1085- member .__module__ == self .cls .__module__ ):
1086- for lineno , end_lineno in self .lineno_found :
1087- if lineno <= member .__code__ .co_firstlineno <= end_lineno :
1088- return lineno
1089-
1090- class_strings = [('' .join (self .lines [lineno : end_lineno ]), lineno )
1091- for lineno , end_lineno in self .lineno_found ]
1092-
1093- # Maybe the class has a docstring and it's unique?
1094- if self .cls .__doc__ :
1095- ret = None
1096- for candidate , lineno in class_strings :
1097- if self .cls .__doc__ .strip () in candidate :
1098- if ret is None :
1099- ret = lineno
1100- else :
1101- break
1102- else :
1103- if ret is not None :
1104- return ret
1105-
1106- # We are out of ideas, just return the last one found, which is
1107- # slightly better than previous ones
1108- return self .lineno_found [- 1 ][0 ]
1109-
1110-
11111038def findsource (object ):
11121039 """Return the entire source file and starting line number for an object.
11131040
@@ -1140,11 +1067,11 @@ def findsource(object):
11401067 return lines , 0
11411068
11421069 if isclass (object ):
1143- qualname = object . __qualname__
1144- source = '' . join ( lines )
1145- tree = ast . parse ( source )
1146- class_finder = _ClassFinder ( object , tree , lines , qualname )
1147- return lines , class_finder . get_lineno ()
1070+ try :
1071+ firstlineno = object . __firstlineno__
1072+ except AttributeError :
1073+ raise OSError ( 'source code not available' )
1074+ return lines , object . __firstlineno__ - 1
11481075
11491076 if ismethod (object ):
11501077 object = object .__func__
0 commit comments