codekingpro/portable-devtools
114k
1"""Get useful information from live Python objects.2 3This module encapsulates the interface provided by the internal special4attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion.5It also provides some help for examining source code and class layout.6 7Here are some of the useful functions provided by this module:8 9 ismodule(), isclass(), ismethod(), ispackage(), isfunction(),10 isgeneratorfunction(), isgenerator(), istraceback(), isframe(),11 iscode(), isbuiltin(), isroutine() - check object types12 getmembers() - get members of an object that satisfy a given condition13 14 getfile(), getsourcefile(), getsource() - find an object's source code15 getdoc(), getcomments() - get documentation on an object16 getmodule() - determine the module that an object came from17 getclasstree() - arrange classes so as to represent their hierarchy18 19 getargvalues(), getcallargs() - get info about function arguments20 getfullargspec() - same, with support for Python 3 features21 formatargvalues() - format an argument spec22 getouterframes(), getinnerframes() - get info about frames23 currentframe() - get the current stack frame24 stack(), trace() - get info about frames on the stack or in a traceback25 26 signature() - get a Signature object for the callable27"""28 29# This module is in the public domain. No warranties.30 31__author__ = ('Ka-Ping Yee <ping@lfw.org>',32 'Yury Selivanov <yselivanov@sprymix.com>')33 34__all__ = [35 "AGEN_CLOSED",36 "AGEN_CREATED",37 "AGEN_RUNNING",38 "AGEN_SUSPENDED",39 "ArgInfo",40 "Arguments",41 "Attribute",42 "BlockFinder",43 "BoundArguments",44 "BufferFlags",45 "CORO_CLOSED",46 "CORO_CREATED",47 "CORO_RUNNING",48 "CORO_SUSPENDED",49 "CO_ASYNC_GENERATOR",50 "CO_COROUTINE",51 "CO_GENERATOR",52 "CO_ITERABLE_COROUTINE",53 "CO_NESTED",54 "CO_NEWLOCALS",55 "CO_NOFREE",56 "CO_OPTIMIZED",57 "CO_VARARGS",58 "CO_VARKEYWORDS",59 "CO_HAS_DOCSTRING",60 "CO_METHOD",61 "ClassFoundException",62 "ClosureVars",63 "EndOfBlock",64 "FrameInfo",65 "FullArgSpec",66 "GEN_CLOSED",67 "GEN_CREATED",68 "GEN_RUNNING",69 "GEN_SUSPENDED",70 "Parameter",71 "Signature",72 "TPFLAGS_IS_ABSTRACT",73 "Traceback",74 "classify_class_attrs",75 "cleandoc",76 "currentframe",77 "findsource",78 "formatannotation",79 "formatannotationrelativeto",80 "formatargvalues",81 "get_annotations",82 "getabsfile",83 "getargs",84 "getargvalues",85 "getasyncgenlocals",86 "getasyncgenstate",87 "getattr_static",88 "getblock",89 "getcallargs",90 "getclasstree",91 "getclosurevars",92 "getcomments",93 "getcoroutinelocals",94 "getcoroutinestate",95 "getdoc",96 "getfile",97 "getframeinfo",98 "getfullargspec",99 "getgeneratorlocals",100 "getgeneratorstate",101 "getinnerframes",102 "getlineno",103 "getmembers",104 "getmembers_static",105 "getmodule",106 "getmodulename",107 "getmro",108 "getouterframes",109 "getsource",110 "getsourcefile",111 "getsourcelines",112 "indentsize",113 "isabstract",114 "isasyncgen",115 "isasyncgenfunction",116 "isawaitable",117 "isbuiltin",118 "isclass",119 "iscode",120 "iscoroutine",121 "iscoroutinefunction",122 "isdatadescriptor",123 "isframe",124 "isfunction",125 "isgenerator",126 "isgeneratorfunction",127 "isgetsetdescriptor",128 "ismemberdescriptor",129 "ismethod",130 "ismethoddescriptor",131 "ismethodwrapper",132 "ismodule",133 "ispackage",134 "isroutine",135 "istraceback",136 "markcoroutinefunction",137 "signature",138 "stack",139 "trace",140 "unwrap",141 "walktree",142]143 144 145import abc146from annotationlib import Format, ForwardRef147from annotationlib import get_annotations # re-exported148import ast149import dis150import collections.abc151import enum152import importlib.machinery153import itertools154import linecache155import os156import re157import sys158import tokenize159import token160import types161import functools162import builtins163from keyword import iskeyword164from operator import attrgetter165from collections import namedtuple, OrderedDict166from weakref import ref as make_weakref167 168# Create constants for the compiler flags in Include/code.h169# We try to get them from dis to avoid duplication170mod_dict = globals()171for k, v in dis.COMPILER_FLAG_NAMES.items():172 mod_dict["CO_" + v] = k173del k, v, mod_dict174 175# See Include/object.h176TPFLAGS_IS_ABSTRACT = 1 << 20177 178 179# ----------------------------------------------------------- type-checking180def ismodule(object):181 """Return true if the object is a module."""182 return isinstance(object, types.ModuleType)183 184def isclass(object):185 """Return true if the object is a class."""186 return isinstance(object, type)187 188def ismethod(object):189 """Return true if the object is an instance method."""190 return isinstance(object, types.MethodType)191 192def ispackage(object):193 """Return true if the object is a package."""194 return ismodule(object) and hasattr(object, "__path__")195 196def ismethoddescriptor(object):197 """Return true if the object is a method descriptor.198 199 But not if ismethod() or isclass() or isfunction() are true.200 201 This is new in Python 2.2, and, for example, is true of int.__add__.202 An object passing this test has a __get__ attribute, but not a203 __set__ attribute or a __delete__ attribute. Beyond that, the set204 of attributes varies; __name__ is usually sensible, and __doc__205 often is.206 207 Methods implemented via descriptors that also pass one of the other208 tests return false from the ismethoddescriptor() test, simply because209 the other tests promise more -- you can, e.g., count on having the210 __func__ attribute (etc) when an object passes ismethod()."""211 if isclass(object) or ismethod(object) or isfunction(object):212 # mutual exclusion213 return False214 tp = type(object)215 return (hasattr(tp, "__get__")216 and not hasattr(tp, "__set__")217 and not hasattr(tp, "__delete__"))218 219def isdatadescriptor(object):220 """Return true if the object is a data descriptor.221 222 Data descriptors have a __set__ or a __delete__ attribute. Examples are223 properties (defined in Python) and getsets and members (defined in C).224 Typically, data descriptors will also have __name__ and __doc__ attributes225 (properties, getsets, and members have both of these attributes), but this226 is not guaranteed."""227 if isclass(object) or ismethod(object) or isfunction(object):228 # mutual exclusion229 return False230 tp = type(object)231 return hasattr(tp, "__set__") or hasattr(tp, "__delete__")232 233if hasattr(types, 'MemberDescriptorType'):234 # CPython and equivalent235 def ismemberdescriptor(object):236 """Return true if the object is a member descriptor.237 238 Member descriptors are specialized descriptors defined in extension239 modules."""240 return isinstance(object, types.MemberDescriptorType)241else:242 # Other implementations243 def ismemberdescriptor(object):244 """Return true if the object is a member descriptor.245 246 Member descriptors are specialized descriptors defined in extension247 modules."""248 return False249 250if hasattr(types, 'GetSetDescriptorType'):251 # CPython and equivalent252 def isgetsetdescriptor(object):253 """Return true if the object is a getset descriptor.254 255 getset descriptors are specialized descriptors defined in extension256 modules."""257 return isinstance(object, types.GetSetDescriptorType)258else:259 # Other implementations260 def isgetsetdescriptor(object):261 """Return true if the object is a getset descriptor.262 263 getset descriptors are specialized descriptors defined in extension264 modules."""265 return False266 267def isfunction(object):268 """Return true if the object is a user-defined function.269 270 Function objects provide these attributes:271 __doc__ documentation string272 __name__ name with which this function was defined273 __qualname__ qualified name of this function274 __module__ name of the module the function was defined in or None275 __code__ code object containing compiled function bytecode276 __defaults__ tuple of any default values for arguments277 __globals__ global namespace in which this function was defined278 __annotations__ dict of parameter annotations279 __kwdefaults__ dict of keyword only parameters with defaults280 __dict__ namespace which is supporting arbitrary function attributes281 __closure__ a tuple of cells or None282 __type_params__ tuple of type parameters"""283 return isinstance(object, types.FunctionType)284 285def _has_code_flag(f, flag):286 """Return true if ``f`` is a function (or a method or functools.partial287 wrapper wrapping a function or a functools.partialmethod wrapping a288 function) whose code object has the given ``flag``289 set in its flags."""290 f = functools._unwrap_partialmethod(f)291 while ismethod(f):292 f = f.__func__293 f = functools._unwrap_partial(f)294 if not (isfunction(f) or _signature_is_functionlike(f)):295 return False296 return bool(f.__code__.co_flags & flag)297 298def isgeneratorfunction(obj):299 """Return true if the object is a user-defined generator function.300 301 Generator function objects provide the same attributes as functions.302 See help(isfunction) for a list of attributes."""303 return _has_code_flag(obj, CO_GENERATOR)304 305# A marker for markcoroutinefunction and iscoroutinefunction.306_is_coroutine_mark = object()307 308def _has_coroutine_mark(f):309 while ismethod(f):310 f = f.__func__311 f = functools._unwrap_partial(f)312 return getattr(f, "_is_coroutine_marker", None) is _is_coroutine_mark313 314def markcoroutinefunction(func):315 """316 Decorator to ensure callable is recognised as a coroutine function.317 """318 if hasattr(func, '__func__'):319 func = func.__func__320 func._is_coroutine_marker = _is_coroutine_mark321 return func322 323def iscoroutinefunction(obj):324 """Return true if the object is a coroutine function.325 326 Coroutine functions are normally defined with "async def" syntax, but may327 be marked via markcoroutinefunction.328 """329 return _has_code_flag(obj, CO_COROUTINE) or _has_coroutine_mark(obj)330 331def isasyncgenfunction(obj):332 """Return true if the object is an asynchronous generator function.333 334 Asynchronous generator functions are defined with "async def"335 syntax and have "yield" expressions in their body.336 """337 return _has_code_flag(obj, CO_ASYNC_GENERATOR)338 339def isasyncgen(object):340 """Return true if the object is an asynchronous generator."""341 return isinstance(object, types.AsyncGeneratorType)342 343def isgenerator(object):344 """Return true if the object is a generator.345 346 Generator objects provide these attributes:347 gi_code code object348 gi_frame frame object or possibly None once the generator has349 been exhausted350 gi_running set to 1 when generator is executing, 0 otherwise351 gi_suspended set to 1 when the generator is suspended at a yield point, 0 otherwise352 gi_yieldfrom object being iterated by yield from or None353 354 __iter__() defined to support iteration over container355 close() raises a new GeneratorExit exception inside the356 generator to terminate the iteration357 send() resumes the generator and "sends" a value that becomes358 the result of the current yield-expression359 throw() used to raise an exception inside the generator"""360 return isinstance(object, types.GeneratorType)361 362def iscoroutine(object):363 """Return true if the object is a coroutine."""364 return isinstance(object, types.CoroutineType)365 366def isawaitable(object):367 """Return true if object can be passed to an ``await`` expression."""368 return (isinstance(object, types.CoroutineType) or369 isinstance(object, types.GeneratorType) and370 bool(object.gi_code.co_flags & CO_ITERABLE_COROUTINE) or371 isinstance(object, collections.abc.Awaitable))372 373def istraceback(object):374 """Return true if the object is a traceback.375 376 Traceback objects provide these attributes:377 tb_frame frame object at this level378 tb_lasti index of last attempted instruction in bytecode379 tb_lineno current line number in Python source code380 tb_next next inner traceback object (called by this level)"""381 return isinstance(object, types.TracebackType)382 383def isframe(object):384 """Return true if the object is a frame object.385 386 Frame objects provide these attributes:387 f_back next outer frame object (this frame's caller)388 f_builtins built-in namespace seen by this frame389 f_code code object being executed in this frame390 f_globals global namespace seen by this frame391 f_lasti index of last attempted instruction in bytecode392 f_lineno current line number in Python source code393 f_locals local namespace seen by this frame394 f_trace tracing function for this frame, or None395 f_trace_lines is a tracing event triggered for each source line?396 f_trace_opcodes are per-opcode events being requested?397 398 clear() used to clear all references to local variables"""399 return isinstance(object, types.FrameType)400 401def iscode(object):402 """Return true if the object is a code object.403 404 Code objects provide these attributes:405 co_argcount number of arguments (not including *, ** args406 or keyword only arguments)407 co_code string of raw compiled bytecode408 co_cellvars tuple of names of cell variables409 co_consts tuple of constants used in the bytecode410 co_filename name of file in which this code object was created411 co_firstlineno number of first line in Python source code412 co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg413 | 16=nested | 32=generator | 64=nofree | 128=coroutine414 | 256=iterable_coroutine | 512=async_generator415 | 0x4000000=has_docstring416 co_freevars tuple of names of free variables417 co_posonlyargcount number of positional only arguments418 co_kwonlyargcount number of keyword only arguments (not including ** arg)419 co_lnotab encoded mapping of line numbers to bytecode indices420 co_name name with which this code object was defined421 co_names tuple of names other than arguments and function locals422 co_nlocals number of local variables423 co_stacksize virtual machine stack space required424 co_varnames tuple of names of arguments and local variables425 co_qualname fully qualified function name426 427 co_lines() returns an iterator that yields successive bytecode ranges428 co_positions() returns an iterator of source code positions for each bytecode instruction429 replace() returns a copy of the code object with a new values"""430 return isinstance(object, types.CodeType)431 432def isbuiltin(object):433 """Return true if the object is a built-in function or method.434 435 Built-in functions and methods provide these attributes:436 __doc__ documentation string437 __name__ original name of this function or method438 __self__ instance to which a method is bound, or None"""439 return isinstance(object, types.BuiltinFunctionType)440 441def ismethodwrapper(object):442 """Return true if the object is a method wrapper."""443 return isinstance(object, types.MethodWrapperType)444 445def isroutine(object):446 """Return true if the object is any kind of function or method."""447 return (isbuiltin(object)448 or isfunction(object)449 or ismethod(object)450 or ismethoddescriptor(object)451 or ismethodwrapper(object)452 or isinstance(object, functools._singledispatchmethod_get))453 454def isabstract(object):455 """Return true if the object is an abstract base class (ABC)."""456 if not isinstance(object, type):457 return False458 if object.__flags__ & TPFLAGS_IS_ABSTRACT:459 return True460 if not issubclass(type(object), abc.ABCMeta):461 return False462 if hasattr(object, '__abstractmethods__'):463 # It looks like ABCMeta.__new__ has finished running;464 # TPFLAGS_IS_ABSTRACT should have been accurate.465 return False466 # It looks like ABCMeta.__new__ has not finished running yet; we're467 # probably in __init_subclass__. We'll look for abstractmethods manually.468 for name, value in object.__dict__.items():469 if getattr(value, "__isabstractmethod__", False):470 return True471 for base in object.__bases__:472 for name in getattr(base, "__abstractmethods__", ()):473 value = getattr(object, name, None)474 if getattr(value, "__isabstractmethod__", False):475 return True476 return False477 478def _getmembers(object, predicate, getter):479 results = []480 processed = set()481 names = dir(object)482 if isclass(object):483 mro = getmro(object)484 # add any DynamicClassAttributes to the list of names if object is a class;485 # this may result in duplicate entries if, for example, a virtual486 # attribute with the same name as a DynamicClassAttribute exists487 try:488 for base in object.__bases__:489 for k, v in base.__dict__.items():490 if isinstance(v, types.DynamicClassAttribute):491 names.append(k)492 except AttributeError:493 pass494 else:495 mro = ()496 for key in names:497 # First try to get the value via getattr. Some descriptors don't498 # like calling their __get__ (see bug #1785), so fall back to499 # looking in the __dict__.500 try:501 value = getter(object, key)502 # handle the duplicate key503 if key in processed:504 raise AttributeError505 except AttributeError:506 for base in mro:507 if key in base.__dict__:508 value = base.__dict__[key]509 break510 else:511 # could be a (currently) missing slot member, or a buggy512 # __dir__; discard and move on513 continue514 if not predicate or predicate(value):515 results.append((key, value))516 processed.add(key)517 results.sort(key=lambda pair: pair[0])518 return results519 520def getmembers(object, predicate=None):521 """Return all members of an object as (name, value) pairs sorted by name.522 Optionally, only return members that satisfy a given predicate."""523 return _getmembers(object, predicate, getattr)524 525def getmembers_static(object, predicate=None):526 """Return all members of an object as (name, value) pairs sorted by name527 without triggering dynamic lookup via the descriptor protocol,528 __getattr__ or __getattribute__. Optionally, only return members that529 satisfy a given predicate.530 531 Note: this function may not be able to retrieve all members532 that getmembers can fetch (like dynamically created attributes)533 and may find members that getmembers can't (like descriptors534 that raise AttributeError). It can also return descriptor objects535 instead of instance members in some cases.536 """537 return _getmembers(object, predicate, getattr_static)538 539Attribute = namedtuple('Attribute', 'name kind defining_class object')540 541def classify_class_attrs(cls):542 """Return list of attribute-descriptor tuples.543 544 For each name in dir(cls), the return list contains a 4-tuple545 with these elements:546 547 0. The name (a string).548 549 1. The kind of attribute this is, one of these strings:550 'class method' created via classmethod()551 'static method' created via staticmethod()552 'property' created via property()553 'method' any other flavor of method or descriptor554 'data' not a method555 556 2. The class which defined this attribute (a class).557 558 3. The object as obtained by calling getattr; if this fails, or if the559 resulting object does not live anywhere in the class' mro (including560 metaclasses) then the object is looked up in the defining class's561 dict (found by walking the mro).562 563 If one of the items in dir(cls) is stored in the metaclass it will now564 be discovered and not have None be listed as the class in which it was565 defined. Any items whose home class cannot be discovered are skipped.566 """567 568 mro = getmro(cls)569 metamro = getmro(type(cls)) # for attributes stored in the metaclass570 metamro = tuple(cls for cls in metamro if cls not in (type, object))571 class_bases = (cls,) + mro572 all_bases = class_bases + metamro573 names = dir(cls)574 # :dd any DynamicClassAttributes to the list of names;575 # this may result in duplicate entries if, for example, a virtual576 # attribute with the same name as a DynamicClassAttribute exists.577 for base in mro:578 for k, v in base.__dict__.items():579 if isinstance(v, types.DynamicClassAttribute) and v.fget is not None:580 names.append(k)581 result = []582 processed = set()583 584 for name in names:585 # Get the object associated with the name, and where it was defined.586 # Normal objects will be looked up with both getattr and directly in587 # its class' dict (in case getattr fails [bug #1785], and also to look588 # for a docstring).589 # For DynamicClassAttributes on the second pass we only look in the590 # class's dict.591 #592 # Getting an obj from the __dict__ sometimes reveals more than593 # using getattr. Static and class methods are dramatic examples.594 homecls = None595 get_obj = None596 dict_obj = None597 if name not in processed:598 try:599 if name == '__dict__':600 raise Exception("__dict__ is special, don't want the proxy")601 get_obj = getattr(cls, name)602 except Exception:603 pass604 else:605 homecls = getattr(get_obj, "__objclass__", homecls)606 if homecls not in class_bases:607 # if the resulting object does not live somewhere in the608 # mro, drop it and search the mro manually609 homecls = None610 last_cls = None611 # first look in the classes612 for srch_cls in class_bases:613 srch_obj = getattr(srch_cls, name, None)614 if srch_obj is get_obj:615 last_cls = srch_cls616 # then check the metaclasses617 for srch_cls in metamro:618 try:619 srch_obj = srch_cls.__getattr__(cls, name)620 except AttributeError:621 continue622 if srch_obj is get_obj:623 last_cls = srch_cls624 if last_cls is not None:625 homecls = last_cls626 for base in all_bases:627 if name in base.__dict__:628 dict_obj = base.__dict__[name]629 if homecls not in metamro:630 homecls = base631 break632 if homecls is None:633 # unable to locate the attribute anywhere, most likely due to634 # buggy custom __dir__; discard and move on635 continue636 obj = get_obj if get_obj is not None else dict_obj637 # Classify the object or its descriptor.638 if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)):639 kind = "static method"640 obj = dict_obj641 elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)):642 kind = "class method"643 obj = dict_obj644 elif isinstance(dict_obj, property):645 kind = "property"646 obj = dict_obj647 elif isroutine(obj):648 kind = "method"649 else:650 kind = "data"651 result.append(Attribute(name, kind, homecls, obj))652 processed.add(name)653 return result654 655# ----------------------------------------------------------- class helpers656 657def getmro(cls):658 "Return tuple of base classes (including cls) in method resolution order."659 return cls.__mro__660 661# -------------------------------------------------------- function helpers662 663def unwrap(func, *, stop=None):664 """Get the object wrapped by *func*.665 666 Follows the chain of :attr:`__wrapped__` attributes returning the last667 object in the chain.668 669 *stop* is an optional callback accepting an object in the wrapper chain670 as its sole argument that allows the unwrapping to be terminated early if671 the callback returns a true value. If the callback never returns a true672 value, the last object in the chain is returned as usual. For example,673 :func:`signature` uses this to stop unwrapping if any object in the674 chain has a ``__signature__`` attribute defined.675 676 :exc:`ValueError` is raised if a cycle is encountered.677 678 """679 f = func # remember the original func for error reporting680 # Memoise by id to tolerate non-hashable objects, but store objects to681 # ensure they aren't destroyed, which would allow their IDs to be reused.682 memo = {id(f): f}683 recursion_limit = sys.getrecursionlimit()684 while not isinstance(func, type) and hasattr(func, '__wrapped__'):685 if stop is not None and stop(func):686 break687 func = func.__wrapped__688 id_func = id(func)689 if (id_func in memo) or (len(memo) >= recursion_limit):690 raise ValueError('wrapper loop when unwrapping {!r}'.format(f))691 memo[id_func] = func692 return func693 694# -------------------------------------------------- source code extraction695def indentsize(line):696 """Return the indent size, in spaces, at the start of a line of text."""697 expline = line.expandtabs()698 return len(expline) - len(expline.lstrip())699 700def _findclass(func):701 cls = sys.modules.get(func.__module__)702 if cls is None:703 return None704 for name in func.__qualname__.split('.')[:-1]:705 cls = getattr(cls, name)706 if not isclass(cls):707 return None708 return cls709 710def _finddoc(obj):711 if isclass(obj):712 for base in obj.__mro__:713 if base is not object:714 try:715 doc = base.__doc__716 except AttributeError:717 continue718 if doc is not None:719 return doc720 return None721 722 if ismethod(obj):723 name = obj.__func__.__name__724 self = obj.__self__725 if (isclass(self) and726 getattr(getattr(self, name, None), '__func__') is obj.__func__):727 # classmethod728 cls = self729 else:730 cls = self.__class__731 elif isfunction(obj):732 name = obj.__name__733 cls = _findclass(obj)734 if cls is None or getattr(cls, name) is not obj:735 return None736 elif isbuiltin(obj):737 name = obj.__name__738 self = obj.__self__739 if (isclass(self) and740 self.__qualname__ + '.' + name == obj.__qualname__):741 # classmethod742 cls = self743 else:744 cls = self.__class__745 # Should be tested before isdatadescriptor().746 elif isinstance(obj, property):747 name = obj.__name__748 cls = _findclass(obj.fget)749 if cls is None or getattr(cls, name) is not obj:750 return None751 elif ismethoddescriptor(obj) or isdatadescriptor(obj):752 name = obj.__name__753 cls = obj.__objclass__754 if getattr(cls, name) is not obj:755 return None756 if ismemberdescriptor(obj):757 slots = getattr(cls, '__slots__', None)758 if isinstance(slots, dict) and name in slots:759 return slots[name]760 else:761 return None762 for base in cls.__mro__:763 try:764 doc = getattr(base, name).__doc__765 except AttributeError:766 continue767 if doc is not None:768 return doc769 return None770 771def getdoc(object):772 """Get the documentation string for an object.773 774 All tabs are expanded to spaces. To clean up docstrings that are775 indented to line up with blocks of code, any whitespace than can be776 uniformly removed from the second line onwards is removed."""777 try:778 doc = object.__doc__779 except AttributeError:780 return None781 if doc is None:782 try:783 doc = _finddoc(object)784 except (AttributeError, TypeError):785 return None786 if not isinstance(doc, str):787 return None788 return cleandoc(doc)789 790def cleandoc(doc):791 """Clean up indentation from docstrings.792 793 Any whitespace that can be uniformly removed from the second line794 onwards is removed."""795 lines = doc.expandtabs().split('\n')796 797 # Find minimum indentation of any non-blank lines after first line.798 margin = sys.maxsize799 for line in lines[1:]:800 content = len(line.lstrip(' '))801 if content:802 indent = len(line) - content803 margin = min(margin, indent)804 # Remove indentation.805 if lines:806 lines[0] = lines[0].lstrip(' ')807 if margin < sys.maxsize:808 for i in range(1, len(lines)):809 lines[i] = lines[i][margin:]810 # Remove any trailing or leading blank lines.811 while lines and not lines[-1]:812 lines.pop()813 while lines and not lines[0]:814 lines.pop(0)815 return '\n'.join(lines)816 817 818def getfile(object):819 """Work out which source or compiled file an object was defined in."""820 if ismodule(object):821 if getattr(object, '__file__', None):822 return object.__file__823 raise TypeError('{!r} is a built-in module'.format(object))824 if isclass(object):825 if hasattr(object, '__module__'):826 module = sys.modules.get(object.__module__)827 if getattr(module, '__file__', None):828 return module.__file__829 if object.__module__ == '__main__':830 raise OSError('source code not available')831 raise TypeError('{!r} is a built-in class'.format(object))832 if ismethod(object):833 object = object.__func__834 if isfunction(object):835 object = object.__code__836 if istraceback(object):837 object = object.tb_frame838 if isframe(object):839 object = object.f_code840 if iscode(object):841 return object.co_filename842 raise TypeError('module, class, method, function, traceback, frame, or '843 'code object was expected, got {}'.format(844 type(object).__name__))845 846def getmodulename(path):847 """Return the module name for a given file, or None."""848 fname = os.path.basename(path)849 # Check for paths that look like an actual module file850 suffixes = [(-len(suffix), suffix)851 for suffix in importlib.machinery.all_suffixes()]852 suffixes.sort() # try longest suffixes first, in case they overlap853 for neglen, suffix in suffixes:854 if fname.endswith(suffix):855 return fname[:neglen]856 return None857 858def getsourcefile(object):859 """Return the filename that can be used to locate an object's source.860 Return None if no way can be identified to get the source.861 """862 filename = getfile(object)863 all_bytecode_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]864 if any(filename.endswith(s) for s in all_bytecode_suffixes):865 filename = (os.path.splitext(filename)[0] +866 importlib.machinery.SOURCE_SUFFIXES[0])867 elif any(filename.endswith(s) for s in868 importlib.machinery.EXTENSION_SUFFIXES):869 return None870 elif filename.endswith(".fwork"):871 # Apple mobile framework markers are another type of non-source file872 return None873 874 # return a filename found in the linecache even if it doesn't exist on disk875 if filename in linecache.cache:876 return filename877 if os.path.exists(filename):878 return filename879 # only return a non-existent filename if the module has a PEP 302 loader880 module = getmodule(object, filename)881 if getattr(module, '__loader__', None) is not None:882 return filename883 elif getattr(getattr(module, "__spec__", None), "loader", None) is not None:884 return filename885 886def getabsfile(object, _filename=None):887 """Return an absolute path to the source or compiled file for an object.888 889 The idea is for each object to have a unique origin, so this routine890 normalizes the result as much as possible."""891 if _filename is None:892 _filename = getsourcefile(object) or getfile(object)893 return os.path.normcase(os.path.abspath(_filename))894 895modulesbyfile = {}896_filesbymodname = {}897 898def getmodule(object, _filename=None):899 """Return the module an object was defined in, or None if not found."""900 if ismodule(object):901 return object902 if hasattr(object, '__module__'):903 return sys.modules.get(object.__module__)904 905 # Try the filename to modulename cache906 if _filename is not None and _filename in modulesbyfile:907 return sys.modules.get(modulesbyfile[_filename])908 # Try the cache again with the absolute file name909 try:910 file = getabsfile(object, _filename)911 except (TypeError, FileNotFoundError):912 return None913 if file in modulesbyfile:914 return sys.modules.get(modulesbyfile[file])915 # Update the filename to module name cache and check yet again916 # Copy sys.modules in order to cope with changes while iterating917 for modname, module in sys.modules.copy().items():918 if ismodule(module) and hasattr(module, '__file__'):919 f = module.__file__920 if f == _filesbymodname.get(modname, None):921 # Have already mapped this module, so skip it922 continue923 _filesbymodname[modname] = f924 f = getabsfile(module)925 # Always map to the name the module knows itself by926 modulesbyfile[f] = modulesbyfile[927 os.path.realpath(f)] = module.__name__928 if file in modulesbyfile:929 return sys.modules.get(modulesbyfile[file])930 # Check the main module931 main = sys.modules['__main__']932 if not hasattr(object, '__name__'):933 return None934 if hasattr(main, object.__name__):935 mainobject = getattr(main, object.__name__)936 if mainobject is object:937 return main938 # Check builtins939 builtin = sys.modules['builtins']940 if hasattr(builtin, object.__name__):941 builtinobject = getattr(builtin, object.__name__)942 if builtinobject is object:943 return builtin944 945 946class ClassFoundException(Exception):947 pass948 949 950def findsource(object):951 """Return the entire source file and starting line number for an object.952 953 The argument may be a module, class, method, function, traceback, frame,954 or code object. The source code is returned as a list of all the lines955 in the file and the line number indexes a line in that list. An OSError956 is raised if the source code cannot be retrieved."""957 958 file = getsourcefile(object)959 if file:960 # Invalidate cache if needed.961 linecache.checkcache(file)962 else:963 file = getfile(object)964 # Allow filenames in form of "<something>" to pass through.965 # `doctest` monkeypatches `linecache` module to enable966 # inspection, so let `linecache.getlines` to be called.967 if (not (file.startswith('<') and file.endswith('>'))) or file.endswith('.fwork'):968 raise OSError('source code not available')969 970 module = getmodule(object, file)971 if module:972 lines = linecache.getlines(file, module.__dict__)973 if not lines and file.startswith('<') and hasattr(object, "__code__"):974 lines = linecache._getlines_from_code(object.__code__)975 else:976 lines = linecache.getlines(file)977 if not lines:978 raise OSError('could not get source code')979 980 if ismodule(object):981 return lines, 0982 983 if isclass(object):984 try:985 lnum = vars(object)['__firstlineno__'] - 1986 except (TypeError, KeyError):987 raise OSError('source code not available')988 if lnum >= len(lines):989 raise OSError('lineno is out of bounds')990 return lines, lnum991 992 if ismethod(object):993 object = object.__func__994 if isfunction(object):995 object = object.__code__996 if istraceback(object):997 object = object.tb_frame998 if isframe(object):999 object = object.f_code1000 if iscode(object):1001 if not hasattr(object, 'co_firstlineno'):1002 raise OSError('could not find function definition')1003 lnum = object.co_firstlineno - 11004 if lnum >= len(lines):1005 raise OSError('lineno is out of bounds')1006 return lines, lnum1007 raise OSError('could not find code object')1008 1009def getcomments(object):1010 """Get lines of comments immediately preceding an object's source code.1011 1012 Returns None when source can't be found.1013 """1014 try:1015 lines, lnum = findsource(object)1016 except (OSError, TypeError):1017 return None1018 1019 if ismodule(object):1020 # Look for a comment block at the top of the file.1021 start = 01022 if lines and lines[0][:2] == '#!': start = 11023 while start < len(lines) and lines[start].strip() in ('', '#'):1024 start = start + 11025 if start < len(lines) and lines[start][:1] == '#':1026 comments = []1027 end = start1028 while end < len(lines) and lines[end][:1] == '#':1029 comments.append(lines[end].expandtabs())1030 end = end + 11031 return ''.join(comments)1032 1033 # Look for a preceding block of comments at the same indentation.1034 elif lnum > 0:1035 indent = indentsize(lines[lnum])1036 end = lnum - 11037 if end >= 0 and lines[end].lstrip()[:1] == '#' and \1038 indentsize(lines[end]) == indent:1039 comments = [lines[end].expandtabs().lstrip()]1040 if end > 0:1041 end = end - 11042 comment = lines[end].expandtabs().lstrip()1043 while comment[:1] == '#' and indentsize(lines[end]) == indent:1044 comments[:0] = [comment]1045 end = end - 11046 if end < 0: break1047 comment = lines[end].expandtabs().lstrip()1048 while comments and comments[0].strip() == '#':1049 comments[:1] = []1050 while comments and comments[-1].strip() == '#':1051 comments[-1:] = []1052 return ''.join(comments)1053 1054class EndOfBlock(Exception): pass1055 1056class BlockFinder:1057 """Provide a tokeneater() method to detect the end of a code block."""1058 def __init__(self):1059 self.indent = 01060 self.singleline = False1061 self.started = False1062 self.passline = False1063 self.indecorator = False1064 self.last = 11065 self.body_col0 = None1066 1067 def tokeneater(self, type, token, srowcol, erowcol, line):1068 if not self.started and not self.indecorator:1069 if type in (tokenize.INDENT, tokenize.COMMENT, tokenize.NL):1070 pass1071 elif token == "async":1072 pass1073 # skip any decorators1074 elif token == "@":1075 self.indecorator = True1076 else:1077 # For "def" and "class" scan to the end of the block.1078 # For "lambda" and generator expression scan to1079 # the end of the logical line.1080 self.singleline = token not in ("def", "class")1081 self.started = True1082 self.passline = True # skip to the end of the line1083 elif type == tokenize.NEWLINE:1084 self.passline = False # stop skipping when a NEWLINE is seen1085 self.last = srowcol[0]1086 if self.singleline:1087 raise EndOfBlock1088 # hitting a NEWLINE when in a decorator without args1089 # ends the decorator1090 if self.indecorator:1091 self.indecorator = False1092 elif self.passline:1093 pass1094 elif type == tokenize.INDENT:1095 if self.body_col0 is None and self.started:1096 self.body_col0 = erowcol[1]1097 self.indent = self.indent + 11098 self.passline = True1099 elif type == tokenize.DEDENT:1100 self.indent = self.indent - 11101 # the end of matching indent/dedent pairs end a block1102 # (note that this only works for "def"/"class" blocks,1103 # not e.g. for "if: else:" or "try: finally:" blocks)1104 if self.indent <= 0:1105 raise EndOfBlock1106 elif type == tokenize.COMMENT:1107 if self.body_col0 is not None and srowcol[1] >= self.body_col0:1108 # Include comments if indented at least as much as the block1109 self.last = srowcol[0]1110 elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):1111 # any other token on the same indentation level end the previous1112 # block as well, except the pseudo-tokens COMMENT and NL.1113 raise EndOfBlock1114 1115def getblock(lines):1116 """Extract the block of code at the top of the given list of lines."""1117 blockfinder = BlockFinder()1118 try:1119 tokens = tokenize.generate_tokens(iter(lines).__next__)1120 for _token in tokens:1121 blockfinder.tokeneater(*_token)1122 except (EndOfBlock, IndentationError):1123 pass1124 except SyntaxError as e:1125 if "unmatched" not in e.msg:1126 raise e from None1127 _, *_token_info = _token1128 try:1129 blockfinder.tokeneater(tokenize.NEWLINE, *_token_info)1130 except (EndOfBlock, IndentationError):1131 pass1132 return lines[:blockfinder.last]1133 1134def getsourcelines(object):1135 """Return a list of source lines and starting line number for an object.1136 1137 The argument may be a module, class, method, function, traceback, frame,1138 or code object. The source code is returned as a list of the lines1139 corresponding to the object and the line number indicates where in the1140 original source file the first line of code was found. An OSError is1141 raised if the source code cannot be retrieved."""1142 object = unwrap(object)1143 lines, lnum = findsource(object)1144 1145 if istraceback(object):1146 object = object.tb_frame1147 1148 # for module or frame that corresponds to module, return all source lines1149 if (ismodule(object) or1150 (isframe(object) and object.f_code.co_name == "<module>")):1151 return lines, 01152 else:1153 return getblock(lines[lnum:]), lnum + 11154 1155def getsource(object):1156 """Return the text of the source code for an object.1157 1158 The argument may be a module, class, method, function, traceback, frame,1159 or code object. The source code is returned as a single string. An1160 OSError is raised if the source code cannot be retrieved."""1161 lines, lnum = getsourcelines(object)1162 return ''.join(lines)1163 1164# --------------------------------------------------- class tree extraction1165def walktree(classes, children, parent):1166 """Recursive helper function for getclasstree()."""1167 results = []1168 classes.sort(key=attrgetter('__module__', '__name__'))1169 for c in classes:1170 results.append((c, c.__bases__))1171 if c in children:1172 results.append(walktree(children[c], children, c))1173 return results1174 1175def getclasstree(classes, unique=False):1176 """Arrange the given list of classes into a hierarchy of nested lists.1177 1178 Where a nested list appears, it contains classes derived from the class1179 whose entry immediately precedes the list. Each entry is a 2-tuple1180 containing a class and a tuple of its base classes. If the 'unique'1181 argument is true, exactly one entry appears in the returned structure1182 for each class in the given list. Otherwise, classes using multiple1183 inheritance and their descendants will appear multiple times."""1184 children = {}1185 roots = []1186 for c in classes:1187 if c.__bases__:1188 for parent in c.__bases__:1189 if parent not in children:1190 children[parent] = []1191 if c not in children[parent]:1192 children[parent].append(c)1193 if unique and parent in classes: break1194 elif c not in roots:1195 roots.append(c)1196 for parent in children:1197 if parent not in classes:1198 roots.append(parent)1199 return walktree(roots, children, None)1200 