Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../usr/lib64/python3....
File: inspect.py
"""Get useful information from live Python objects.
[0] Fix | Delete
[1] Fix | Delete
This module encapsulates the interface provided by the internal special
[2] Fix | Delete
attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion.
[3] Fix | Delete
It also provides some help for examining source code and class layout.
[4] Fix | Delete
[5] Fix | Delete
Here are some of the useful functions provided by this module:
[6] Fix | Delete
[7] Fix | Delete
ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
[8] Fix | Delete
isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
[9] Fix | Delete
isroutine() - check object types
[10] Fix | Delete
getmembers() - get members of an object that satisfy a given condition
[11] Fix | Delete
[12] Fix | Delete
getfile(), getsourcefile(), getsource() - find an object's source code
[13] Fix | Delete
getdoc(), getcomments() - get documentation on an object
[14] Fix | Delete
getmodule() - determine the module that an object came from
[15] Fix | Delete
getclasstree() - arrange classes so as to represent their hierarchy
[16] Fix | Delete
[17] Fix | Delete
getargvalues(), getcallargs() - get info about function arguments
[18] Fix | Delete
getfullargspec() - same, with support for Python 3 features
[19] Fix | Delete
formatargspec(), formatargvalues() - format an argument spec
[20] Fix | Delete
getouterframes(), getinnerframes() - get info about frames
[21] Fix | Delete
currentframe() - get the current stack frame
[22] Fix | Delete
stack(), trace() - get info about frames on the stack or in a traceback
[23] Fix | Delete
[24] Fix | Delete
signature() - get a Signature object for the callable
[25] Fix | Delete
"""
[26] Fix | Delete
[27] Fix | Delete
# This module is in the public domain. No warranties.
[28] Fix | Delete
[29] Fix | Delete
__author__ = ('Ka-Ping Yee <ping@lfw.org>',
[30] Fix | Delete
'Yury Selivanov <yselivanov@sprymix.com>')
[31] Fix | Delete
[32] Fix | Delete
import abc
[33] Fix | Delete
import ast
[34] Fix | Delete
import dis
[35] Fix | Delete
import collections.abc
[36] Fix | Delete
import enum
[37] Fix | Delete
import importlib.machinery
[38] Fix | Delete
import itertools
[39] Fix | Delete
import linecache
[40] Fix | Delete
import os
[41] Fix | Delete
import re
[42] Fix | Delete
import sys
[43] Fix | Delete
import tokenize
[44] Fix | Delete
import token
[45] Fix | Delete
import types
[46] Fix | Delete
import warnings
[47] Fix | Delete
import functools
[48] Fix | Delete
import builtins
[49] Fix | Delete
from operator import attrgetter
[50] Fix | Delete
from collections import namedtuple, OrderedDict
[51] Fix | Delete
[52] Fix | Delete
# Create constants for the compiler flags in Include/code.h
[53] Fix | Delete
# We try to get them from dis to avoid duplication
[54] Fix | Delete
mod_dict = globals()
[55] Fix | Delete
for k, v in dis.COMPILER_FLAG_NAMES.items():
[56] Fix | Delete
mod_dict["CO_" + v] = k
[57] Fix | Delete
[58] Fix | Delete
# See Include/object.h
[59] Fix | Delete
TPFLAGS_IS_ABSTRACT = 1 << 20
[60] Fix | Delete
[61] Fix | Delete
# ----------------------------------------------------------- type-checking
[62] Fix | Delete
def ismodule(object):
[63] Fix | Delete
"""Return true if the object is a module.
[64] Fix | Delete
[65] Fix | Delete
Module objects provide these attributes:
[66] Fix | Delete
__cached__ pathname to byte compiled file
[67] Fix | Delete
__doc__ documentation string
[68] Fix | Delete
__file__ filename (missing for built-in modules)"""
[69] Fix | Delete
return isinstance(object, types.ModuleType)
[70] Fix | Delete
[71] Fix | Delete
def isclass(object):
[72] Fix | Delete
"""Return true if the object is a class.
[73] Fix | Delete
[74] Fix | Delete
Class objects provide these attributes:
[75] Fix | Delete
__doc__ documentation string
[76] Fix | Delete
__module__ name of module in which this class was defined"""
[77] Fix | Delete
return isinstance(object, type)
[78] Fix | Delete
[79] Fix | Delete
def ismethod(object):
[80] Fix | Delete
"""Return true if the object is an instance method.
[81] Fix | Delete
[82] Fix | Delete
Instance method objects provide these attributes:
[83] Fix | Delete
__doc__ documentation string
[84] Fix | Delete
__name__ name with which this method was defined
[85] Fix | Delete
__func__ function object containing implementation of method
[86] Fix | Delete
__self__ instance to which this method is bound"""
[87] Fix | Delete
return isinstance(object, types.MethodType)
[88] Fix | Delete
[89] Fix | Delete
def ismethoddescriptor(object):
[90] Fix | Delete
"""Return true if the object is a method descriptor.
[91] Fix | Delete
[92] Fix | Delete
But not if ismethod() or isclass() or isfunction() are true.
[93] Fix | Delete
[94] Fix | Delete
This is new in Python 2.2, and, for example, is true of int.__add__.
[95] Fix | Delete
An object passing this test has a __get__ attribute but not a __set__
[96] Fix | Delete
attribute, but beyond that the set of attributes varies. __name__ is
[97] Fix | Delete
usually sensible, and __doc__ often is.
[98] Fix | Delete
[99] Fix | Delete
Methods implemented via descriptors that also pass one of the other
[100] Fix | Delete
tests return false from the ismethoddescriptor() test, simply because
[101] Fix | Delete
the other tests promise more -- you can, e.g., count on having the
[102] Fix | Delete
__func__ attribute (etc) when an object passes ismethod()."""
[103] Fix | Delete
if isclass(object) or ismethod(object) or isfunction(object):
[104] Fix | Delete
# mutual exclusion
[105] Fix | Delete
return False
[106] Fix | Delete
tp = type(object)
[107] Fix | Delete
return hasattr(tp, "__get__") and not hasattr(tp, "__set__")
[108] Fix | Delete
[109] Fix | Delete
def isdatadescriptor(object):
[110] Fix | Delete
"""Return true if the object is a data descriptor.
[111] Fix | Delete
[112] Fix | Delete
Data descriptors have both a __get__ and a __set__ attribute. Examples are
[113] Fix | Delete
properties (defined in Python) and getsets and members (defined in C).
[114] Fix | Delete
Typically, data descriptors will also have __name__ and __doc__ attributes
[115] Fix | Delete
(properties, getsets, and members have both of these attributes), but this
[116] Fix | Delete
is not guaranteed."""
[117] Fix | Delete
if isclass(object) or ismethod(object) or isfunction(object):
[118] Fix | Delete
# mutual exclusion
[119] Fix | Delete
return False
[120] Fix | Delete
tp = type(object)
[121] Fix | Delete
return hasattr(tp, "__set__") and hasattr(tp, "__get__")
[122] Fix | Delete
[123] Fix | Delete
if hasattr(types, 'MemberDescriptorType'):
[124] Fix | Delete
# CPython and equivalent
[125] Fix | Delete
def ismemberdescriptor(object):
[126] Fix | Delete
"""Return true if the object is a member descriptor.
[127] Fix | Delete
[128] Fix | Delete
Member descriptors are specialized descriptors defined in extension
[129] Fix | Delete
modules."""
[130] Fix | Delete
return isinstance(object, types.MemberDescriptorType)
[131] Fix | Delete
else:
[132] Fix | Delete
# Other implementations
[133] Fix | Delete
def ismemberdescriptor(object):
[134] Fix | Delete
"""Return true if the object is a member descriptor.
[135] Fix | Delete
[136] Fix | Delete
Member descriptors are specialized descriptors defined in extension
[137] Fix | Delete
modules."""
[138] Fix | Delete
return False
[139] Fix | Delete
[140] Fix | Delete
if hasattr(types, 'GetSetDescriptorType'):
[141] Fix | Delete
# CPython and equivalent
[142] Fix | Delete
def isgetsetdescriptor(object):
[143] Fix | Delete
"""Return true if the object is a getset descriptor.
[144] Fix | Delete
[145] Fix | Delete
getset descriptors are specialized descriptors defined in extension
[146] Fix | Delete
modules."""
[147] Fix | Delete
return isinstance(object, types.GetSetDescriptorType)
[148] Fix | Delete
else:
[149] Fix | Delete
# Other implementations
[150] Fix | Delete
def isgetsetdescriptor(object):
[151] Fix | Delete
"""Return true if the object is a getset descriptor.
[152] Fix | Delete
[153] Fix | Delete
getset descriptors are specialized descriptors defined in extension
[154] Fix | Delete
modules."""
[155] Fix | Delete
return False
[156] Fix | Delete
[157] Fix | Delete
def isfunction(object):
[158] Fix | Delete
"""Return true if the object is a user-defined function.
[159] Fix | Delete
[160] Fix | Delete
Function objects provide these attributes:
[161] Fix | Delete
__doc__ documentation string
[162] Fix | Delete
__name__ name with which this function was defined
[163] Fix | Delete
__code__ code object containing compiled function bytecode
[164] Fix | Delete
__defaults__ tuple of any default values for arguments
[165] Fix | Delete
__globals__ global namespace in which this function was defined
[166] Fix | Delete
__annotations__ dict of parameter annotations
[167] Fix | Delete
__kwdefaults__ dict of keyword only parameters with defaults"""
[168] Fix | Delete
return isinstance(object, types.FunctionType)
[169] Fix | Delete
[170] Fix | Delete
def isgeneratorfunction(object):
[171] Fix | Delete
"""Return true if the object is a user-defined generator function.
[172] Fix | Delete
[173] Fix | Delete
Generator function objects provide the same attributes as functions.
[174] Fix | Delete
See help(isfunction) for a list of attributes."""
[175] Fix | Delete
return bool((isfunction(object) or ismethod(object)) and
[176] Fix | Delete
object.__code__.co_flags & CO_GENERATOR)
[177] Fix | Delete
[178] Fix | Delete
def iscoroutinefunction(object):
[179] Fix | Delete
"""Return true if the object is a coroutine function.
[180] Fix | Delete
[181] Fix | Delete
Coroutine functions are defined with "async def" syntax.
[182] Fix | Delete
"""
[183] Fix | Delete
return bool((isfunction(object) or ismethod(object)) and
[184] Fix | Delete
object.__code__.co_flags & CO_COROUTINE)
[185] Fix | Delete
[186] Fix | Delete
def isasyncgenfunction(object):
[187] Fix | Delete
"""Return true if the object is an asynchronous generator function.
[188] Fix | Delete
[189] Fix | Delete
Asynchronous generator functions are defined with "async def"
[190] Fix | Delete
syntax and have "yield" expressions in their body.
[191] Fix | Delete
"""
[192] Fix | Delete
return bool((isfunction(object) or ismethod(object)) and
[193] Fix | Delete
object.__code__.co_flags & CO_ASYNC_GENERATOR)
[194] Fix | Delete
[195] Fix | Delete
def isasyncgen(object):
[196] Fix | Delete
"""Return true if the object is an asynchronous generator."""
[197] Fix | Delete
return isinstance(object, types.AsyncGeneratorType)
[198] Fix | Delete
[199] Fix | Delete
def isgenerator(object):
[200] Fix | Delete
"""Return true if the object is a generator.
[201] Fix | Delete
[202] Fix | Delete
Generator objects provide these attributes:
[203] Fix | Delete
__iter__ defined to support iteration over container
[204] Fix | Delete
close raises a new GeneratorExit exception inside the
[205] Fix | Delete
generator to terminate the iteration
[206] Fix | Delete
gi_code code object
[207] Fix | Delete
gi_frame frame object or possibly None once the generator has
[208] Fix | Delete
been exhausted
[209] Fix | Delete
gi_running set to 1 when generator is executing, 0 otherwise
[210] Fix | Delete
next return the next item from the container
[211] Fix | Delete
send resumes the generator and "sends" a value that becomes
[212] Fix | Delete
the result of the current yield-expression
[213] Fix | Delete
throw used to raise an exception inside the generator"""
[214] Fix | Delete
return isinstance(object, types.GeneratorType)
[215] Fix | Delete
[216] Fix | Delete
def iscoroutine(object):
[217] Fix | Delete
"""Return true if the object is a coroutine."""
[218] Fix | Delete
return isinstance(object, types.CoroutineType)
[219] Fix | Delete
[220] Fix | Delete
def isawaitable(object):
[221] Fix | Delete
"""Return true if object can be passed to an ``await`` expression."""
[222] Fix | Delete
return (isinstance(object, types.CoroutineType) or
[223] Fix | Delete
isinstance(object, types.GeneratorType) and
[224] Fix | Delete
bool(object.gi_code.co_flags & CO_ITERABLE_COROUTINE) or
[225] Fix | Delete
isinstance(object, collections.abc.Awaitable))
[226] Fix | Delete
[227] Fix | Delete
def istraceback(object):
[228] Fix | Delete
"""Return true if the object is a traceback.
[229] Fix | Delete
[230] Fix | Delete
Traceback objects provide these attributes:
[231] Fix | Delete
tb_frame frame object at this level
[232] Fix | Delete
tb_lasti index of last attempted instruction in bytecode
[233] Fix | Delete
tb_lineno current line number in Python source code
[234] Fix | Delete
tb_next next inner traceback object (called by this level)"""
[235] Fix | Delete
return isinstance(object, types.TracebackType)
[236] Fix | Delete
[237] Fix | Delete
def isframe(object):
[238] Fix | Delete
"""Return true if the object is a frame object.
[239] Fix | Delete
[240] Fix | Delete
Frame objects provide these attributes:
[241] Fix | Delete
f_back next outer frame object (this frame's caller)
[242] Fix | Delete
f_builtins built-in namespace seen by this frame
[243] Fix | Delete
f_code code object being executed in this frame
[244] Fix | Delete
f_globals global namespace seen by this frame
[245] Fix | Delete
f_lasti index of last attempted instruction in bytecode
[246] Fix | Delete
f_lineno current line number in Python source code
[247] Fix | Delete
f_locals local namespace seen by this frame
[248] Fix | Delete
f_trace tracing function for this frame, or None"""
[249] Fix | Delete
return isinstance(object, types.FrameType)
[250] Fix | Delete
[251] Fix | Delete
def iscode(object):
[252] Fix | Delete
"""Return true if the object is a code object.
[253] Fix | Delete
[254] Fix | Delete
Code objects provide these attributes:
[255] Fix | Delete
co_argcount number of arguments (not including *, ** args
[256] Fix | Delete
or keyword only arguments)
[257] Fix | Delete
co_code string of raw compiled bytecode
[258] Fix | Delete
co_cellvars tuple of names of cell variables
[259] Fix | Delete
co_consts tuple of constants used in the bytecode
[260] Fix | Delete
co_filename name of file in which this code object was created
[261] Fix | Delete
co_firstlineno number of first line in Python source code
[262] Fix | Delete
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
[263] Fix | Delete
| 16=nested | 32=generator | 64=nofree | 128=coroutine
[264] Fix | Delete
| 256=iterable_coroutine | 512=async_generator
[265] Fix | Delete
co_freevars tuple of names of free variables
[266] Fix | Delete
co_kwonlyargcount number of keyword only arguments (not including ** arg)
[267] Fix | Delete
co_lnotab encoded mapping of line numbers to bytecode indices
[268] Fix | Delete
co_name name with which this code object was defined
[269] Fix | Delete
co_names tuple of names of local variables
[270] Fix | Delete
co_nlocals number of local variables
[271] Fix | Delete
co_stacksize virtual machine stack space required
[272] Fix | Delete
co_varnames tuple of names of arguments and local variables"""
[273] Fix | Delete
return isinstance(object, types.CodeType)
[274] Fix | Delete
[275] Fix | Delete
def isbuiltin(object):
[276] Fix | Delete
"""Return true if the object is a built-in function or method.
[277] Fix | Delete
[278] Fix | Delete
Built-in functions and methods provide these attributes:
[279] Fix | Delete
__doc__ documentation string
[280] Fix | Delete
__name__ original name of this function or method
[281] Fix | Delete
__self__ instance to which a method is bound, or None"""
[282] Fix | Delete
return isinstance(object, types.BuiltinFunctionType)
[283] Fix | Delete
[284] Fix | Delete
def isroutine(object):
[285] Fix | Delete
"""Return true if the object is any kind of function or method."""
[286] Fix | Delete
return (isbuiltin(object)
[287] Fix | Delete
or isfunction(object)
[288] Fix | Delete
or ismethod(object)
[289] Fix | Delete
or ismethoddescriptor(object))
[290] Fix | Delete
[291] Fix | Delete
def isabstract(object):
[292] Fix | Delete
"""Return true if the object is an abstract base class (ABC)."""
[293] Fix | Delete
if not isinstance(object, type):
[294] Fix | Delete
return False
[295] Fix | Delete
if object.__flags__ & TPFLAGS_IS_ABSTRACT:
[296] Fix | Delete
return True
[297] Fix | Delete
if not issubclass(type(object), abc.ABCMeta):
[298] Fix | Delete
return False
[299] Fix | Delete
if hasattr(object, '__abstractmethods__'):
[300] Fix | Delete
# It looks like ABCMeta.__new__ has finished running;
[301] Fix | Delete
# TPFLAGS_IS_ABSTRACT should have been accurate.
[302] Fix | Delete
return False
[303] Fix | Delete
# It looks like ABCMeta.__new__ has not finished running yet; we're
[304] Fix | Delete
# probably in __init_subclass__. We'll look for abstractmethods manually.
[305] Fix | Delete
for name, value in object.__dict__.items():
[306] Fix | Delete
if getattr(value, "__isabstractmethod__", False):
[307] Fix | Delete
return True
[308] Fix | Delete
for base in object.__bases__:
[309] Fix | Delete
for name in getattr(base, "__abstractmethods__", ()):
[310] Fix | Delete
value = getattr(object, name, None)
[311] Fix | Delete
if getattr(value, "__isabstractmethod__", False):
[312] Fix | Delete
return True
[313] Fix | Delete
return False
[314] Fix | Delete
[315] Fix | Delete
def getmembers(object, predicate=None):
[316] Fix | Delete
"""Return all members of an object as (name, value) pairs sorted by name.
[317] Fix | Delete
Optionally, only return members that satisfy a given predicate."""
[318] Fix | Delete
if isclass(object):
[319] Fix | Delete
mro = (object,) + getmro(object)
[320] Fix | Delete
else:
[321] Fix | Delete
mro = ()
[322] Fix | Delete
results = []
[323] Fix | Delete
processed = set()
[324] Fix | Delete
names = dir(object)
[325] Fix | Delete
# :dd any DynamicClassAttributes to the list of names if object is a class;
[326] Fix | Delete
# this may result in duplicate entries if, for example, a virtual
[327] Fix | Delete
# attribute with the same name as a DynamicClassAttribute exists
[328] Fix | Delete
try:
[329] Fix | Delete
for base in object.__bases__:
[330] Fix | Delete
for k, v in base.__dict__.items():
[331] Fix | Delete
if isinstance(v, types.DynamicClassAttribute):
[332] Fix | Delete
names.append(k)
[333] Fix | Delete
except AttributeError:
[334] Fix | Delete
pass
[335] Fix | Delete
for key in names:
[336] Fix | Delete
# First try to get the value via getattr. Some descriptors don't
[337] Fix | Delete
# like calling their __get__ (see bug #1785), so fall back to
[338] Fix | Delete
# looking in the __dict__.
[339] Fix | Delete
try:
[340] Fix | Delete
value = getattr(object, key)
[341] Fix | Delete
# handle the duplicate key
[342] Fix | Delete
if key in processed:
[343] Fix | Delete
raise AttributeError
[344] Fix | Delete
except AttributeError:
[345] Fix | Delete
for base in mro:
[346] Fix | Delete
if key in base.__dict__:
[347] Fix | Delete
value = base.__dict__[key]
[348] Fix | Delete
break
[349] Fix | Delete
else:
[350] Fix | Delete
# could be a (currently) missing slot member, or a buggy
[351] Fix | Delete
# __dir__; discard and move on
[352] Fix | Delete
continue
[353] Fix | Delete
if not predicate or predicate(value):
[354] Fix | Delete
results.append((key, value))
[355] Fix | Delete
processed.add(key)
[356] Fix | Delete
results.sort(key=lambda pair: pair[0])
[357] Fix | Delete
return results
[358] Fix | Delete
[359] Fix | Delete
Attribute = namedtuple('Attribute', 'name kind defining_class object')
[360] Fix | Delete
[361] Fix | Delete
def classify_class_attrs(cls):
[362] Fix | Delete
"""Return list of attribute-descriptor tuples.
[363] Fix | Delete
[364] Fix | Delete
For each name in dir(cls), the return list contains a 4-tuple
[365] Fix | Delete
with these elements:
[366] Fix | Delete
[367] Fix | Delete
0. The name (a string).
[368] Fix | Delete
[369] Fix | Delete
1. The kind of attribute this is, one of these strings:
[370] Fix | Delete
'class method' created via classmethod()
[371] Fix | Delete
'static method' created via staticmethod()
[372] Fix | Delete
'property' created via property()
[373] Fix | Delete
'method' any other flavor of method or descriptor
[374] Fix | Delete
'data' not a method
[375] Fix | Delete
[376] Fix | Delete
2. The class which defined this attribute (a class).
[377] Fix | Delete
[378] Fix | Delete
3. The object as obtained by calling getattr; if this fails, or if the
[379] Fix | Delete
resulting object does not live anywhere in the class' mro (including
[380] Fix | Delete
metaclasses) then the object is looked up in the defining class's
[381] Fix | Delete
dict (found by walking the mro).
[382] Fix | Delete
[383] Fix | Delete
If one of the items in dir(cls) is stored in the metaclass it will now
[384] Fix | Delete
be discovered and not have None be listed as the class in which it was
[385] Fix | Delete
defined. Any items whose home class cannot be discovered are skipped.
[386] Fix | Delete
"""
[387] Fix | Delete
[388] Fix | Delete
mro = getmro(cls)
[389] Fix | Delete
metamro = getmro(type(cls)) # for attributes stored in the metaclass
[390] Fix | Delete
metamro = tuple([cls for cls in metamro if cls not in (type, object)])
[391] Fix | Delete
class_bases = (cls,) + mro
[392] Fix | Delete
all_bases = class_bases + metamro
[393] Fix | Delete
names = dir(cls)
[394] Fix | Delete
# :dd any DynamicClassAttributes to the list of names;
[395] Fix | Delete
# this may result in duplicate entries if, for example, a virtual
[396] Fix | Delete
# attribute with the same name as a DynamicClassAttribute exists.
[397] Fix | Delete
for base in mro:
[398] Fix | Delete
for k, v in base.__dict__.items():
[399] Fix | Delete
if isinstance(v, types.DynamicClassAttribute):
[400] Fix | Delete
names.append(k)
[401] Fix | Delete
result = []
[402] Fix | Delete
processed = set()
[403] Fix | Delete
[404] Fix | Delete
for name in names:
[405] Fix | Delete
# Get the object associated with the name, and where it was defined.
[406] Fix | Delete
# Normal objects will be looked up with both getattr and directly in
[407] Fix | Delete
# its class' dict (in case getattr fails [bug #1785], and also to look
[408] Fix | Delete
# for a docstring).
[409] Fix | Delete
# For DynamicClassAttributes on the second pass we only look in the
[410] Fix | Delete
# class's dict.
[411] Fix | Delete
#
[412] Fix | Delete
# Getting an obj from the __dict__ sometimes reveals more than
[413] Fix | Delete
# using getattr. Static and class methods are dramatic examples.
[414] Fix | Delete
homecls = None
[415] Fix | Delete
get_obj = None
[416] Fix | Delete
dict_obj = None
[417] Fix | Delete
if name not in processed:
[418] Fix | Delete
try:
[419] Fix | Delete
if name == '__dict__':
[420] Fix | Delete
raise Exception("__dict__ is special, don't want the proxy")
[421] Fix | Delete
get_obj = getattr(cls, name)
[422] Fix | Delete
except Exception as exc:
[423] Fix | Delete
pass
[424] Fix | Delete
else:
[425] Fix | Delete
homecls = getattr(get_obj, "__objclass__", homecls)
[426] Fix | Delete
if homecls not in class_bases:
[427] Fix | Delete
# if the resulting object does not live somewhere in the
[428] Fix | Delete
# mro, drop it and search the mro manually
[429] Fix | Delete
homecls = None
[430] Fix | Delete
last_cls = None
[431] Fix | Delete
# first look in the classes
[432] Fix | Delete
for srch_cls in class_bases:
[433] Fix | Delete
srch_obj = getattr(srch_cls, name, None)
[434] Fix | Delete
if srch_obj is get_obj:
[435] Fix | Delete
last_cls = srch_cls
[436] Fix | Delete
# then check the metaclasses
[437] Fix | Delete
for srch_cls in metamro:
[438] Fix | Delete
try:
[439] Fix | Delete
srch_obj = srch_cls.__getattr__(cls, name)
[440] Fix | Delete
except AttributeError:
[441] Fix | Delete
continue
[442] Fix | Delete
if srch_obj is get_obj:
[443] Fix | Delete
last_cls = srch_cls
[444] Fix | Delete
if last_cls is not None:
[445] Fix | Delete
homecls = last_cls
[446] Fix | Delete
for base in all_bases:
[447] Fix | Delete
if name in base.__dict__:
[448] Fix | Delete
dict_obj = base.__dict__[name]
[449] Fix | Delete
if homecls not in metamro:
[450] Fix | Delete
homecls = base
[451] Fix | Delete
break
[452] Fix | Delete
if homecls is None:
[453] Fix | Delete
# unable to locate the attribute anywhere, most likely due to
[454] Fix | Delete
# buggy custom __dir__; discard and move on
[455] Fix | Delete
continue
[456] Fix | Delete
obj = get_obj if get_obj is not None else dict_obj
[457] Fix | Delete
# Classify the object or its descriptor.
[458] Fix | Delete
if isinstance(dict_obj, staticmethod):
[459] Fix | Delete
kind = "static method"
[460] Fix | Delete
obj = dict_obj
[461] Fix | Delete
elif isinstance(dict_obj, classmethod):
[462] Fix | Delete
kind = "class method"
[463] Fix | Delete
obj = dict_obj
[464] Fix | Delete
elif isinstance(dict_obj, property):
[465] Fix | Delete
kind = "property"
[466] Fix | Delete
obj = dict_obj
[467] Fix | Delete
elif isroutine(obj):
[468] Fix | Delete
kind = "method"
[469] Fix | Delete
else:
[470] Fix | Delete
kind = "data"
[471] Fix | Delete
result.append(Attribute(name, kind, homecls, obj))
[472] Fix | Delete
processed.add(name)
[473] Fix | Delete
return result
[474] Fix | Delete
[475] Fix | Delete
# ----------------------------------------------------------- class helpers
[476] Fix | Delete
[477] Fix | Delete
def getmro(cls):
[478] Fix | Delete
"Return tuple of base classes (including cls) in method resolution order."
[479] Fix | Delete
return cls.__mro__
[480] Fix | Delete
[481] Fix | Delete
# -------------------------------------------------------- function helpers
[482] Fix | Delete
[483] Fix | Delete
def unwrap(func, *, stop=None):
[484] Fix | Delete
"""Get the object wrapped by *func*.
[485] Fix | Delete
[486] Fix | Delete
Follows the chain of :attr:`__wrapped__` attributes returning the last
[487] Fix | Delete
object in the chain.
[488] Fix | Delete
[489] Fix | Delete
*stop* is an optional callback accepting an object in the wrapper chain
[490] Fix | Delete
as its sole argument that allows the unwrapping to be terminated early if
[491] Fix | Delete
the callback returns a true value. If the callback never returns a true
[492] Fix | Delete
value, the last object in the chain is returned as usual. For example,
[493] Fix | Delete
:func:`signature` uses this to stop unwrapping if any object in the
[494] Fix | Delete
chain has a ``__signature__`` attribute defined.
[495] Fix | Delete
[496] Fix | Delete
:exc:`ValueError` is raised if a cycle is encountered.
[497] Fix | Delete
[498] Fix | Delete
"""
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function