Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../opt/imh-pyth.../lib/python3....
File: pyclbr.py
"""Parse a Python module and describe its classes and functions.
[0] Fix | Delete
[1] Fix | Delete
Parse enough of a Python file to recognize imports and class and
[2] Fix | Delete
function 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=None)
[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 value
[9] Fix | Delete
is a dictionary. The keys of the dictionary are the names of the
[10] Fix | Delete
classes and functions defined in the module (including classes that are
[11] Fix | Delete
defined via the from XXX import YYY construct). The values are
[12] Fix | Delete
instances of classes Class and Function. One special key/value pair is
[13] Fix | Delete
present for packages: the key '__path__' has a list as its value which
[14] Fix | Delete
contains the package search path.
[15] Fix | Delete
[16] Fix | Delete
Classes and Functions have a common superclass: _Object. Every instance
[17] Fix | Delete
has the following attributes:
[18] Fix | Delete
module -- name of the module;
[19] Fix | Delete
name -- name of the object;
[20] Fix | Delete
file -- file in which the object is defined;
[21] Fix | Delete
lineno -- line in the file where the object's definition starts;
[22] Fix | Delete
parent -- parent of this object, if any;
[23] Fix | Delete
children -- nested objects contained in this object.
[24] Fix | Delete
The 'children' attribute is a dictionary mapping names to objects.
[25] Fix | Delete
[26] Fix | Delete
Instances of Function describe functions with the attributes from _Object.
[27] Fix | Delete
[28] Fix | Delete
Instances of Class describe classes with the attributes from _Object,
[29] Fix | Delete
plus the following:
[30] Fix | Delete
super -- list of super classes (Class instances if possible);
[31] Fix | Delete
methods -- mapping of method names to beginning line numbers.
[32] Fix | Delete
If the name of a super class is not recognized, the corresponding
[33] Fix | Delete
entry in the list of super classes is not a class instance but a
[34] Fix | Delete
string giving the name of the super class. Since import statements
[35] Fix | Delete
are recognized and imported modules are scanned as well, this
[36] Fix | Delete
shouldn't happen often.
[37] Fix | Delete
"""
[38] Fix | Delete
[39] Fix | Delete
import io
[40] Fix | Delete
import sys
[41] Fix | Delete
import importlib.util
[42] Fix | Delete
import tokenize
[43] Fix | Delete
from token import NAME, DEDENT, OP
[44] Fix | Delete
[45] Fix | Delete
__all__ = ["readmodule", "readmodule_ex", "Class", "Function"]
[46] Fix | Delete
[47] Fix | Delete
_modules = {} # Initialize cache of modules we've seen.
[48] Fix | Delete
[49] Fix | Delete
[50] Fix | Delete
class _Object:
[51] Fix | Delete
"Information about Python class or function."
[52] Fix | Delete
def __init__(self, module, name, file, lineno, parent):
[53] Fix | Delete
self.module = module
[54] Fix | Delete
self.name = name
[55] Fix | Delete
self.file = file
[56] Fix | Delete
self.lineno = lineno
[57] Fix | Delete
self.parent = parent
[58] Fix | Delete
self.children = {}
[59] Fix | Delete
[60] Fix | Delete
def _addchild(self, name, obj):
[61] Fix | Delete
self.children[name] = obj
[62] Fix | Delete
[63] Fix | Delete
[64] Fix | Delete
class Function(_Object):
[65] Fix | Delete
"Information about a Python function, including methods."
[66] Fix | Delete
def __init__(self, module, name, file, lineno, parent=None):
[67] Fix | Delete
_Object.__init__(self, module, name, file, lineno, parent)
[68] Fix | Delete
[69] Fix | Delete
[70] Fix | Delete
class Class(_Object):
[71] Fix | Delete
"Information about a Python class."
[72] Fix | Delete
def __init__(self, module, name, super, file, lineno, parent=None):
[73] Fix | Delete
_Object.__init__(self, module, name, file, lineno, parent)
[74] Fix | Delete
self.super = [] if super is None else super
[75] Fix | Delete
self.methods = {}
[76] Fix | Delete
[77] Fix | Delete
def _addmethod(self, name, lineno):
[78] Fix | Delete
self.methods[name] = lineno
[79] Fix | Delete
[80] Fix | Delete
[81] Fix | Delete
def _nest_function(ob, func_name, lineno):
[82] Fix | Delete
"Return a Function after nesting within ob."
[83] Fix | Delete
newfunc = Function(ob.module, func_name, ob.file, lineno, ob)
[84] Fix | Delete
ob._addchild(func_name, newfunc)
[85] Fix | Delete
if isinstance(ob, Class):
[86] Fix | Delete
ob._addmethod(func_name, lineno)
[87] Fix | Delete
return newfunc
[88] Fix | Delete
[89] Fix | Delete
def _nest_class(ob, class_name, lineno, super=None):
[90] Fix | Delete
"Return a Class after nesting within ob."
[91] Fix | Delete
newclass = Class(ob.module, class_name, super, ob.file, lineno, ob)
[92] Fix | Delete
ob._addchild(class_name, newclass)
[93] Fix | Delete
return newclass
[94] Fix | Delete
[95] Fix | Delete
def readmodule(module, path=None):
[96] Fix | Delete
"""Return Class objects for the top-level classes in module.
[97] Fix | Delete
[98] Fix | Delete
This is the original interface, before Functions were added.
[99] Fix | Delete
"""
[100] Fix | Delete
[101] Fix | Delete
res = {}
[102] Fix | Delete
for key, value in _readmodule(module, path or []).items():
[103] Fix | Delete
if isinstance(value, Class):
[104] Fix | Delete
res[key] = value
[105] Fix | Delete
return res
[106] Fix | Delete
[107] Fix | Delete
def readmodule_ex(module, path=None):
[108] Fix | Delete
"""Return a dictionary with all functions and classes in module.
[109] Fix | Delete
[110] Fix | Delete
Search for module in PATH + sys.path.
[111] Fix | Delete
If possible, include imported superclasses.
[112] Fix | Delete
Do this by reading source, without importing (and executing) it.
[113] Fix | Delete
"""
[114] Fix | Delete
return _readmodule(module, path or [])
[115] Fix | Delete
[116] Fix | Delete
def _readmodule(module, path, inpackage=None):
[117] Fix | Delete
"""Do the hard work for readmodule[_ex].
[118] Fix | Delete
[119] Fix | Delete
If inpackage is given, it must be the dotted name of the package in
[120] Fix | Delete
which we are searching for a submodule, and then PATH must be the
[121] Fix | Delete
package search path; otherwise, we are searching for a top-level
[122] Fix | Delete
module, and path is combined with sys.path.
[123] Fix | Delete
"""
[124] Fix | Delete
# Compute the full module name (prepending inpackage if set).
[125] Fix | Delete
if inpackage is not None:
[126] Fix | Delete
fullmodule = "%s.%s" % (inpackage, module)
[127] Fix | Delete
else:
[128] Fix | Delete
fullmodule = module
[129] Fix | Delete
[130] Fix | Delete
# Check in the cache.
[131] Fix | Delete
if fullmodule in _modules:
[132] Fix | Delete
return _modules[fullmodule]
[133] Fix | Delete
[134] Fix | Delete
# Initialize the dict for this module's contents.
[135] Fix | Delete
tree = {}
[136] Fix | Delete
[137] Fix | Delete
# Check if it is a built-in module; we don't do much for these.
[138] Fix | Delete
if module in sys.builtin_module_names and inpackage is None:
[139] Fix | Delete
_modules[module] = tree
[140] Fix | Delete
return tree
[141] Fix | Delete
[142] Fix | Delete
# Check for a dotted module name.
[143] Fix | Delete
i = module.rfind('.')
[144] Fix | Delete
if i >= 0:
[145] Fix | Delete
package = module[:i]
[146] Fix | Delete
submodule = module[i+1:]
[147] Fix | Delete
parent = _readmodule(package, path, inpackage)
[148] Fix | Delete
if inpackage is not None:
[149] Fix | Delete
package = "%s.%s" % (inpackage, package)
[150] Fix | Delete
if not '__path__' in parent:
[151] Fix | Delete
raise ImportError('No package named {}'.format(package))
[152] Fix | Delete
return _readmodule(submodule, parent['__path__'], package)
[153] Fix | Delete
[154] Fix | Delete
# Search the path for the module.
[155] Fix | Delete
f = None
[156] Fix | Delete
if inpackage is not None:
[157] Fix | Delete
search_path = path
[158] Fix | Delete
else:
[159] Fix | Delete
search_path = path + sys.path
[160] Fix | Delete
spec = importlib.util._find_spec_from_path(fullmodule, search_path)
[161] Fix | Delete
if spec is None:
[162] Fix | Delete
raise ModuleNotFoundError(f"no module named {fullmodule!r}", name=fullmodule)
[163] Fix | Delete
_modules[fullmodule] = tree
[164] Fix | Delete
# Is module a package?
[165] Fix | Delete
if spec.submodule_search_locations is not None:
[166] Fix | Delete
tree['__path__'] = spec.submodule_search_locations
[167] Fix | Delete
try:
[168] Fix | Delete
source = spec.loader.get_source(fullmodule)
[169] Fix | Delete
except (AttributeError, ImportError):
[170] Fix | Delete
# If module is not Python source, we cannot do anything.
[171] Fix | Delete
return tree
[172] Fix | Delete
else:
[173] Fix | Delete
if source is None:
[174] Fix | Delete
return tree
[175] Fix | Delete
[176] Fix | Delete
fname = spec.loader.get_filename(fullmodule)
[177] Fix | Delete
return _create_tree(fullmodule, path, fname, source, tree, inpackage)
[178] Fix | Delete
[179] Fix | Delete
[180] Fix | Delete
def _create_tree(fullmodule, path, fname, source, tree, inpackage):
[181] Fix | Delete
"""Return the tree for a particular module.
[182] Fix | Delete
[183] Fix | Delete
fullmodule (full module name), inpackage+module, becomes o.module.
[184] Fix | Delete
path is passed to recursive calls of _readmodule.
[185] Fix | Delete
fname becomes o.file.
[186] Fix | Delete
source is tokenized. Imports cause recursive calls to _readmodule.
[187] Fix | Delete
tree is {} or {'__path__': <submodule search locations>}.
[188] Fix | Delete
inpackage, None or string, is passed to recursive calls of _readmodule.
[189] Fix | Delete
[190] Fix | Delete
The effect of recursive calls is mutation of global _modules.
[191] Fix | Delete
"""
[192] Fix | Delete
f = io.StringIO(source)
[193] Fix | Delete
[194] Fix | Delete
stack = [] # Initialize stack of (class, indent) pairs.
[195] Fix | Delete
[196] Fix | Delete
g = tokenize.generate_tokens(f.readline)
[197] Fix | Delete
try:
[198] Fix | Delete
for tokentype, token, start, _end, _line in g:
[199] Fix | Delete
if tokentype == DEDENT:
[200] Fix | Delete
lineno, thisindent = start
[201] Fix | Delete
# Close previous nested classes and defs.
[202] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[203] Fix | Delete
del stack[-1]
[204] Fix | Delete
elif token == 'def':
[205] Fix | Delete
lineno, thisindent = start
[206] Fix | Delete
# Close previous nested classes and defs.
[207] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[208] Fix | Delete
del stack[-1]
[209] Fix | Delete
tokentype, func_name, start = next(g)[0:3]
[210] Fix | Delete
if tokentype != NAME:
[211] Fix | Delete
continue # Skip def with syntax error.
[212] Fix | Delete
cur_func = None
[213] Fix | Delete
if stack:
[214] Fix | Delete
cur_obj = stack[-1][0]
[215] Fix | Delete
cur_func = _nest_function(cur_obj, func_name, lineno)
[216] Fix | Delete
else:
[217] Fix | Delete
# It is just a function.
[218] Fix | Delete
cur_func = Function(fullmodule, func_name, fname, lineno)
[219] Fix | Delete
tree[func_name] = cur_func
[220] Fix | Delete
stack.append((cur_func, thisindent))
[221] Fix | Delete
elif token == 'class':
[222] Fix | Delete
lineno, thisindent = start
[223] Fix | Delete
# Close previous nested classes and defs.
[224] Fix | Delete
while stack and stack[-1][1] >= thisindent:
[225] Fix | Delete
del stack[-1]
[226] Fix | Delete
tokentype, class_name, start = next(g)[0:3]
[227] Fix | Delete
if tokentype != NAME:
[228] Fix | Delete
continue # Skip class with syntax error.
[229] Fix | Delete
# Parse what follows the class name.
[230] Fix | Delete
tokentype, token, start = next(g)[0:3]
[231] Fix | Delete
inherit = None
[232] Fix | Delete
if token == '(':
[233] Fix | Delete
names = [] # Initialize list of superclasses.
[234] Fix | Delete
level = 1
[235] Fix | Delete
super = [] # Tokens making up current superclass.
[236] Fix | Delete
while True:
[237] Fix | Delete
tokentype, token, start = next(g)[0:3]
[238] Fix | Delete
if token in (')', ',') and level == 1:
[239] Fix | Delete
n = "".join(super)
[240] Fix | Delete
if n in tree:
[241] Fix | Delete
# We know this super class.
[242] Fix | Delete
n = tree[n]
[243] Fix | Delete
else:
[244] Fix | Delete
c = n.split('.')
[245] Fix | Delete
if len(c) > 1:
[246] Fix | Delete
# Super class form is module.class:
[247] Fix | Delete
# look in module for class.
[248] Fix | Delete
m = c[-2]
[249] Fix | Delete
c = c[-1]
[250] Fix | Delete
if m in _modules:
[251] Fix | Delete
d = _modules[m]
[252] Fix | Delete
if c in d:
[253] Fix | Delete
n = d[c]
[254] Fix | Delete
names.append(n)
[255] Fix | Delete
super = []
[256] Fix | Delete
if token == '(':
[257] Fix | Delete
level += 1
[258] Fix | Delete
elif token == ')':
[259] Fix | Delete
level -= 1
[260] Fix | Delete
if level == 0:
[261] Fix | Delete
break
[262] Fix | Delete
elif token == ',' and level == 1:
[263] Fix | Delete
pass
[264] Fix | Delete
# Only use NAME and OP (== dot) tokens for type name.
[265] Fix | Delete
elif tokentype in (NAME, OP) and level == 1:
[266] Fix | Delete
super.append(token)
[267] Fix | Delete
# Expressions in the base list are not supported.
[268] Fix | Delete
inherit = names
[269] Fix | Delete
if stack:
[270] Fix | Delete
cur_obj = stack[-1][0]
[271] Fix | Delete
cur_class = _nest_class(
[272] Fix | Delete
cur_obj, class_name, lineno, inherit)
[273] Fix | Delete
else:
[274] Fix | Delete
cur_class = Class(fullmodule, class_name, inherit,
[275] Fix | Delete
fname, lineno)
[276] Fix | Delete
tree[class_name] = cur_class
[277] Fix | Delete
stack.append((cur_class, thisindent))
[278] Fix | Delete
elif token == 'import' and start[1] == 0:
[279] Fix | Delete
modules = _getnamelist(g)
[280] Fix | Delete
for mod, _mod2 in modules:
[281] Fix | Delete
try:
[282] Fix | Delete
# Recursively read the imported module.
[283] Fix | Delete
if inpackage is None:
[284] Fix | Delete
_readmodule(mod, path)
[285] Fix | Delete
else:
[286] Fix | Delete
try:
[287] Fix | Delete
_readmodule(mod, path, inpackage)
[288] Fix | Delete
except ImportError:
[289] Fix | Delete
_readmodule(mod, [])
[290] Fix | Delete
except:
[291] Fix | Delete
# If we can't find or parse the imported module,
[292] Fix | Delete
# too bad -- don't die here.
[293] Fix | Delete
pass
[294] Fix | Delete
elif token == 'from' and start[1] == 0:
[295] Fix | Delete
mod, token = _getname(g)
[296] Fix | Delete
if not mod or token != "import":
[297] Fix | Delete
continue
[298] Fix | Delete
names = _getnamelist(g)
[299] Fix | Delete
try:
[300] Fix | Delete
# Recursively read the imported module.
[301] Fix | Delete
d = _readmodule(mod, path, inpackage)
[302] Fix | Delete
except:
[303] Fix | Delete
# If we can't find or parse the imported module,
[304] Fix | Delete
# too bad -- don't die here.
[305] Fix | Delete
continue
[306] Fix | Delete
# Add any classes that were defined in the imported module
[307] Fix | Delete
# to our name space if they were mentioned in the list.
[308] Fix | Delete
for n, n2 in names:
[309] Fix | Delete
if n in d:
[310] Fix | Delete
tree[n2 or n] = d[n]
[311] Fix | Delete
elif n == '*':
[312] Fix | Delete
# Don't add names that start with _.
[313] Fix | Delete
for n in d:
[314] Fix | Delete
if n[0] != '_':
[315] Fix | Delete
tree[n] = d[n]
[316] Fix | Delete
except StopIteration:
[317] Fix | Delete
pass
[318] Fix | Delete
[319] Fix | Delete
f.close()
[320] Fix | Delete
return tree
[321] Fix | Delete
[322] Fix | Delete
[323] Fix | Delete
def _getnamelist(g):
[324] Fix | Delete
"""Return list of (dotted-name, as-name or None) tuples for token source g.
[325] Fix | Delete
[326] Fix | Delete
An as-name is the name that follows 'as' in an as clause.
[327] Fix | Delete
"""
[328] Fix | Delete
names = []
[329] Fix | Delete
while True:
[330] Fix | Delete
name, token = _getname(g)
[331] Fix | Delete
if not name:
[332] Fix | Delete
break
[333] Fix | Delete
if token == 'as':
[334] Fix | Delete
name2, token = _getname(g)
[335] Fix | Delete
else:
[336] Fix | Delete
name2 = None
[337] Fix | Delete
names.append((name, name2))
[338] Fix | Delete
while token != "," and "\n" not in token:
[339] Fix | Delete
token = next(g)[1]
[340] Fix | Delete
if token != ",":
[341] Fix | Delete
break
[342] Fix | Delete
return names
[343] Fix | Delete
[344] Fix | Delete
[345] Fix | Delete
def _getname(g):
[346] Fix | Delete
"Return (dotted-name or None, next-token) tuple for token source g."
[347] Fix | Delete
parts = []
[348] Fix | Delete
tokentype, token = next(g)[0:2]
[349] Fix | Delete
if tokentype != NAME and token != '*':
[350] Fix | Delete
return (None, token)
[351] Fix | Delete
parts.append(token)
[352] Fix | Delete
while True:
[353] Fix | Delete
tokentype, token = next(g)[0:2]
[354] Fix | Delete
if token != '.':
[355] Fix | Delete
break
[356] Fix | Delete
tokentype, token = next(g)[0:2]
[357] Fix | Delete
if tokentype != NAME:
[358] Fix | Delete
break
[359] Fix | Delete
parts.append(token)
[360] Fix | Delete
return (".".join(parts), token)
[361] Fix | Delete
[362] Fix | Delete
[363] Fix | Delete
def _main():
[364] Fix | Delete
"Print module output (default this file) for quick visual check."
[365] Fix | Delete
import os
[366] Fix | Delete
try:
[367] Fix | Delete
mod = sys.argv[1]
[368] Fix | Delete
except:
[369] Fix | Delete
mod = __file__
[370] Fix | Delete
if os.path.exists(mod):
[371] Fix | Delete
path = [os.path.dirname(mod)]
[372] Fix | Delete
mod = os.path.basename(mod)
[373] Fix | Delete
if mod.lower().endswith(".py"):
[374] Fix | Delete
mod = mod[:-3]
[375] Fix | Delete
else:
[376] Fix | Delete
path = []
[377] Fix | Delete
tree = readmodule_ex(mod, path)
[378] Fix | Delete
lineno_key = lambda a: getattr(a, 'lineno', 0)
[379] Fix | Delete
objs = sorted(tree.values(), key=lineno_key, reverse=True)
[380] Fix | Delete
indent_level = 2
[381] Fix | Delete
while objs:
[382] Fix | Delete
obj = objs.pop()
[383] Fix | Delete
if isinstance(obj, list):
[384] Fix | Delete
# Value is a __path__ key.
[385] Fix | Delete
continue
[386] Fix | Delete
if not hasattr(obj, 'indent'):
[387] Fix | Delete
obj.indent = 0
[388] Fix | Delete
[389] Fix | Delete
if isinstance(obj, _Object):
[390] Fix | Delete
new_objs = sorted(obj.children.values(),
[391] Fix | Delete
key=lineno_key, reverse=True)
[392] Fix | Delete
for ob in new_objs:
[393] Fix | Delete
ob.indent = obj.indent + indent_level
[394] Fix | Delete
objs.extend(new_objs)
[395] Fix | Delete
if isinstance(obj, Class):
[396] Fix | Delete
print("{}class {} {} {}"
[397] Fix | Delete
.format(' ' * obj.indent, obj.name, obj.super, obj.lineno))
[398] Fix | Delete
elif isinstance(obj, Function):
[399] Fix | Delete
print("{}def {} {}".format(' ' * obj.indent, obj.name, obj.lineno))
[400] Fix | Delete
[401] Fix | Delete
if __name__ == "__main__":
[402] Fix | Delete
_main()
[403] Fix | Delete
[404] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function