Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
inspect.py3410 linesDownload Raw Back to Lib
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 

Showing the first 1,200 of 3410 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai