Skip to content

Commit a748745

Browse files
committed
Move ast and the class source code to top. Use proper Exception.
1 parent 71c162a commit a748745

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

Lib/inspect.py

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
'Yury Selivanov <yselivanov@sprymix.com>')
3333

3434
import abc
35+
import ast
3536
import dis
3637
import collections.abc
3738
import enum
@@ -769,6 +770,42 @@ def getmodule(object, _filename=None):
769770
if builtinobject is object:
770771
return builtin
771772

773+
774+
class ClassFoundException(Exception):
775+
pass
776+
777+
778+
class _ClassFinder(ast.NodeVisitor):
779+
780+
def __init__(self, qualname):
781+
self.stack = []
782+
self.qualname = qualname
783+
784+
def visit_FunctionDef(self, node):
785+
self.stack.append(node.name)
786+
self.stack.append('<locals>')
787+
self.generic_visit(node)
788+
self.stack.pop()
789+
self.stack.pop()
790+
791+
visit_AsyncFunctionDef = visit_FunctionDef
792+
793+
def visit_ClassDef(self, node):
794+
self.stack.append(node.name)
795+
if self.qualname == '.'.join(self.stack):
796+
# Return the decorator for the class if present
797+
if node.decorator_list:
798+
line_number = node.decorator_list[0].lineno
799+
else:
800+
line_number = node.lineno
801+
802+
# decrement by one since lines starts with indexing by zero
803+
line_number -= 1
804+
raise ClassFoundException(line_number)
805+
self.generic_visit(node)
806+
self.stack.pop()
807+
808+
772809
def findsource(object):
773810
"""Return the entire source file and starting line number for an object.
774811
@@ -801,47 +838,14 @@ def findsource(object):
801838
return lines, 0
802839

803840
if isclass(object):
804-
# Lazy import ast because it's relatively heavy and
805-
# it's not used for other than this part.
806-
import ast
807-
808-
class ClassFinder(ast.NodeVisitor):
809-
810-
def visit_FunctionDef(self, node):
811-
stack.append(node.name)
812-
stack.append('<locals>')
813-
self.generic_visit(node)
814-
stack.pop()
815-
stack.pop()
816-
817-
visit_AsyncFunctionDef = visit_FunctionDef
818-
819-
def visit_ClassDef(self, node):
820-
nonlocal line_number
821-
stack.append(node.name)
822-
if qualname == '.'.join(stack):
823-
# Return the decorator for the class if present
824-
if node.decorator_list:
825-
line_number = node.decorator_list[0].lineno
826-
else:
827-
line_number = node.lineno
828-
829-
# decrement by one since lines starts with indexing by zero
830-
line_number -= 1
831-
raise StopIteration(line_number)
832-
self.generic_visit(node)
833-
stack.pop()
834-
835-
stack = []
836-
line_number = None
837841
qualname = object.__qualname__
838842
source = ''.join(lines)
839843
tree = ast.parse(source)
840-
class_finder = ClassFinder()
844+
class_finder = _ClassFinder(qualname)
841845
try:
842846
class_finder.visit(tree)
843-
except StopIteration as e:
844-
line_number = e.value
847+
except ClassFoundException as e:
848+
line_number = e.args[0]
845849
return lines, line_number
846850
else:
847851
raise OSError('could not find class definition')

0 commit comments

Comments
 (0)