1
# -*- coding: utf-8 -*-
3
Python class/function parser
5
Derived from "Demo/parser/example.py" from Python distribution
7
******************************** WARNING ***************************************
8
This module is not used anymore in Spyder since v1.1.0.
9
However, it will still be part of spyderlib module for a little while -
10
we never know, it could be useful...
11
********************************************************************************
17
from types import ListType, TupleType
20
def get_info(fileName):
21
source = open(fileName, "U").read() + "\n"
22
basename = os.path.basename(os.path.splitext(fileName)[0])
23
ast = parser.suite(source)
24
return ModuleInfo(ast.totuple(line_info=True), basename)
26
def get_classes(filename):
28
Return classes (with methods) and functions of module *filename*:
29
[ (class1_lineno, class1_name, [ (method1_lineno, method1_name), ]),
30
(func1_lineno, func1_name, None),]
32
moduleinfo = get_info(filename)
34
for classname in moduleinfo.get_class_names():
35
clinfo = moduleinfo.get_class_info(classname)
37
for methodname in clinfo.get_method_names():
38
minfo = clinfo.get_method_info(methodname)
39
methods.append( (minfo.get_lineno(), methodname) )
41
classes.append( (clinfo.get_lineno(), classname, methods) )
42
for funcname in moduleinfo.get_function_names():
43
finfo = moduleinfo.get_function_info(funcname)
44
classes.append( (finfo.get_lineno(), funcname, None) )
52
# This pattern identifies compound statements, allowing them to be readily
53
# differentiated from simple statements.
55
COMPOUND_STMT_PATTERN = (
57
(symbol.compound_stmt, ['compound'])
60
def __init__(self, tree = None):
62
self._function_info = {}
64
self._extract_info(tree)
66
def _extract_info(self, tree):
68
# discover inner definitions
70
found, vars = match(self.COMPOUND_STMT_PATTERN, node)
72
cstmt = vars['compound']
73
if cstmt[0] == symbol.funcdef:
74
func_info = FunctionInfo(cstmt)
75
self._function_info[func_info._name] = func_info
76
elif cstmt[0] == symbol.classdef:
77
class_info = ClassInfo(cstmt)
78
self._class_info[class_info._name] = class_info
86
def get_class_names(self):
87
return self._class_info.keys()
89
def get_class_info(self, name):
90
return self._class_info[name]
92
def __getitem__(self, name):
94
return self._class_info[name]
96
return self._function_info[name]
100
# Mixin class providing access to function names and info.
102
def get_function_names(self):
103
return self._function_info.keys()
105
def get_function_info(self, name):
106
return self._function_info[name]
109
class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
110
def __init__(self, tree = None):
113
if tree[1][0] == symbol.decorators:
116
self._name = prefix + tree[index][1]
117
self._lineno = tree[index][2]
118
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
121
class ClassInfo(SuiteInfoBase):
122
def __init__(self, tree = None):
123
self._name = tree[2][1]
124
self._lineno = tree[2][2]
125
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
127
def get_method_names(self):
128
return self._function_info.keys()
130
def get_method_info(self, name):
131
return self._function_info[name]
134
class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
135
def __init__(self, tree = None, name = "<string>"):
138
if tree[0] == symbol.encoding_decl:
139
self._encoding = tree[2]
142
self._encoding = 'ascii'
143
SuiteInfoBase.__init__(self, tree)
146
def match(pattern, data, vars=None):
147
"""Match `data' to `pattern', with variable extraction.
150
Pattern to match against, possibly containing variables.
153
Data to be checked and against which variables are extracted.
156
Dictionary of variables which have already been found. If not
157
provided, an empty dictionary is created.
159
The `pattern' value may contain variables of the form ['varname'] which
160
are allowed to match anything. The value that is matched is returned as
161
part of a dictionary which maps 'varname' to the matched value. 'varname'
162
is not required to be a string object, but using strings makes patterns
163
and the code which uses them more readable.
165
This function returns two values: a boolean indicating whether a match
166
was found and a dictionary mapping variable names to their associated
171
if type(pattern) is ListType: # 'variables' are ['varname']
172
vars[pattern[0]] = data
174
if type(pattern) is not TupleType:
175
return (pattern == data), vars
176
if len(data) != len(pattern):
178
for pattern, data in map(None, pattern, data):
179
same, vars = match(pattern, data, vars)
185
if __name__ == '__main__':
188
classes = get_classes(sys.argv[1])
189
print "Elapsed time: %s ms" % round((time.time()-t0)*1000)
190
# from pprint import pprint