Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python3....
File: pyclbr.py
"""Parse a Python module and describe its classes and methods.
[0] Fix | Delete
[1] Fix | Delete
Parse enough of a Python file to recognize imports and class and
[2] Fix | Delete
method definitions, and to find out the superclasses of a class.
[3] Fix | Delete
[4] Fix | Delete
The interface consists of a single function:
[5] Fix | Delete
readmodule_ex(module [, path])
[6] Fix | Delete
where module is the name of a Python module, and path is an optional
[7] Fix | Delete
list of directories where the module is to be searched. If present,
[8] Fix | Delete
path is prepended to the system search path sys.path. The return
[9] Fix | Delete
value is a dictionary. The keys of the dictionary are the names of
[10] Fix | Delete
the classes defined in the module (including classes that are defined
[11] Fix | Delete
via the from XXX import YYY construct). The values are class
[12] Fix | Delete
instances of the class Class defined here. One special key/value pair
[13] Fix | Delete
is present for packages: the key '__path__' has a list as its value
[14] Fix | Delete
which contains the package search path.
[15] Fix | Delete
[16] Fix | Delete
A class is described by the class Class in this module. Instances
[17] Fix | Delete
of this class have the following instance variables:
[18] Fix | Delete
module -- the module name
[19] Fix | Delete
name -- the name of the class
[20] Fix | Delete
super -- a list of super classes (Class instances)
[21] Fix | Delete
methods -- a dictionary of methods
[22] Fix | Delete
file -- the file in which the class was defined
[23] Fix | Delete
lineno -- the line in the file on which the class statement occurred
[24] Fix | Delete
The dictionary of methods uses the method names as keys and the line
[25] Fix | Delete
numbers on which the method was defined as values.
[26] Fix | Delete
If the name of a super class is not recognized, the corresponding
[27] Fix | Delete
entry in the list of super classes is not a class instance but a
[28] Fix | Delete
string giving the name of the super class. Since import statements
[29] Fix | Delete
are recognized and imported modules are scanned as well, this
[30] Fix | Delete
shouldn't happen often.
[31] Fix | Delete
[32] Fix | Delete
A function is described by the class Function in this module.
[33] Fix | Delete
Instances of this class have the following instance variables:
[34] Fix | Delete
module -- the module name
[35] Fix | Delete
name -- the name of the class
[36] Fix | Delete
file -- the file in which the class was defined
[37] Fix | Delete
lineno -- the line in the file on which the class statement occurred
[38] Fix | Delete
"""
[39] Fix | Delete
[40] Fix | Delete
import io
[41] Fix | Delete
import sys
[42] Fix | Delete
import importlib.util
[43] Fix | Delete
import tokenize
[44] Fix | Delete
from token import NAME, DEDENT, OP
[45] Fix | Delete
[46] Fix | Delete
__all__ = ["readmodule", "readmodule_ex", "Class", "Function"]
[47] Fix | Delete
[48] Fix | Delete
_modules = {} # cache of modules we've seen
[49] Fix | Delete
[50] Fix | Delete
# each Python class is represented by an instance of this class
[51] Fix | Delete
class Class:
[52] Fix | Delete
'''Class to represent a Python class.'''
[53] Fix | Delete
def __init__(self, module, name, super, file, lineno):
[54] Fix | Delete
self.module = module
[55] Fix | Delete
self.name = name
[56] Fix | Delete
if super is None:
[57] Fix | Delete
super = []
[58] Fix | Delete
self.super = super
[59] Fix | Delete
self.methods = {}
[60] Fix | Delete
self.file = file
[61] Fix | Delete
self.lineno = lineno
[62] Fix | Delete
[63] Fix | Delete
def _addmethod(self, name, lineno):
[64] Fix | Delete
self.methods[name] = lineno
[65] Fix | Delete
[66] Fix | Delete
class Function:
[67] Fix | Delete
'''Class to represent a top-level Python function'''
[68] Fix | Delete
def __init__(self, module, name, file, lineno):
[69] Fix | Delete
self.module = module
[70] Fix | Delete
self.name = name
[71] Fix | Delete
self.file = file
[72] Fix | Delete
self.lineno = lineno
[73] Fix | Delete
[74] Fix | Delete
def readmodule(module, path=None):
[75] Fix | Delete
'''Backwards compatible interface.
[76] Fix | Delete
[77] Fix | Delete
Call readmodule_ex() and then only keep Class objects from the
[78] Fix | Delete
resulting dictionary.'''
[79] Fix | Delete
[80] Fix | Delete
res = {}
[81] Fix | Delete
for key, value in _readmodule(module, path or []).items():
[82] Fix | Delete
if isinstance(value, Class):
[83] Fix | Delete
res[key] = value
[84] Fix | Delete
return res
[85] Fix | Delete
[86] Fix | Delete
def readmodule_ex(module, path=None):
[87] Fix | Delete
'''Read a module file and return a dictionary of classes.
[88] Fix | Delete
[89] Fix | Delete
Search for MODULE in PATH and sys.path, read and parse the
[90] Fix | Delete
module and return a dictionary with one entry for each class
[91] Fix | Delete
found in the module.
[92] Fix | Delete
'''
[93] Fix | Delete
return _readmodule(module, path or [])
[94] Fix | Delete
[95] Fix | Delete
def _readmodule(module, path, inpackage=None):
[96] Fix | Delete
'''Do the hard work for readmodule[_ex].
[97] Fix | Delete
[98] Fix | Delete
If INPACKAGE is given, it must be the dotted name of the package in
[99] Fix | Delete
which we are searching for a submodule, and then PATH must be the
[100] Fix | Delete
package search path; otherwise, we are searching for a top-level
[101] Fix | Delete
module, and PATH is combined with sys.path.
[102] Fix | Delete
'''
[103] Fix | Delete
# Compute the full module name (prepending inpackage if set)
[104] Fix | Delete
if inpackage is not None:
[105] Fix | Delete
fullmodule = "%s.%s" % (inpackage, module)
[106] Fix | Delete
else:
[107] Fix | Delete
fullmodule = module
[108] Fix | Delete
[109] Fix | Delete
# Check in the cache
[110] Fix | Delete
if fullmodule in _modules:
[111] Fix | Delete
return _modules[fullmodule]
[112] Fix | Delete
[113] Fix | Delete
# Initialize the dict for this module's contents
[114] Fix | Delete
dict = {}
[115] Fix | Delete
[116] Fix | Delete
# Check if it is a built-in module; we don't do much for these
[117] Fix | Delete
if module in sys.builtin_module_names and inpackage is None:
[118] Fix | Delete
_modules[module] = dict
[119] Fix | Delete
return dict
[120] Fix | Delete
[121] Fix | Delete
# Check for a dotted module name
[122] Fix | Delete
i = module.rfind('.')
[123] Fix | Delete
if i >= 0:
[124] Fix | Delete
package = module[:i]
[125] Fix | Delete
submodule = module[i+1:]
[126] Fix | Delete
parent = _readmodule(package, path, inpackage)
[127] Fix | Delete
if inpackage is not None:
[128] Fix | Delete
package = "%s.%s" % (inpackage, package)
[129] Fix | Delete
if not '__path__' in parent:
[130] Fix | Delete
raise ImportError('No package named {}'.format(package))
[131] Fix | Delete
return _readmodule(submodule, parent['__path__'], package)
[132] Fix | Delete
[133] Fix | Delete
# Search the path for the module
[134] Fix | Delete
f = None
[135] Fix | Delete
if inpackage is not None:
[136] Fix | Delete
search_path = path
[137] Fix | Delete
else:
[138] Fix | Delete
search_path = path + sys.path
[139] Fix | Delete
# XXX This will change once issue19944 lands.
[140] Fix | Delete
spec = importlib.util._find_spec_from_path(fullmodule, search_path)
[141] Fix | Delete
_modules[fullmodule] = dict
[142] Fix | Delete
# is module a package?
[143] Fix | Delete
if spec.submodule_search_locations is not None:
[144] Fix | Delete
dict['__path__'] = spec.submodule_search_locations
[145] Fix | Delete
try:
[146] Fix | Delete
source = spec.loader.get_source(fullmodule)
[147] Fix | Delete
if source is None:
[148] Fix | Delete
return dict
[149] Fix | Delete
except (AttributeError, ImportError):
[150] Fix | Delete
# not Python source, can't do anything with this module
[151] Fix | Delete
return dict
[152] Fix | Delete
[153] Fix | Delete
fname = spec.loader.get_filename(fullmodule)
[154] Fix | Delete
[155] Fix | Delete
f = io.StringIO(source)
[156] Fix | Delete
[157] Fix | Delete
stack = [] # stack of (class, indent) pairs
[158] Fix | Delete
[159] Fix | Delete
g = tokenize.generate_tokens(f.readline)
[160] Fix | Delete
try:
[161] Fix | Delete
for tokentype, token, start, _end, _line in g:
[162] Fix | Delete
if tokentype == DEDENT:
[163] Fix | Delete
lineno, thisindent = start
[164] Fix | Delete
# close nested classes and defs
[165] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[166] Fix | Delete
del stack[-1]
[167] Fix | Delete
elif token == 'def':
[168] Fix | Delete
lineno, thisindent = start
[169] Fix | Delete
# close previous nested classes and defs
[170] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[171] Fix | Delete
del stack[-1]
[172] Fix | Delete
tokentype, meth_name, start = next(g)[0:3]
[173] Fix | Delete
if tokentype != NAME:
[174] Fix | Delete
continue # Syntax error
[175] Fix | Delete
if stack:
[176] Fix | Delete
cur_class = stack[-1][0]
[177] Fix | Delete
if isinstance(cur_class, Class):
[178] Fix | Delete
# it's a method
[179] Fix | Delete
cur_class._addmethod(meth_name, lineno)
[180] Fix | Delete
# else it's a nested def
[181] Fix | Delete
else:
[182] Fix | Delete
# it's a function
[183] Fix | Delete
dict[meth_name] = Function(fullmodule, meth_name,
[184] Fix | Delete
fname, lineno)
[185] Fix | Delete
stack.append((None, thisindent)) # Marker for nested fns
[186] Fix | Delete
elif token == 'class':
[187] Fix | Delete
lineno, thisindent = start
[188] Fix | Delete
# close previous nested classes and defs
[189] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[190] Fix | Delete
del stack[-1]
[191] Fix | Delete
tokentype, class_name, start = next(g)[0:3]
[192] Fix | Delete
if tokentype != NAME:
[193] Fix | Delete
continue # Syntax error
[194] Fix | Delete
# parse what follows the class name
[195] Fix | Delete
tokentype, token, start = next(g)[0:3]
[196] Fix | Delete
inherit = None
[197] Fix | Delete
if token == '(':
[198] Fix | Delete
names = [] # List of superclasses
[199] Fix | Delete
# there's a list of superclasses
[200] Fix | Delete
level = 1
[201] Fix | Delete
super = [] # Tokens making up current superclass
[202] Fix | Delete
while True:
[203] Fix | Delete
tokentype, token, start = next(g)[0:3]
[204] Fix | Delete
if token in (')', ',') and level == 1:
[205] Fix | Delete
n = "".join(super)
[206] Fix | Delete
if n in dict:
[207] Fix | Delete
# we know this super class
[208] Fix | Delete
n = dict[n]
[209] Fix | Delete
else:
[210] Fix | Delete
c = n.split('.')
[211] Fix | Delete
if len(c) > 1:
[212] Fix | Delete
# super class is of the form
[213] Fix | Delete
# module.class: look in module for
[214] Fix | Delete
# class
[215] Fix | Delete
m = c[-2]
[216] Fix | Delete
c = c[-1]
[217] Fix | Delete
if m in _modules:
[218] Fix | Delete
d = _modules[m]
[219] Fix | Delete
if c in d:
[220] Fix | Delete
n = d[c]
[221] Fix | Delete
names.append(n)
[222] Fix | Delete
super = []
[223] Fix | Delete
if token == '(':
[224] Fix | Delete
level += 1
[225] Fix | Delete
elif token == ')':
[226] Fix | Delete
level -= 1
[227] Fix | Delete
if level == 0:
[228] Fix | Delete
break
[229] Fix | Delete
elif token == ',' and level == 1:
[230] Fix | Delete
pass
[231] Fix | Delete
# only use NAME and OP (== dot) tokens for type name
[232] Fix | Delete
elif tokentype in (NAME, OP) and level == 1:
[233] Fix | Delete
super.append(token)
[234] Fix | Delete
# expressions in the base list are not supported
[235] Fix | Delete
inherit = names
[236] Fix | Delete
cur_class = Class(fullmodule, class_name, inherit,
[237] Fix | Delete
fname, lineno)
[238] Fix | Delete
if not stack:
[239] Fix | Delete
dict[class_name] = cur_class
[240] Fix | Delete
stack.append((cur_class, thisindent))
[241] Fix | Delete
elif token == 'import' and start[1] == 0:
[242] Fix | Delete
modules = _getnamelist(g)
[243] Fix | Delete
for mod, _mod2 in modules:
[244] Fix | Delete
try:
[245] Fix | Delete
# Recursively read the imported module
[246] Fix | Delete
if inpackage is None:
[247] Fix | Delete
_readmodule(mod, path)
[248] Fix | Delete
else:
[249] Fix | Delete
try:
[250] Fix | Delete
_readmodule(mod, path, inpackage)
[251] Fix | Delete
except ImportError:
[252] Fix | Delete
_readmodule(mod, [])
[253] Fix | Delete
except:
[254] Fix | Delete
# If we can't find or parse the imported module,
[255] Fix | Delete
# too bad -- don't die here.
[256] Fix | Delete
pass
[257] Fix | Delete
elif token == 'from' and start[1] == 0:
[258] Fix | Delete
mod, token = _getname(g)
[259] Fix | Delete
if not mod or token != "import":
[260] Fix | Delete
continue
[261] Fix | Delete
names = _getnamelist(g)
[262] Fix | Delete
try:
[263] Fix | Delete
# Recursively read the imported module
[264] Fix | Delete
d = _readmodule(mod, path, inpackage)
[265] Fix | Delete
except:
[266] Fix | Delete
# If we can't find or parse the imported module,
[267] Fix | Delete
# too bad -- don't die here.
[268] Fix | Delete
continue
[269] Fix | Delete
# add any classes that were defined in the imported module
[270] Fix | Delete
# to our name space if they were mentioned in the list
[271] Fix | Delete
for n, n2 in names:
[272] Fix | Delete
if n in d:
[273] Fix | Delete
dict[n2 or n] = d[n]
[274] Fix | Delete
elif n == '*':
[275] Fix | Delete
# don't add names that start with _
[276] Fix | Delete
for n in d:
[277] Fix | Delete
if n[0] != '_':
[278] Fix | Delete
dict[n] = d[n]
[279] Fix | Delete
except StopIteration:
[280] Fix | Delete
pass
[281] Fix | Delete
[282] Fix | Delete
f.close()
[283] Fix | Delete
return dict
[284] Fix | Delete
[285] Fix | Delete
def _getnamelist(g):
[286] Fix | Delete
# Helper to get a comma-separated list of dotted names plus 'as'
[287] Fix | Delete
# clauses. Return a list of pairs (name, name2) where name2 is
[288] Fix | Delete
# the 'as' name, or None if there is no 'as' clause.
[289] Fix | Delete
names = []
[290] Fix | Delete
while True:
[291] Fix | Delete
name, token = _getname(g)
[292] Fix | Delete
if not name:
[293] Fix | Delete
break
[294] Fix | Delete
if token == 'as':
[295] Fix | Delete
name2, token = _getname(g)
[296] Fix | Delete
else:
[297] Fix | Delete
name2 = None
[298] Fix | Delete
names.append((name, name2))
[299] Fix | Delete
while token != "," and "\n" not in token:
[300] Fix | Delete
token = next(g)[1]
[301] Fix | Delete
if token != ",":
[302] Fix | Delete
break
[303] Fix | Delete
return names
[304] Fix | Delete
[305] Fix | Delete
def _getname(g):
[306] Fix | Delete
# Helper to get a dotted name, return a pair (name, token) where
[307] Fix | Delete
# name is the dotted name, or None if there was no dotted name,
[308] Fix | Delete
# and token is the next input token.
[309] Fix | Delete
parts = []
[310] Fix | Delete
tokentype, token = next(g)[0:2]
[311] Fix | Delete
if tokentype != NAME and token != '*':
[312] Fix | Delete
return (None, token)
[313] Fix | Delete
parts.append(token)
[314] Fix | Delete
while True:
[315] Fix | Delete
tokentype, token = next(g)[0:2]
[316] Fix | Delete
if token != '.':
[317] Fix | Delete
break
[318] Fix | Delete
tokentype, token = next(g)[0:2]
[319] Fix | Delete
if tokentype != NAME:
[320] Fix | Delete
break
[321] Fix | Delete
parts.append(token)
[322] Fix | Delete
return (".".join(parts), token)
[323] Fix | Delete
[324] Fix | Delete
def _main():
[325] Fix | Delete
# Main program for testing.
[326] Fix | Delete
import os
[327] Fix | Delete
from operator import itemgetter
[328] Fix | Delete
mod = sys.argv[1]
[329] Fix | Delete
if os.path.exists(mod):
[330] Fix | Delete
path = [os.path.dirname(mod)]
[331] Fix | Delete
mod = os.path.basename(mod)
[332] Fix | Delete
if mod.lower().endswith(".py"):
[333] Fix | Delete
mod = mod[:-3]
[334] Fix | Delete
else:
[335] Fix | Delete
path = []
[336] Fix | Delete
dict = readmodule_ex(mod, path)
[337] Fix | Delete
objs = list(dict.values())
[338] Fix | Delete
objs.sort(key=lambda a: getattr(a, 'lineno', 0))
[339] Fix | Delete
for obj in objs:
[340] Fix | Delete
if isinstance(obj, Class):
[341] Fix | Delete
print("class", obj.name, obj.super, obj.lineno)
[342] Fix | Delete
methods = sorted(obj.methods.items(), key=itemgetter(1))
[343] Fix | Delete
for name, lineno in methods:
[344] Fix | Delete
if name != "__path__":
[345] Fix | Delete
print(" def", name, lineno)
[346] Fix | Delete
elif isinstance(obj, Function):
[347] Fix | Delete
print("def", obj.name, obj.lineno)
[348] Fix | Delete
[349] Fix | Delete
if __name__ == "__main__":
[350] Fix | Delete
_main()
[351] Fix | Delete
[352] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function