1*cda5da8dSAndroid Build Coastguard Worker"""Get useful information from live Python objects. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerThis module encapsulates the interface provided by the internal special 4*cda5da8dSAndroid Build Coastguard Workerattributes (co_*, im_*, tb_*, etc.) in a friendlier fashion. 5*cda5da8dSAndroid Build Coastguard WorkerIt also provides some help for examining source code and class layout. 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard WorkerHere are some of the useful functions provided by this module: 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard Worker ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), 10*cda5da8dSAndroid Build Coastguard Worker isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), 11*cda5da8dSAndroid Build Coastguard Worker isroutine() - check object types 12*cda5da8dSAndroid Build Coastguard Worker getmembers() - get members of an object that satisfy a given condition 13*cda5da8dSAndroid Build Coastguard Worker 14*cda5da8dSAndroid Build Coastguard Worker getfile(), getsourcefile(), getsource() - find an object's source code 15*cda5da8dSAndroid Build Coastguard Worker getdoc(), getcomments() - get documentation on an object 16*cda5da8dSAndroid Build Coastguard Worker getmodule() - determine the module that an object came from 17*cda5da8dSAndroid Build Coastguard Worker getclasstree() - arrange classes so as to represent their hierarchy 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker getargvalues(), getcallargs() - get info about function arguments 20*cda5da8dSAndroid Build Coastguard Worker getfullargspec() - same, with support for Python 3 features 21*cda5da8dSAndroid Build Coastguard Worker formatargvalues() - format an argument spec 22*cda5da8dSAndroid Build Coastguard Worker getouterframes(), getinnerframes() - get info about frames 23*cda5da8dSAndroid Build Coastguard Worker currentframe() - get the current stack frame 24*cda5da8dSAndroid Build Coastguard Worker stack(), trace() - get info about frames on the stack or in a traceback 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker signature() - get a Signature object for the callable 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Worker get_annotations() - safely compute an object's annotations 29*cda5da8dSAndroid Build Coastguard Worker""" 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Worker# This module is in the public domain. No warranties. 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker__author__ = ('Ka-Ping Yee <[email protected]>', 34*cda5da8dSAndroid Build Coastguard Worker 'Yury Selivanov <[email protected]>') 35*cda5da8dSAndroid Build Coastguard Worker 36*cda5da8dSAndroid Build Coastguard Worker__all__ = [ 37*cda5da8dSAndroid Build Coastguard Worker "ArgInfo", 38*cda5da8dSAndroid Build Coastguard Worker "Arguments", 39*cda5da8dSAndroid Build Coastguard Worker "Attribute", 40*cda5da8dSAndroid Build Coastguard Worker "BlockFinder", 41*cda5da8dSAndroid Build Coastguard Worker "BoundArguments", 42*cda5da8dSAndroid Build Coastguard Worker "CORO_CLOSED", 43*cda5da8dSAndroid Build Coastguard Worker "CORO_CREATED", 44*cda5da8dSAndroid Build Coastguard Worker "CORO_RUNNING", 45*cda5da8dSAndroid Build Coastguard Worker "CORO_SUSPENDED", 46*cda5da8dSAndroid Build Coastguard Worker "CO_ASYNC_GENERATOR", 47*cda5da8dSAndroid Build Coastguard Worker "CO_COROUTINE", 48*cda5da8dSAndroid Build Coastguard Worker "CO_GENERATOR", 49*cda5da8dSAndroid Build Coastguard Worker "CO_ITERABLE_COROUTINE", 50*cda5da8dSAndroid Build Coastguard Worker "CO_NESTED", 51*cda5da8dSAndroid Build Coastguard Worker "CO_NEWLOCALS", 52*cda5da8dSAndroid Build Coastguard Worker "CO_NOFREE", 53*cda5da8dSAndroid Build Coastguard Worker "CO_OPTIMIZED", 54*cda5da8dSAndroid Build Coastguard Worker "CO_VARARGS", 55*cda5da8dSAndroid Build Coastguard Worker "CO_VARKEYWORDS", 56*cda5da8dSAndroid Build Coastguard Worker "ClassFoundException", 57*cda5da8dSAndroid Build Coastguard Worker "ClosureVars", 58*cda5da8dSAndroid Build Coastguard Worker "EndOfBlock", 59*cda5da8dSAndroid Build Coastguard Worker "FrameInfo", 60*cda5da8dSAndroid Build Coastguard Worker "FullArgSpec", 61*cda5da8dSAndroid Build Coastguard Worker "GEN_CLOSED", 62*cda5da8dSAndroid Build Coastguard Worker "GEN_CREATED", 63*cda5da8dSAndroid Build Coastguard Worker "GEN_RUNNING", 64*cda5da8dSAndroid Build Coastguard Worker "GEN_SUSPENDED", 65*cda5da8dSAndroid Build Coastguard Worker "Parameter", 66*cda5da8dSAndroid Build Coastguard Worker "Signature", 67*cda5da8dSAndroid Build Coastguard Worker "TPFLAGS_IS_ABSTRACT", 68*cda5da8dSAndroid Build Coastguard Worker "Traceback", 69*cda5da8dSAndroid Build Coastguard Worker "classify_class_attrs", 70*cda5da8dSAndroid Build Coastguard Worker "cleandoc", 71*cda5da8dSAndroid Build Coastguard Worker "currentframe", 72*cda5da8dSAndroid Build Coastguard Worker "findsource", 73*cda5da8dSAndroid Build Coastguard Worker "formatannotation", 74*cda5da8dSAndroid Build Coastguard Worker "formatannotationrelativeto", 75*cda5da8dSAndroid Build Coastguard Worker "formatargvalues", 76*cda5da8dSAndroid Build Coastguard Worker "get_annotations", 77*cda5da8dSAndroid Build Coastguard Worker "getabsfile", 78*cda5da8dSAndroid Build Coastguard Worker "getargs", 79*cda5da8dSAndroid Build Coastguard Worker "getargvalues", 80*cda5da8dSAndroid Build Coastguard Worker "getattr_static", 81*cda5da8dSAndroid Build Coastguard Worker "getblock", 82*cda5da8dSAndroid Build Coastguard Worker "getcallargs", 83*cda5da8dSAndroid Build Coastguard Worker "getclasstree", 84*cda5da8dSAndroid Build Coastguard Worker "getclosurevars", 85*cda5da8dSAndroid Build Coastguard Worker "getcomments", 86*cda5da8dSAndroid Build Coastguard Worker "getcoroutinelocals", 87*cda5da8dSAndroid Build Coastguard Worker "getcoroutinestate", 88*cda5da8dSAndroid Build Coastguard Worker "getdoc", 89*cda5da8dSAndroid Build Coastguard Worker "getfile", 90*cda5da8dSAndroid Build Coastguard Worker "getframeinfo", 91*cda5da8dSAndroid Build Coastguard Worker "getfullargspec", 92*cda5da8dSAndroid Build Coastguard Worker "getgeneratorlocals", 93*cda5da8dSAndroid Build Coastguard Worker "getgeneratorstate", 94*cda5da8dSAndroid Build Coastguard Worker "getinnerframes", 95*cda5da8dSAndroid Build Coastguard Worker "getlineno", 96*cda5da8dSAndroid Build Coastguard Worker "getmembers", 97*cda5da8dSAndroid Build Coastguard Worker "getmembers_static", 98*cda5da8dSAndroid Build Coastguard Worker "getmodule", 99*cda5da8dSAndroid Build Coastguard Worker "getmodulename", 100*cda5da8dSAndroid Build Coastguard Worker "getmro", 101*cda5da8dSAndroid Build Coastguard Worker "getouterframes", 102*cda5da8dSAndroid Build Coastguard Worker "getsource", 103*cda5da8dSAndroid Build Coastguard Worker "getsourcefile", 104*cda5da8dSAndroid Build Coastguard Worker "getsourcelines", 105*cda5da8dSAndroid Build Coastguard Worker "indentsize", 106*cda5da8dSAndroid Build Coastguard Worker "isabstract", 107*cda5da8dSAndroid Build Coastguard Worker "isasyncgen", 108*cda5da8dSAndroid Build Coastguard Worker "isasyncgenfunction", 109*cda5da8dSAndroid Build Coastguard Worker "isawaitable", 110*cda5da8dSAndroid Build Coastguard Worker "isbuiltin", 111*cda5da8dSAndroid Build Coastguard Worker "isclass", 112*cda5da8dSAndroid Build Coastguard Worker "iscode", 113*cda5da8dSAndroid Build Coastguard Worker "iscoroutine", 114*cda5da8dSAndroid Build Coastguard Worker "iscoroutinefunction", 115*cda5da8dSAndroid Build Coastguard Worker "isdatadescriptor", 116*cda5da8dSAndroid Build Coastguard Worker "isframe", 117*cda5da8dSAndroid Build Coastguard Worker "isfunction", 118*cda5da8dSAndroid Build Coastguard Worker "isgenerator", 119*cda5da8dSAndroid Build Coastguard Worker "isgeneratorfunction", 120*cda5da8dSAndroid Build Coastguard Worker "isgetsetdescriptor", 121*cda5da8dSAndroid Build Coastguard Worker "ismemberdescriptor", 122*cda5da8dSAndroid Build Coastguard Worker "ismethod", 123*cda5da8dSAndroid Build Coastguard Worker "ismethoddescriptor", 124*cda5da8dSAndroid Build Coastguard Worker "ismethodwrapper", 125*cda5da8dSAndroid Build Coastguard Worker "ismodule", 126*cda5da8dSAndroid Build Coastguard Worker "isroutine", 127*cda5da8dSAndroid Build Coastguard Worker "istraceback", 128*cda5da8dSAndroid Build Coastguard Worker "signature", 129*cda5da8dSAndroid Build Coastguard Worker "stack", 130*cda5da8dSAndroid Build Coastguard Worker "trace", 131*cda5da8dSAndroid Build Coastguard Worker "unwrap", 132*cda5da8dSAndroid Build Coastguard Worker "walktree", 133*cda5da8dSAndroid Build Coastguard Worker] 134*cda5da8dSAndroid Build Coastguard Worker 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Workerimport abc 137*cda5da8dSAndroid Build Coastguard Workerimport ast 138*cda5da8dSAndroid Build Coastguard Workerimport dis 139*cda5da8dSAndroid Build Coastguard Workerimport collections.abc 140*cda5da8dSAndroid Build Coastguard Workerimport enum 141*cda5da8dSAndroid Build Coastguard Workerimport importlib.machinery 142*cda5da8dSAndroid Build Coastguard Workerimport itertools 143*cda5da8dSAndroid Build Coastguard Workerimport linecache 144*cda5da8dSAndroid Build Coastguard Workerimport os 145*cda5da8dSAndroid Build Coastguard Workerimport re 146*cda5da8dSAndroid Build Coastguard Workerimport sys 147*cda5da8dSAndroid Build Coastguard Workerimport tokenize 148*cda5da8dSAndroid Build Coastguard Workerimport token 149*cda5da8dSAndroid Build Coastguard Workerimport types 150*cda5da8dSAndroid Build Coastguard Workerimport functools 151*cda5da8dSAndroid Build Coastguard Workerimport builtins 152*cda5da8dSAndroid Build Coastguard Workerfrom keyword import iskeyword 153*cda5da8dSAndroid Build Coastguard Workerfrom operator import attrgetter 154*cda5da8dSAndroid Build Coastguard Workerfrom collections import namedtuple, OrderedDict 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker# Create constants for the compiler flags in Include/code.h 157*cda5da8dSAndroid Build Coastguard Worker# We try to get them from dis to avoid duplication 158*cda5da8dSAndroid Build Coastguard Workermod_dict = globals() 159*cda5da8dSAndroid Build Coastguard Workerfor k, v in dis.COMPILER_FLAG_NAMES.items(): 160*cda5da8dSAndroid Build Coastguard Worker mod_dict["CO_" + v] = k 161*cda5da8dSAndroid Build Coastguard Workerdel k, v, mod_dict 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker# See Include/object.h 164*cda5da8dSAndroid Build Coastguard WorkerTPFLAGS_IS_ABSTRACT = 1 << 20 165*cda5da8dSAndroid Build Coastguard Worker 166*cda5da8dSAndroid Build Coastguard Worker 167*cda5da8dSAndroid Build Coastguard Workerdef get_annotations(obj, *, globals=None, locals=None, eval_str=False): 168*cda5da8dSAndroid Build Coastguard Worker """Compute the annotations dict for an object. 169*cda5da8dSAndroid Build Coastguard Worker 170*cda5da8dSAndroid Build Coastguard Worker obj may be a callable, class, or module. 171*cda5da8dSAndroid Build Coastguard Worker Passing in an object of any other type raises TypeError. 172*cda5da8dSAndroid Build Coastguard Worker 173*cda5da8dSAndroid Build Coastguard Worker Returns a dict. get_annotations() returns a new dict every time 174*cda5da8dSAndroid Build Coastguard Worker it's called; calling it twice on the same object will return two 175*cda5da8dSAndroid Build Coastguard Worker different but equivalent dicts. 176*cda5da8dSAndroid Build Coastguard Worker 177*cda5da8dSAndroid Build Coastguard Worker This function handles several details for you: 178*cda5da8dSAndroid Build Coastguard Worker 179*cda5da8dSAndroid Build Coastguard Worker * If eval_str is true, values of type str will 180*cda5da8dSAndroid Build Coastguard Worker be un-stringized using eval(). This is intended 181*cda5da8dSAndroid Build Coastguard Worker for use with stringized annotations 182*cda5da8dSAndroid Build Coastguard Worker ("from __future__ import annotations"). 183*cda5da8dSAndroid Build Coastguard Worker * If obj doesn't have an annotations dict, returns an 184*cda5da8dSAndroid Build Coastguard Worker empty dict. (Functions and methods always have an 185*cda5da8dSAndroid Build Coastguard Worker annotations dict; classes, modules, and other types of 186*cda5da8dSAndroid Build Coastguard Worker callables may not.) 187*cda5da8dSAndroid Build Coastguard Worker * Ignores inherited annotations on classes. If a class 188*cda5da8dSAndroid Build Coastguard Worker doesn't have its own annotations dict, returns an empty dict. 189*cda5da8dSAndroid Build Coastguard Worker * All accesses to object members and dict values are done 190*cda5da8dSAndroid Build Coastguard Worker using getattr() and dict.get() for safety. 191*cda5da8dSAndroid Build Coastguard Worker * Always, always, always returns a freshly-created dict. 192*cda5da8dSAndroid Build Coastguard Worker 193*cda5da8dSAndroid Build Coastguard Worker eval_str controls whether or not values of type str are replaced 194*cda5da8dSAndroid Build Coastguard Worker with the result of calling eval() on those values: 195*cda5da8dSAndroid Build Coastguard Worker 196*cda5da8dSAndroid Build Coastguard Worker * If eval_str is true, eval() is called on values of type str. 197*cda5da8dSAndroid Build Coastguard Worker * If eval_str is false (the default), values of type str are unchanged. 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker globals and locals are passed in to eval(); see the documentation 200*cda5da8dSAndroid Build Coastguard Worker for eval() for more information. If either globals or locals is 201*cda5da8dSAndroid Build Coastguard Worker None, this function may replace that value with a context-specific 202*cda5da8dSAndroid Build Coastguard Worker default, contingent on type(obj): 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker * If obj is a module, globals defaults to obj.__dict__. 205*cda5da8dSAndroid Build Coastguard Worker * If obj is a class, globals defaults to 206*cda5da8dSAndroid Build Coastguard Worker sys.modules[obj.__module__].__dict__ and locals 207*cda5da8dSAndroid Build Coastguard Worker defaults to the obj class namespace. 208*cda5da8dSAndroid Build Coastguard Worker * If obj is a callable, globals defaults to obj.__globals__, 209*cda5da8dSAndroid Build Coastguard Worker although if obj is a wrapped function (using 210*cda5da8dSAndroid Build Coastguard Worker functools.update_wrapper()) it is first unwrapped. 211*cda5da8dSAndroid Build Coastguard Worker """ 212*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, type): 213*cda5da8dSAndroid Build Coastguard Worker # class 214*cda5da8dSAndroid Build Coastguard Worker obj_dict = getattr(obj, '__dict__', None) 215*cda5da8dSAndroid Build Coastguard Worker if obj_dict and hasattr(obj_dict, 'get'): 216*cda5da8dSAndroid Build Coastguard Worker ann = obj_dict.get('__annotations__', None) 217*cda5da8dSAndroid Build Coastguard Worker if isinstance(ann, types.GetSetDescriptorType): 218*cda5da8dSAndroid Build Coastguard Worker ann = None 219*cda5da8dSAndroid Build Coastguard Worker else: 220*cda5da8dSAndroid Build Coastguard Worker ann = None 221*cda5da8dSAndroid Build Coastguard Worker 222*cda5da8dSAndroid Build Coastguard Worker obj_globals = None 223*cda5da8dSAndroid Build Coastguard Worker module_name = getattr(obj, '__module__', None) 224*cda5da8dSAndroid Build Coastguard Worker if module_name: 225*cda5da8dSAndroid Build Coastguard Worker module = sys.modules.get(module_name, None) 226*cda5da8dSAndroid Build Coastguard Worker if module: 227*cda5da8dSAndroid Build Coastguard Worker obj_globals = getattr(module, '__dict__', None) 228*cda5da8dSAndroid Build Coastguard Worker obj_locals = dict(vars(obj)) 229*cda5da8dSAndroid Build Coastguard Worker unwrap = obj 230*cda5da8dSAndroid Build Coastguard Worker elif isinstance(obj, types.ModuleType): 231*cda5da8dSAndroid Build Coastguard Worker # module 232*cda5da8dSAndroid Build Coastguard Worker ann = getattr(obj, '__annotations__', None) 233*cda5da8dSAndroid Build Coastguard Worker obj_globals = getattr(obj, '__dict__') 234*cda5da8dSAndroid Build Coastguard Worker obj_locals = None 235*cda5da8dSAndroid Build Coastguard Worker unwrap = None 236*cda5da8dSAndroid Build Coastguard Worker elif callable(obj): 237*cda5da8dSAndroid Build Coastguard Worker # this includes types.Function, types.BuiltinFunctionType, 238*cda5da8dSAndroid Build Coastguard Worker # types.BuiltinMethodType, functools.partial, functools.singledispatch, 239*cda5da8dSAndroid Build Coastguard Worker # "class funclike" from Lib/test/test_inspect... on and on it goes. 240*cda5da8dSAndroid Build Coastguard Worker ann = getattr(obj, '__annotations__', None) 241*cda5da8dSAndroid Build Coastguard Worker obj_globals = getattr(obj, '__globals__', None) 242*cda5da8dSAndroid Build Coastguard Worker obj_locals = None 243*cda5da8dSAndroid Build Coastguard Worker unwrap = obj 244*cda5da8dSAndroid Build Coastguard Worker else: 245*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{obj!r} is not a module, class, or callable.") 246*cda5da8dSAndroid Build Coastguard Worker 247*cda5da8dSAndroid Build Coastguard Worker if ann is None: 248*cda5da8dSAndroid Build Coastguard Worker return {} 249*cda5da8dSAndroid Build Coastguard Worker 250*cda5da8dSAndroid Build Coastguard Worker if not isinstance(ann, dict): 251*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") 252*cda5da8dSAndroid Build Coastguard Worker 253*cda5da8dSAndroid Build Coastguard Worker if not ann: 254*cda5da8dSAndroid Build Coastguard Worker return {} 255*cda5da8dSAndroid Build Coastguard Worker 256*cda5da8dSAndroid Build Coastguard Worker if not eval_str: 257*cda5da8dSAndroid Build Coastguard Worker return dict(ann) 258*cda5da8dSAndroid Build Coastguard Worker 259*cda5da8dSAndroid Build Coastguard Worker if unwrap is not None: 260*cda5da8dSAndroid Build Coastguard Worker while True: 261*cda5da8dSAndroid Build Coastguard Worker if hasattr(unwrap, '__wrapped__'): 262*cda5da8dSAndroid Build Coastguard Worker unwrap = unwrap.__wrapped__ 263*cda5da8dSAndroid Build Coastguard Worker continue 264*cda5da8dSAndroid Build Coastguard Worker if isinstance(unwrap, functools.partial): 265*cda5da8dSAndroid Build Coastguard Worker unwrap = unwrap.func 266*cda5da8dSAndroid Build Coastguard Worker continue 267*cda5da8dSAndroid Build Coastguard Worker break 268*cda5da8dSAndroid Build Coastguard Worker if hasattr(unwrap, "__globals__"): 269*cda5da8dSAndroid Build Coastguard Worker obj_globals = unwrap.__globals__ 270*cda5da8dSAndroid Build Coastguard Worker 271*cda5da8dSAndroid Build Coastguard Worker if globals is None: 272*cda5da8dSAndroid Build Coastguard Worker globals = obj_globals 273*cda5da8dSAndroid Build Coastguard Worker if locals is None: 274*cda5da8dSAndroid Build Coastguard Worker locals = obj_locals 275*cda5da8dSAndroid Build Coastguard Worker 276*cda5da8dSAndroid Build Coastguard Worker return_value = {key: 277*cda5da8dSAndroid Build Coastguard Worker value if not isinstance(value, str) else eval(value, globals, locals) 278*cda5da8dSAndroid Build Coastguard Worker for key, value in ann.items() } 279*cda5da8dSAndroid Build Coastguard Worker return return_value 280*cda5da8dSAndroid Build Coastguard Worker 281*cda5da8dSAndroid Build Coastguard Worker 282*cda5da8dSAndroid Build Coastguard Worker# ----------------------------------------------------------- type-checking 283*cda5da8dSAndroid Build Coastguard Workerdef ismodule(object): 284*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a module. 285*cda5da8dSAndroid Build Coastguard Worker 286*cda5da8dSAndroid Build Coastguard Worker Module objects provide these attributes: 287*cda5da8dSAndroid Build Coastguard Worker __cached__ pathname to byte compiled file 288*cda5da8dSAndroid Build Coastguard Worker __doc__ documentation string 289*cda5da8dSAndroid Build Coastguard Worker __file__ filename (missing for built-in modules)""" 290*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.ModuleType) 291*cda5da8dSAndroid Build Coastguard Worker 292*cda5da8dSAndroid Build Coastguard Workerdef isclass(object): 293*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a class. 294*cda5da8dSAndroid Build Coastguard Worker 295*cda5da8dSAndroid Build Coastguard Worker Class objects provide these attributes: 296*cda5da8dSAndroid Build Coastguard Worker __doc__ documentation string 297*cda5da8dSAndroid Build Coastguard Worker __module__ name of module in which this class was defined""" 298*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, type) 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Workerdef ismethod(object): 301*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is an instance method. 302*cda5da8dSAndroid Build Coastguard Worker 303*cda5da8dSAndroid Build Coastguard Worker Instance method objects provide these attributes: 304*cda5da8dSAndroid Build Coastguard Worker __doc__ documentation string 305*cda5da8dSAndroid Build Coastguard Worker __name__ name with which this method was defined 306*cda5da8dSAndroid Build Coastguard Worker __func__ function object containing implementation of method 307*cda5da8dSAndroid Build Coastguard Worker __self__ instance to which this method is bound""" 308*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.MethodType) 309*cda5da8dSAndroid Build Coastguard Worker 310*cda5da8dSAndroid Build Coastguard Workerdef ismethoddescriptor(object): 311*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a method descriptor. 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Worker But not if ismethod() or isclass() or isfunction() are true. 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Worker This is new in Python 2.2, and, for example, is true of int.__add__. 316*cda5da8dSAndroid Build Coastguard Worker An object passing this test has a __get__ attribute but not a __set__ 317*cda5da8dSAndroid Build Coastguard Worker attribute, but beyond that the set of attributes varies. __name__ is 318*cda5da8dSAndroid Build Coastguard Worker usually sensible, and __doc__ often is. 319*cda5da8dSAndroid Build Coastguard Worker 320*cda5da8dSAndroid Build Coastguard Worker Methods implemented via descriptors that also pass one of the other 321*cda5da8dSAndroid Build Coastguard Worker tests return false from the ismethoddescriptor() test, simply because 322*cda5da8dSAndroid Build Coastguard Worker the other tests promise more -- you can, e.g., count on having the 323*cda5da8dSAndroid Build Coastguard Worker __func__ attribute (etc) when an object passes ismethod().""" 324*cda5da8dSAndroid Build Coastguard Worker if isclass(object) or ismethod(object) or isfunction(object): 325*cda5da8dSAndroid Build Coastguard Worker # mutual exclusion 326*cda5da8dSAndroid Build Coastguard Worker return False 327*cda5da8dSAndroid Build Coastguard Worker tp = type(object) 328*cda5da8dSAndroid Build Coastguard Worker return hasattr(tp, "__get__") and not hasattr(tp, "__set__") 329*cda5da8dSAndroid Build Coastguard Worker 330*cda5da8dSAndroid Build Coastguard Workerdef isdatadescriptor(object): 331*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a data descriptor. 332*cda5da8dSAndroid Build Coastguard Worker 333*cda5da8dSAndroid Build Coastguard Worker Data descriptors have a __set__ or a __delete__ attribute. Examples are 334*cda5da8dSAndroid Build Coastguard Worker properties (defined in Python) and getsets and members (defined in C). 335*cda5da8dSAndroid Build Coastguard Worker Typically, data descriptors will also have __name__ and __doc__ attributes 336*cda5da8dSAndroid Build Coastguard Worker (properties, getsets, and members have both of these attributes), but this 337*cda5da8dSAndroid Build Coastguard Worker is not guaranteed.""" 338*cda5da8dSAndroid Build Coastguard Worker if isclass(object) or ismethod(object) or isfunction(object): 339*cda5da8dSAndroid Build Coastguard Worker # mutual exclusion 340*cda5da8dSAndroid Build Coastguard Worker return False 341*cda5da8dSAndroid Build Coastguard Worker tp = type(object) 342*cda5da8dSAndroid Build Coastguard Worker return hasattr(tp, "__set__") or hasattr(tp, "__delete__") 343*cda5da8dSAndroid Build Coastguard Worker 344*cda5da8dSAndroid Build Coastguard Workerif hasattr(types, 'MemberDescriptorType'): 345*cda5da8dSAndroid Build Coastguard Worker # CPython and equivalent 346*cda5da8dSAndroid Build Coastguard Worker def ismemberdescriptor(object): 347*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a member descriptor. 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Worker Member descriptors are specialized descriptors defined in extension 350*cda5da8dSAndroid Build Coastguard Worker modules.""" 351*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.MemberDescriptorType) 352*cda5da8dSAndroid Build Coastguard Workerelse: 353*cda5da8dSAndroid Build Coastguard Worker # Other implementations 354*cda5da8dSAndroid Build Coastguard Worker def ismemberdescriptor(object): 355*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a member descriptor. 356*cda5da8dSAndroid Build Coastguard Worker 357*cda5da8dSAndroid Build Coastguard Worker Member descriptors are specialized descriptors defined in extension 358*cda5da8dSAndroid Build Coastguard Worker modules.""" 359*cda5da8dSAndroid Build Coastguard Worker return False 360*cda5da8dSAndroid Build Coastguard Worker 361*cda5da8dSAndroid Build Coastguard Workerif hasattr(types, 'GetSetDescriptorType'): 362*cda5da8dSAndroid Build Coastguard Worker # CPython and equivalent 363*cda5da8dSAndroid Build Coastguard Worker def isgetsetdescriptor(object): 364*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a getset descriptor. 365*cda5da8dSAndroid Build Coastguard Worker 366*cda5da8dSAndroid Build Coastguard Worker getset descriptors are specialized descriptors defined in extension 367*cda5da8dSAndroid Build Coastguard Worker modules.""" 368*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.GetSetDescriptorType) 369*cda5da8dSAndroid Build Coastguard Workerelse: 370*cda5da8dSAndroid Build Coastguard Worker # Other implementations 371*cda5da8dSAndroid Build Coastguard Worker def isgetsetdescriptor(object): 372*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a getset descriptor. 373*cda5da8dSAndroid Build Coastguard Worker 374*cda5da8dSAndroid Build Coastguard Worker getset descriptors are specialized descriptors defined in extension 375*cda5da8dSAndroid Build Coastguard Worker modules.""" 376*cda5da8dSAndroid Build Coastguard Worker return False 377*cda5da8dSAndroid Build Coastguard Worker 378*cda5da8dSAndroid Build Coastguard Workerdef isfunction(object): 379*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a user-defined function. 380*cda5da8dSAndroid Build Coastguard Worker 381*cda5da8dSAndroid Build Coastguard Worker Function objects provide these attributes: 382*cda5da8dSAndroid Build Coastguard Worker __doc__ documentation string 383*cda5da8dSAndroid Build Coastguard Worker __name__ name with which this function was defined 384*cda5da8dSAndroid Build Coastguard Worker __code__ code object containing compiled function bytecode 385*cda5da8dSAndroid Build Coastguard Worker __defaults__ tuple of any default values for arguments 386*cda5da8dSAndroid Build Coastguard Worker __globals__ global namespace in which this function was defined 387*cda5da8dSAndroid Build Coastguard Worker __annotations__ dict of parameter annotations 388*cda5da8dSAndroid Build Coastguard Worker __kwdefaults__ dict of keyword only parameters with defaults""" 389*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.FunctionType) 390*cda5da8dSAndroid Build Coastguard Worker 391*cda5da8dSAndroid Build Coastguard Workerdef _has_code_flag(f, flag): 392*cda5da8dSAndroid Build Coastguard Worker """Return true if ``f`` is a function (or a method or functools.partial 393*cda5da8dSAndroid Build Coastguard Worker wrapper wrapping a function) whose code object has the given ``flag`` 394*cda5da8dSAndroid Build Coastguard Worker set in its flags.""" 395*cda5da8dSAndroid Build Coastguard Worker while ismethod(f): 396*cda5da8dSAndroid Build Coastguard Worker f = f.__func__ 397*cda5da8dSAndroid Build Coastguard Worker f = functools._unwrap_partial(f) 398*cda5da8dSAndroid Build Coastguard Worker if not (isfunction(f) or _signature_is_functionlike(f)): 399*cda5da8dSAndroid Build Coastguard Worker return False 400*cda5da8dSAndroid Build Coastguard Worker return bool(f.__code__.co_flags & flag) 401*cda5da8dSAndroid Build Coastguard Worker 402*cda5da8dSAndroid Build Coastguard Workerdef isgeneratorfunction(obj): 403*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a user-defined generator function. 404*cda5da8dSAndroid Build Coastguard Worker 405*cda5da8dSAndroid Build Coastguard Worker Generator function objects provide the same attributes as functions. 406*cda5da8dSAndroid Build Coastguard Worker See help(isfunction) for a list of attributes.""" 407*cda5da8dSAndroid Build Coastguard Worker return _has_code_flag(obj, CO_GENERATOR) 408*cda5da8dSAndroid Build Coastguard Worker 409*cda5da8dSAndroid Build Coastguard Workerdef iscoroutinefunction(obj): 410*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a coroutine function. 411*cda5da8dSAndroid Build Coastguard Worker 412*cda5da8dSAndroid Build Coastguard Worker Coroutine functions are defined with "async def" syntax. 413*cda5da8dSAndroid Build Coastguard Worker """ 414*cda5da8dSAndroid Build Coastguard Worker return _has_code_flag(obj, CO_COROUTINE) 415*cda5da8dSAndroid Build Coastguard Worker 416*cda5da8dSAndroid Build Coastguard Workerdef isasyncgenfunction(obj): 417*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is an asynchronous generator function. 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker Asynchronous generator functions are defined with "async def" 420*cda5da8dSAndroid Build Coastguard Worker syntax and have "yield" expressions in their body. 421*cda5da8dSAndroid Build Coastguard Worker """ 422*cda5da8dSAndroid Build Coastguard Worker return _has_code_flag(obj, CO_ASYNC_GENERATOR) 423*cda5da8dSAndroid Build Coastguard Worker 424*cda5da8dSAndroid Build Coastguard Workerdef isasyncgen(object): 425*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is an asynchronous generator.""" 426*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.AsyncGeneratorType) 427*cda5da8dSAndroid Build Coastguard Worker 428*cda5da8dSAndroid Build Coastguard Workerdef isgenerator(object): 429*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a generator. 430*cda5da8dSAndroid Build Coastguard Worker 431*cda5da8dSAndroid Build Coastguard Worker Generator objects provide these attributes: 432*cda5da8dSAndroid Build Coastguard Worker __iter__ defined to support iteration over container 433*cda5da8dSAndroid Build Coastguard Worker close raises a new GeneratorExit exception inside the 434*cda5da8dSAndroid Build Coastguard Worker generator to terminate the iteration 435*cda5da8dSAndroid Build Coastguard Worker gi_code code object 436*cda5da8dSAndroid Build Coastguard Worker gi_frame frame object or possibly None once the generator has 437*cda5da8dSAndroid Build Coastguard Worker been exhausted 438*cda5da8dSAndroid Build Coastguard Worker gi_running set to 1 when generator is executing, 0 otherwise 439*cda5da8dSAndroid Build Coastguard Worker next return the next item from the container 440*cda5da8dSAndroid Build Coastguard Worker send resumes the generator and "sends" a value that becomes 441*cda5da8dSAndroid Build Coastguard Worker the result of the current yield-expression 442*cda5da8dSAndroid Build Coastguard Worker throw used to raise an exception inside the generator""" 443*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.GeneratorType) 444*cda5da8dSAndroid Build Coastguard Worker 445*cda5da8dSAndroid Build Coastguard Workerdef iscoroutine(object): 446*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a coroutine.""" 447*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.CoroutineType) 448*cda5da8dSAndroid Build Coastguard Worker 449*cda5da8dSAndroid Build Coastguard Workerdef isawaitable(object): 450*cda5da8dSAndroid Build Coastguard Worker """Return true if object can be passed to an ``await`` expression.""" 451*cda5da8dSAndroid Build Coastguard Worker return (isinstance(object, types.CoroutineType) or 452*cda5da8dSAndroid Build Coastguard Worker isinstance(object, types.GeneratorType) and 453*cda5da8dSAndroid Build Coastguard Worker bool(object.gi_code.co_flags & CO_ITERABLE_COROUTINE) or 454*cda5da8dSAndroid Build Coastguard Worker isinstance(object, collections.abc.Awaitable)) 455*cda5da8dSAndroid Build Coastguard Worker 456*cda5da8dSAndroid Build Coastguard Workerdef istraceback(object): 457*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a traceback. 458*cda5da8dSAndroid Build Coastguard Worker 459*cda5da8dSAndroid Build Coastguard Worker Traceback objects provide these attributes: 460*cda5da8dSAndroid Build Coastguard Worker tb_frame frame object at this level 461*cda5da8dSAndroid Build Coastguard Worker tb_lasti index of last attempted instruction in bytecode 462*cda5da8dSAndroid Build Coastguard Worker tb_lineno current line number in Python source code 463*cda5da8dSAndroid Build Coastguard Worker tb_next next inner traceback object (called by this level)""" 464*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.TracebackType) 465*cda5da8dSAndroid Build Coastguard Worker 466*cda5da8dSAndroid Build Coastguard Workerdef isframe(object): 467*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a frame object. 468*cda5da8dSAndroid Build Coastguard Worker 469*cda5da8dSAndroid Build Coastguard Worker Frame objects provide these attributes: 470*cda5da8dSAndroid Build Coastguard Worker f_back next outer frame object (this frame's caller) 471*cda5da8dSAndroid Build Coastguard Worker f_builtins built-in namespace seen by this frame 472*cda5da8dSAndroid Build Coastguard Worker f_code code object being executed in this frame 473*cda5da8dSAndroid Build Coastguard Worker f_globals global namespace seen by this frame 474*cda5da8dSAndroid Build Coastguard Worker f_lasti index of last attempted instruction in bytecode 475*cda5da8dSAndroid Build Coastguard Worker f_lineno current line number in Python source code 476*cda5da8dSAndroid Build Coastguard Worker f_locals local namespace seen by this frame 477*cda5da8dSAndroid Build Coastguard Worker f_trace tracing function for this frame, or None""" 478*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.FrameType) 479*cda5da8dSAndroid Build Coastguard Worker 480*cda5da8dSAndroid Build Coastguard Workerdef iscode(object): 481*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a code object. 482*cda5da8dSAndroid Build Coastguard Worker 483*cda5da8dSAndroid Build Coastguard Worker Code objects provide these attributes: 484*cda5da8dSAndroid Build Coastguard Worker co_argcount number of arguments (not including *, ** args 485*cda5da8dSAndroid Build Coastguard Worker or keyword only arguments) 486*cda5da8dSAndroid Build Coastguard Worker co_code string of raw compiled bytecode 487*cda5da8dSAndroid Build Coastguard Worker co_cellvars tuple of names of cell variables 488*cda5da8dSAndroid Build Coastguard Worker co_consts tuple of constants used in the bytecode 489*cda5da8dSAndroid Build Coastguard Worker co_filename name of file in which this code object was created 490*cda5da8dSAndroid Build Coastguard Worker co_firstlineno number of first line in Python source code 491*cda5da8dSAndroid Build Coastguard Worker co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg 492*cda5da8dSAndroid Build Coastguard Worker | 16=nested | 32=generator | 64=nofree | 128=coroutine 493*cda5da8dSAndroid Build Coastguard Worker | 256=iterable_coroutine | 512=async_generator 494*cda5da8dSAndroid Build Coastguard Worker co_freevars tuple of names of free variables 495*cda5da8dSAndroid Build Coastguard Worker co_posonlyargcount number of positional only arguments 496*cda5da8dSAndroid Build Coastguard Worker co_kwonlyargcount number of keyword only arguments (not including ** arg) 497*cda5da8dSAndroid Build Coastguard Worker co_lnotab encoded mapping of line numbers to bytecode indices 498*cda5da8dSAndroid Build Coastguard Worker co_name name with which this code object was defined 499*cda5da8dSAndroid Build Coastguard Worker co_names tuple of names other than arguments and function locals 500*cda5da8dSAndroid Build Coastguard Worker co_nlocals number of local variables 501*cda5da8dSAndroid Build Coastguard Worker co_stacksize virtual machine stack space required 502*cda5da8dSAndroid Build Coastguard Worker co_varnames tuple of names of arguments and local variables""" 503*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.CodeType) 504*cda5da8dSAndroid Build Coastguard Worker 505*cda5da8dSAndroid Build Coastguard Workerdef isbuiltin(object): 506*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a built-in function or method. 507*cda5da8dSAndroid Build Coastguard Worker 508*cda5da8dSAndroid Build Coastguard Worker Built-in functions and methods provide these attributes: 509*cda5da8dSAndroid Build Coastguard Worker __doc__ documentation string 510*cda5da8dSAndroid Build Coastguard Worker __name__ original name of this function or method 511*cda5da8dSAndroid Build Coastguard Worker __self__ instance to which a method is bound, or None""" 512*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.BuiltinFunctionType) 513*cda5da8dSAndroid Build Coastguard Worker 514*cda5da8dSAndroid Build Coastguard Workerdef ismethodwrapper(object): 515*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is a method wrapper.""" 516*cda5da8dSAndroid Build Coastguard Worker return isinstance(object, types.MethodWrapperType) 517*cda5da8dSAndroid Build Coastguard Worker 518*cda5da8dSAndroid Build Coastguard Workerdef isroutine(object): 519*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is any kind of function or method.""" 520*cda5da8dSAndroid Build Coastguard Worker return (isbuiltin(object) 521*cda5da8dSAndroid Build Coastguard Worker or isfunction(object) 522*cda5da8dSAndroid Build Coastguard Worker or ismethod(object) 523*cda5da8dSAndroid Build Coastguard Worker or ismethoddescriptor(object) 524*cda5da8dSAndroid Build Coastguard Worker or ismethodwrapper(object)) 525*cda5da8dSAndroid Build Coastguard Worker 526*cda5da8dSAndroid Build Coastguard Workerdef isabstract(object): 527*cda5da8dSAndroid Build Coastguard Worker """Return true if the object is an abstract base class (ABC).""" 528*cda5da8dSAndroid Build Coastguard Worker if not isinstance(object, type): 529*cda5da8dSAndroid Build Coastguard Worker return False 530*cda5da8dSAndroid Build Coastguard Worker if object.__flags__ & TPFLAGS_IS_ABSTRACT: 531*cda5da8dSAndroid Build Coastguard Worker return True 532*cda5da8dSAndroid Build Coastguard Worker if not issubclass(type(object), abc.ABCMeta): 533*cda5da8dSAndroid Build Coastguard Worker return False 534*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__abstractmethods__'): 535*cda5da8dSAndroid Build Coastguard Worker # It looks like ABCMeta.__new__ has finished running; 536*cda5da8dSAndroid Build Coastguard Worker # TPFLAGS_IS_ABSTRACT should have been accurate. 537*cda5da8dSAndroid Build Coastguard Worker return False 538*cda5da8dSAndroid Build Coastguard Worker # It looks like ABCMeta.__new__ has not finished running yet; we're 539*cda5da8dSAndroid Build Coastguard Worker # probably in __init_subclass__. We'll look for abstractmethods manually. 540*cda5da8dSAndroid Build Coastguard Worker for name, value in object.__dict__.items(): 541*cda5da8dSAndroid Build Coastguard Worker if getattr(value, "__isabstractmethod__", False): 542*cda5da8dSAndroid Build Coastguard Worker return True 543*cda5da8dSAndroid Build Coastguard Worker for base in object.__bases__: 544*cda5da8dSAndroid Build Coastguard Worker for name in getattr(base, "__abstractmethods__", ()): 545*cda5da8dSAndroid Build Coastguard Worker value = getattr(object, name, None) 546*cda5da8dSAndroid Build Coastguard Worker if getattr(value, "__isabstractmethod__", False): 547*cda5da8dSAndroid Build Coastguard Worker return True 548*cda5da8dSAndroid Build Coastguard Worker return False 549*cda5da8dSAndroid Build Coastguard Worker 550*cda5da8dSAndroid Build Coastguard Workerdef _getmembers(object, predicate, getter): 551*cda5da8dSAndroid Build Coastguard Worker results = [] 552*cda5da8dSAndroid Build Coastguard Worker processed = set() 553*cda5da8dSAndroid Build Coastguard Worker names = dir(object) 554*cda5da8dSAndroid Build Coastguard Worker if isclass(object): 555*cda5da8dSAndroid Build Coastguard Worker mro = (object,) + getmro(object) 556*cda5da8dSAndroid Build Coastguard Worker # add any DynamicClassAttributes to the list of names if object is a class; 557*cda5da8dSAndroid Build Coastguard Worker # this may result in duplicate entries if, for example, a virtual 558*cda5da8dSAndroid Build Coastguard Worker # attribute with the same name as a DynamicClassAttribute exists 559*cda5da8dSAndroid Build Coastguard Worker try: 560*cda5da8dSAndroid Build Coastguard Worker for base in object.__bases__: 561*cda5da8dSAndroid Build Coastguard Worker for k, v in base.__dict__.items(): 562*cda5da8dSAndroid Build Coastguard Worker if isinstance(v, types.DynamicClassAttribute): 563*cda5da8dSAndroid Build Coastguard Worker names.append(k) 564*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 565*cda5da8dSAndroid Build Coastguard Worker pass 566*cda5da8dSAndroid Build Coastguard Worker else: 567*cda5da8dSAndroid Build Coastguard Worker mro = () 568*cda5da8dSAndroid Build Coastguard Worker for key in names: 569*cda5da8dSAndroid Build Coastguard Worker # First try to get the value via getattr. Some descriptors don't 570*cda5da8dSAndroid Build Coastguard Worker # like calling their __get__ (see bug #1785), so fall back to 571*cda5da8dSAndroid Build Coastguard Worker # looking in the __dict__. 572*cda5da8dSAndroid Build Coastguard Worker try: 573*cda5da8dSAndroid Build Coastguard Worker value = getter(object, key) 574*cda5da8dSAndroid Build Coastguard Worker # handle the duplicate key 575*cda5da8dSAndroid Build Coastguard Worker if key in processed: 576*cda5da8dSAndroid Build Coastguard Worker raise AttributeError 577*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 578*cda5da8dSAndroid Build Coastguard Worker for base in mro: 579*cda5da8dSAndroid Build Coastguard Worker if key in base.__dict__: 580*cda5da8dSAndroid Build Coastguard Worker value = base.__dict__[key] 581*cda5da8dSAndroid Build Coastguard Worker break 582*cda5da8dSAndroid Build Coastguard Worker else: 583*cda5da8dSAndroid Build Coastguard Worker # could be a (currently) missing slot member, or a buggy 584*cda5da8dSAndroid Build Coastguard Worker # __dir__; discard and move on 585*cda5da8dSAndroid Build Coastguard Worker continue 586*cda5da8dSAndroid Build Coastguard Worker if not predicate or predicate(value): 587*cda5da8dSAndroid Build Coastguard Worker results.append((key, value)) 588*cda5da8dSAndroid Build Coastguard Worker processed.add(key) 589*cda5da8dSAndroid Build Coastguard Worker results.sort(key=lambda pair: pair[0]) 590*cda5da8dSAndroid Build Coastguard Worker return results 591*cda5da8dSAndroid Build Coastguard Worker 592*cda5da8dSAndroid Build Coastguard Workerdef getmembers(object, predicate=None): 593*cda5da8dSAndroid Build Coastguard Worker """Return all members of an object as (name, value) pairs sorted by name. 594*cda5da8dSAndroid Build Coastguard Worker Optionally, only return members that satisfy a given predicate.""" 595*cda5da8dSAndroid Build Coastguard Worker return _getmembers(object, predicate, getattr) 596*cda5da8dSAndroid Build Coastguard Worker 597*cda5da8dSAndroid Build Coastguard Workerdef getmembers_static(object, predicate=None): 598*cda5da8dSAndroid Build Coastguard Worker """Return all members of an object as (name, value) pairs sorted by name 599*cda5da8dSAndroid Build Coastguard Worker without triggering dynamic lookup via the descriptor protocol, 600*cda5da8dSAndroid Build Coastguard Worker __getattr__ or __getattribute__. Optionally, only return members that 601*cda5da8dSAndroid Build Coastguard Worker satisfy a given predicate. 602*cda5da8dSAndroid Build Coastguard Worker 603*cda5da8dSAndroid Build Coastguard Worker Note: this function may not be able to retrieve all members 604*cda5da8dSAndroid Build Coastguard Worker that getmembers can fetch (like dynamically created attributes) 605*cda5da8dSAndroid Build Coastguard Worker and may find members that getmembers can't (like descriptors 606*cda5da8dSAndroid Build Coastguard Worker that raise AttributeError). It can also return descriptor objects 607*cda5da8dSAndroid Build Coastguard Worker instead of instance members in some cases. 608*cda5da8dSAndroid Build Coastguard Worker """ 609*cda5da8dSAndroid Build Coastguard Worker return _getmembers(object, predicate, getattr_static) 610*cda5da8dSAndroid Build Coastguard Worker 611*cda5da8dSAndroid Build Coastguard WorkerAttribute = namedtuple('Attribute', 'name kind defining_class object') 612*cda5da8dSAndroid Build Coastguard Worker 613*cda5da8dSAndroid Build Coastguard Workerdef classify_class_attrs(cls): 614*cda5da8dSAndroid Build Coastguard Worker """Return list of attribute-descriptor tuples. 615*cda5da8dSAndroid Build Coastguard Worker 616*cda5da8dSAndroid Build Coastguard Worker For each name in dir(cls), the return list contains a 4-tuple 617*cda5da8dSAndroid Build Coastguard Worker with these elements: 618*cda5da8dSAndroid Build Coastguard Worker 619*cda5da8dSAndroid Build Coastguard Worker 0. The name (a string). 620*cda5da8dSAndroid Build Coastguard Worker 621*cda5da8dSAndroid Build Coastguard Worker 1. The kind of attribute this is, one of these strings: 622*cda5da8dSAndroid Build Coastguard Worker 'class method' created via classmethod() 623*cda5da8dSAndroid Build Coastguard Worker 'static method' created via staticmethod() 624*cda5da8dSAndroid Build Coastguard Worker 'property' created via property() 625*cda5da8dSAndroid Build Coastguard Worker 'method' any other flavor of method or descriptor 626*cda5da8dSAndroid Build Coastguard Worker 'data' not a method 627*cda5da8dSAndroid Build Coastguard Worker 628*cda5da8dSAndroid Build Coastguard Worker 2. The class which defined this attribute (a class). 629*cda5da8dSAndroid Build Coastguard Worker 630*cda5da8dSAndroid Build Coastguard Worker 3. The object as obtained by calling getattr; if this fails, or if the 631*cda5da8dSAndroid Build Coastguard Worker resulting object does not live anywhere in the class' mro (including 632*cda5da8dSAndroid Build Coastguard Worker metaclasses) then the object is looked up in the defining class's 633*cda5da8dSAndroid Build Coastguard Worker dict (found by walking the mro). 634*cda5da8dSAndroid Build Coastguard Worker 635*cda5da8dSAndroid Build Coastguard Worker If one of the items in dir(cls) is stored in the metaclass it will now 636*cda5da8dSAndroid Build Coastguard Worker be discovered and not have None be listed as the class in which it was 637*cda5da8dSAndroid Build Coastguard Worker defined. Any items whose home class cannot be discovered are skipped. 638*cda5da8dSAndroid Build Coastguard Worker """ 639*cda5da8dSAndroid Build Coastguard Worker 640*cda5da8dSAndroid Build Coastguard Worker mro = getmro(cls) 641*cda5da8dSAndroid Build Coastguard Worker metamro = getmro(type(cls)) # for attributes stored in the metaclass 642*cda5da8dSAndroid Build Coastguard Worker metamro = tuple(cls for cls in metamro if cls not in (type, object)) 643*cda5da8dSAndroid Build Coastguard Worker class_bases = (cls,) + mro 644*cda5da8dSAndroid Build Coastguard Worker all_bases = class_bases + metamro 645*cda5da8dSAndroid Build Coastguard Worker names = dir(cls) 646*cda5da8dSAndroid Build Coastguard Worker # :dd any DynamicClassAttributes to the list of names; 647*cda5da8dSAndroid Build Coastguard Worker # this may result in duplicate entries if, for example, a virtual 648*cda5da8dSAndroid Build Coastguard Worker # attribute with the same name as a DynamicClassAttribute exists. 649*cda5da8dSAndroid Build Coastguard Worker for base in mro: 650*cda5da8dSAndroid Build Coastguard Worker for k, v in base.__dict__.items(): 651*cda5da8dSAndroid Build Coastguard Worker if isinstance(v, types.DynamicClassAttribute) and v.fget is not None: 652*cda5da8dSAndroid Build Coastguard Worker names.append(k) 653*cda5da8dSAndroid Build Coastguard Worker result = [] 654*cda5da8dSAndroid Build Coastguard Worker processed = set() 655*cda5da8dSAndroid Build Coastguard Worker 656*cda5da8dSAndroid Build Coastguard Worker for name in names: 657*cda5da8dSAndroid Build Coastguard Worker # Get the object associated with the name, and where it was defined. 658*cda5da8dSAndroid Build Coastguard Worker # Normal objects will be looked up with both getattr and directly in 659*cda5da8dSAndroid Build Coastguard Worker # its class' dict (in case getattr fails [bug #1785], and also to look 660*cda5da8dSAndroid Build Coastguard Worker # for a docstring). 661*cda5da8dSAndroid Build Coastguard Worker # For DynamicClassAttributes on the second pass we only look in the 662*cda5da8dSAndroid Build Coastguard Worker # class's dict. 663*cda5da8dSAndroid Build Coastguard Worker # 664*cda5da8dSAndroid Build Coastguard Worker # Getting an obj from the __dict__ sometimes reveals more than 665*cda5da8dSAndroid Build Coastguard Worker # using getattr. Static and class methods are dramatic examples. 666*cda5da8dSAndroid Build Coastguard Worker homecls = None 667*cda5da8dSAndroid Build Coastguard Worker get_obj = None 668*cda5da8dSAndroid Build Coastguard Worker dict_obj = None 669*cda5da8dSAndroid Build Coastguard Worker if name not in processed: 670*cda5da8dSAndroid Build Coastguard Worker try: 671*cda5da8dSAndroid Build Coastguard Worker if name == '__dict__': 672*cda5da8dSAndroid Build Coastguard Worker raise Exception("__dict__ is special, don't want the proxy") 673*cda5da8dSAndroid Build Coastguard Worker get_obj = getattr(cls, name) 674*cda5da8dSAndroid Build Coastguard Worker except Exception as exc: 675*cda5da8dSAndroid Build Coastguard Worker pass 676*cda5da8dSAndroid Build Coastguard Worker else: 677*cda5da8dSAndroid Build Coastguard Worker homecls = getattr(get_obj, "__objclass__", homecls) 678*cda5da8dSAndroid Build Coastguard Worker if homecls not in class_bases: 679*cda5da8dSAndroid Build Coastguard Worker # if the resulting object does not live somewhere in the 680*cda5da8dSAndroid Build Coastguard Worker # mro, drop it and search the mro manually 681*cda5da8dSAndroid Build Coastguard Worker homecls = None 682*cda5da8dSAndroid Build Coastguard Worker last_cls = None 683*cda5da8dSAndroid Build Coastguard Worker # first look in the classes 684*cda5da8dSAndroid Build Coastguard Worker for srch_cls in class_bases: 685*cda5da8dSAndroid Build Coastguard Worker srch_obj = getattr(srch_cls, name, None) 686*cda5da8dSAndroid Build Coastguard Worker if srch_obj is get_obj: 687*cda5da8dSAndroid Build Coastguard Worker last_cls = srch_cls 688*cda5da8dSAndroid Build Coastguard Worker # then check the metaclasses 689*cda5da8dSAndroid Build Coastguard Worker for srch_cls in metamro: 690*cda5da8dSAndroid Build Coastguard Worker try: 691*cda5da8dSAndroid Build Coastguard Worker srch_obj = srch_cls.__getattr__(cls, name) 692*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 693*cda5da8dSAndroid Build Coastguard Worker continue 694*cda5da8dSAndroid Build Coastguard Worker if srch_obj is get_obj: 695*cda5da8dSAndroid Build Coastguard Worker last_cls = srch_cls 696*cda5da8dSAndroid Build Coastguard Worker if last_cls is not None: 697*cda5da8dSAndroid Build Coastguard Worker homecls = last_cls 698*cda5da8dSAndroid Build Coastguard Worker for base in all_bases: 699*cda5da8dSAndroid Build Coastguard Worker if name in base.__dict__: 700*cda5da8dSAndroid Build Coastguard Worker dict_obj = base.__dict__[name] 701*cda5da8dSAndroid Build Coastguard Worker if homecls not in metamro: 702*cda5da8dSAndroid Build Coastguard Worker homecls = base 703*cda5da8dSAndroid Build Coastguard Worker break 704*cda5da8dSAndroid Build Coastguard Worker if homecls is None: 705*cda5da8dSAndroid Build Coastguard Worker # unable to locate the attribute anywhere, most likely due to 706*cda5da8dSAndroid Build Coastguard Worker # buggy custom __dir__; discard and move on 707*cda5da8dSAndroid Build Coastguard Worker continue 708*cda5da8dSAndroid Build Coastguard Worker obj = get_obj if get_obj is not None else dict_obj 709*cda5da8dSAndroid Build Coastguard Worker # Classify the object or its descriptor. 710*cda5da8dSAndroid Build Coastguard Worker if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)): 711*cda5da8dSAndroid Build Coastguard Worker kind = "static method" 712*cda5da8dSAndroid Build Coastguard Worker obj = dict_obj 713*cda5da8dSAndroid Build Coastguard Worker elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)): 714*cda5da8dSAndroid Build Coastguard Worker kind = "class method" 715*cda5da8dSAndroid Build Coastguard Worker obj = dict_obj 716*cda5da8dSAndroid Build Coastguard Worker elif isinstance(dict_obj, property): 717*cda5da8dSAndroid Build Coastguard Worker kind = "property" 718*cda5da8dSAndroid Build Coastguard Worker obj = dict_obj 719*cda5da8dSAndroid Build Coastguard Worker elif isroutine(obj): 720*cda5da8dSAndroid Build Coastguard Worker kind = "method" 721*cda5da8dSAndroid Build Coastguard Worker else: 722*cda5da8dSAndroid Build Coastguard Worker kind = "data" 723*cda5da8dSAndroid Build Coastguard Worker result.append(Attribute(name, kind, homecls, obj)) 724*cda5da8dSAndroid Build Coastguard Worker processed.add(name) 725*cda5da8dSAndroid Build Coastguard Worker return result 726*cda5da8dSAndroid Build Coastguard Worker 727*cda5da8dSAndroid Build Coastguard Worker# ----------------------------------------------------------- class helpers 728*cda5da8dSAndroid Build Coastguard Worker 729*cda5da8dSAndroid Build Coastguard Workerdef getmro(cls): 730*cda5da8dSAndroid Build Coastguard Worker "Return tuple of base classes (including cls) in method resolution order." 731*cda5da8dSAndroid Build Coastguard Worker return cls.__mro__ 732*cda5da8dSAndroid Build Coastguard Worker 733*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------------------- function helpers 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Workerdef unwrap(func, *, stop=None): 736*cda5da8dSAndroid Build Coastguard Worker """Get the object wrapped by *func*. 737*cda5da8dSAndroid Build Coastguard Worker 738*cda5da8dSAndroid Build Coastguard Worker Follows the chain of :attr:`__wrapped__` attributes returning the last 739*cda5da8dSAndroid Build Coastguard Worker object in the chain. 740*cda5da8dSAndroid Build Coastguard Worker 741*cda5da8dSAndroid Build Coastguard Worker *stop* is an optional callback accepting an object in the wrapper chain 742*cda5da8dSAndroid Build Coastguard Worker as its sole argument that allows the unwrapping to be terminated early if 743*cda5da8dSAndroid Build Coastguard Worker the callback returns a true value. If the callback never returns a true 744*cda5da8dSAndroid Build Coastguard Worker value, the last object in the chain is returned as usual. For example, 745*cda5da8dSAndroid Build Coastguard Worker :func:`signature` uses this to stop unwrapping if any object in the 746*cda5da8dSAndroid Build Coastguard Worker chain has a ``__signature__`` attribute defined. 747*cda5da8dSAndroid Build Coastguard Worker 748*cda5da8dSAndroid Build Coastguard Worker :exc:`ValueError` is raised if a cycle is encountered. 749*cda5da8dSAndroid Build Coastguard Worker 750*cda5da8dSAndroid Build Coastguard Worker """ 751*cda5da8dSAndroid Build Coastguard Worker if stop is None: 752*cda5da8dSAndroid Build Coastguard Worker def _is_wrapper(f): 753*cda5da8dSAndroid Build Coastguard Worker return hasattr(f, '__wrapped__') 754*cda5da8dSAndroid Build Coastguard Worker else: 755*cda5da8dSAndroid Build Coastguard Worker def _is_wrapper(f): 756*cda5da8dSAndroid Build Coastguard Worker return hasattr(f, '__wrapped__') and not stop(f) 757*cda5da8dSAndroid Build Coastguard Worker f = func # remember the original func for error reporting 758*cda5da8dSAndroid Build Coastguard Worker # Memoise by id to tolerate non-hashable objects, but store objects to 759*cda5da8dSAndroid Build Coastguard Worker # ensure they aren't destroyed, which would allow their IDs to be reused. 760*cda5da8dSAndroid Build Coastguard Worker memo = {id(f): f} 761*cda5da8dSAndroid Build Coastguard Worker recursion_limit = sys.getrecursionlimit() 762*cda5da8dSAndroid Build Coastguard Worker while _is_wrapper(func): 763*cda5da8dSAndroid Build Coastguard Worker func = func.__wrapped__ 764*cda5da8dSAndroid Build Coastguard Worker id_func = id(func) 765*cda5da8dSAndroid Build Coastguard Worker if (id_func in memo) or (len(memo) >= recursion_limit): 766*cda5da8dSAndroid Build Coastguard Worker raise ValueError('wrapper loop when unwrapping {!r}'.format(f)) 767*cda5da8dSAndroid Build Coastguard Worker memo[id_func] = func 768*cda5da8dSAndroid Build Coastguard Worker return func 769*cda5da8dSAndroid Build Coastguard Worker 770*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------------- source code extraction 771*cda5da8dSAndroid Build Coastguard Workerdef indentsize(line): 772*cda5da8dSAndroid Build Coastguard Worker """Return the indent size, in spaces, at the start of a line of text.""" 773*cda5da8dSAndroid Build Coastguard Worker expline = line.expandtabs() 774*cda5da8dSAndroid Build Coastguard Worker return len(expline) - len(expline.lstrip()) 775*cda5da8dSAndroid Build Coastguard Worker 776*cda5da8dSAndroid Build Coastguard Workerdef _findclass(func): 777*cda5da8dSAndroid Build Coastguard Worker cls = sys.modules.get(func.__module__) 778*cda5da8dSAndroid Build Coastguard Worker if cls is None: 779*cda5da8dSAndroid Build Coastguard Worker return None 780*cda5da8dSAndroid Build Coastguard Worker for name in func.__qualname__.split('.')[:-1]: 781*cda5da8dSAndroid Build Coastguard Worker cls = getattr(cls, name) 782*cda5da8dSAndroid Build Coastguard Worker if not isclass(cls): 783*cda5da8dSAndroid Build Coastguard Worker return None 784*cda5da8dSAndroid Build Coastguard Worker return cls 785*cda5da8dSAndroid Build Coastguard Worker 786*cda5da8dSAndroid Build Coastguard Workerdef _finddoc(obj): 787*cda5da8dSAndroid Build Coastguard Worker if isclass(obj): 788*cda5da8dSAndroid Build Coastguard Worker for base in obj.__mro__: 789*cda5da8dSAndroid Build Coastguard Worker if base is not object: 790*cda5da8dSAndroid Build Coastguard Worker try: 791*cda5da8dSAndroid Build Coastguard Worker doc = base.__doc__ 792*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 793*cda5da8dSAndroid Build Coastguard Worker continue 794*cda5da8dSAndroid Build Coastguard Worker if doc is not None: 795*cda5da8dSAndroid Build Coastguard Worker return doc 796*cda5da8dSAndroid Build Coastguard Worker return None 797*cda5da8dSAndroid Build Coastguard Worker 798*cda5da8dSAndroid Build Coastguard Worker if ismethod(obj): 799*cda5da8dSAndroid Build Coastguard Worker name = obj.__func__.__name__ 800*cda5da8dSAndroid Build Coastguard Worker self = obj.__self__ 801*cda5da8dSAndroid Build Coastguard Worker if (isclass(self) and 802*cda5da8dSAndroid Build Coastguard Worker getattr(getattr(self, name, None), '__func__') is obj.__func__): 803*cda5da8dSAndroid Build Coastguard Worker # classmethod 804*cda5da8dSAndroid Build Coastguard Worker cls = self 805*cda5da8dSAndroid Build Coastguard Worker else: 806*cda5da8dSAndroid Build Coastguard Worker cls = self.__class__ 807*cda5da8dSAndroid Build Coastguard Worker elif isfunction(obj): 808*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 809*cda5da8dSAndroid Build Coastguard Worker cls = _findclass(obj) 810*cda5da8dSAndroid Build Coastguard Worker if cls is None or getattr(cls, name) is not obj: 811*cda5da8dSAndroid Build Coastguard Worker return None 812*cda5da8dSAndroid Build Coastguard Worker elif isbuiltin(obj): 813*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 814*cda5da8dSAndroid Build Coastguard Worker self = obj.__self__ 815*cda5da8dSAndroid Build Coastguard Worker if (isclass(self) and 816*cda5da8dSAndroid Build Coastguard Worker self.__qualname__ + '.' + name == obj.__qualname__): 817*cda5da8dSAndroid Build Coastguard Worker # classmethod 818*cda5da8dSAndroid Build Coastguard Worker cls = self 819*cda5da8dSAndroid Build Coastguard Worker else: 820*cda5da8dSAndroid Build Coastguard Worker cls = self.__class__ 821*cda5da8dSAndroid Build Coastguard Worker # Should be tested before isdatadescriptor(). 822*cda5da8dSAndroid Build Coastguard Worker elif isinstance(obj, property): 823*cda5da8dSAndroid Build Coastguard Worker func = obj.fget 824*cda5da8dSAndroid Build Coastguard Worker name = func.__name__ 825*cda5da8dSAndroid Build Coastguard Worker cls = _findclass(func) 826*cda5da8dSAndroid Build Coastguard Worker if cls is None or getattr(cls, name) is not obj: 827*cda5da8dSAndroid Build Coastguard Worker return None 828*cda5da8dSAndroid Build Coastguard Worker elif ismethoddescriptor(obj) or isdatadescriptor(obj): 829*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 830*cda5da8dSAndroid Build Coastguard Worker cls = obj.__objclass__ 831*cda5da8dSAndroid Build Coastguard Worker if getattr(cls, name) is not obj: 832*cda5da8dSAndroid Build Coastguard Worker return None 833*cda5da8dSAndroid Build Coastguard Worker if ismemberdescriptor(obj): 834*cda5da8dSAndroid Build Coastguard Worker slots = getattr(cls, '__slots__', None) 835*cda5da8dSAndroid Build Coastguard Worker if isinstance(slots, dict) and name in slots: 836*cda5da8dSAndroid Build Coastguard Worker return slots[name] 837*cda5da8dSAndroid Build Coastguard Worker else: 838*cda5da8dSAndroid Build Coastguard Worker return None 839*cda5da8dSAndroid Build Coastguard Worker for base in cls.__mro__: 840*cda5da8dSAndroid Build Coastguard Worker try: 841*cda5da8dSAndroid Build Coastguard Worker doc = getattr(base, name).__doc__ 842*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 843*cda5da8dSAndroid Build Coastguard Worker continue 844*cda5da8dSAndroid Build Coastguard Worker if doc is not None: 845*cda5da8dSAndroid Build Coastguard Worker return doc 846*cda5da8dSAndroid Build Coastguard Worker return None 847*cda5da8dSAndroid Build Coastguard Worker 848*cda5da8dSAndroid Build Coastguard Workerdef getdoc(object): 849*cda5da8dSAndroid Build Coastguard Worker """Get the documentation string for an object. 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Worker All tabs are expanded to spaces. To clean up docstrings that are 852*cda5da8dSAndroid Build Coastguard Worker indented to line up with blocks of code, any whitespace than can be 853*cda5da8dSAndroid Build Coastguard Worker uniformly removed from the second line onwards is removed.""" 854*cda5da8dSAndroid Build Coastguard Worker try: 855*cda5da8dSAndroid Build Coastguard Worker doc = object.__doc__ 856*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 857*cda5da8dSAndroid Build Coastguard Worker return None 858*cda5da8dSAndroid Build Coastguard Worker if doc is None: 859*cda5da8dSAndroid Build Coastguard Worker try: 860*cda5da8dSAndroid Build Coastguard Worker doc = _finddoc(object) 861*cda5da8dSAndroid Build Coastguard Worker except (AttributeError, TypeError): 862*cda5da8dSAndroid Build Coastguard Worker return None 863*cda5da8dSAndroid Build Coastguard Worker if not isinstance(doc, str): 864*cda5da8dSAndroid Build Coastguard Worker return None 865*cda5da8dSAndroid Build Coastguard Worker return cleandoc(doc) 866*cda5da8dSAndroid Build Coastguard Worker 867*cda5da8dSAndroid Build Coastguard Workerdef cleandoc(doc): 868*cda5da8dSAndroid Build Coastguard Worker """Clean up indentation from docstrings. 869*cda5da8dSAndroid Build Coastguard Worker 870*cda5da8dSAndroid Build Coastguard Worker Any whitespace that can be uniformly removed from the second line 871*cda5da8dSAndroid Build Coastguard Worker onwards is removed.""" 872*cda5da8dSAndroid Build Coastguard Worker try: 873*cda5da8dSAndroid Build Coastguard Worker lines = doc.expandtabs().split('\n') 874*cda5da8dSAndroid Build Coastguard Worker except UnicodeError: 875*cda5da8dSAndroid Build Coastguard Worker return None 876*cda5da8dSAndroid Build Coastguard Worker else: 877*cda5da8dSAndroid Build Coastguard Worker # Find minimum indentation of any non-blank lines after first line. 878*cda5da8dSAndroid Build Coastguard Worker margin = sys.maxsize 879*cda5da8dSAndroid Build Coastguard Worker for line in lines[1:]: 880*cda5da8dSAndroid Build Coastguard Worker content = len(line.lstrip()) 881*cda5da8dSAndroid Build Coastguard Worker if content: 882*cda5da8dSAndroid Build Coastguard Worker indent = len(line) - content 883*cda5da8dSAndroid Build Coastguard Worker margin = min(margin, indent) 884*cda5da8dSAndroid Build Coastguard Worker # Remove indentation. 885*cda5da8dSAndroid Build Coastguard Worker if lines: 886*cda5da8dSAndroid Build Coastguard Worker lines[0] = lines[0].lstrip() 887*cda5da8dSAndroid Build Coastguard Worker if margin < sys.maxsize: 888*cda5da8dSAndroid Build Coastguard Worker for i in range(1, len(lines)): lines[i] = lines[i][margin:] 889*cda5da8dSAndroid Build Coastguard Worker # Remove any trailing or leading blank lines. 890*cda5da8dSAndroid Build Coastguard Worker while lines and not lines[-1]: 891*cda5da8dSAndroid Build Coastguard Worker lines.pop() 892*cda5da8dSAndroid Build Coastguard Worker while lines and not lines[0]: 893*cda5da8dSAndroid Build Coastguard Worker lines.pop(0) 894*cda5da8dSAndroid Build Coastguard Worker return '\n'.join(lines) 895*cda5da8dSAndroid Build Coastguard Worker 896*cda5da8dSAndroid Build Coastguard Workerdef getfile(object): 897*cda5da8dSAndroid Build Coastguard Worker """Work out which source or compiled file an object was defined in.""" 898*cda5da8dSAndroid Build Coastguard Worker if ismodule(object): 899*cda5da8dSAndroid Build Coastguard Worker if getattr(object, '__file__', None): 900*cda5da8dSAndroid Build Coastguard Worker return object.__file__ 901*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is a built-in module'.format(object)) 902*cda5da8dSAndroid Build Coastguard Worker if isclass(object): 903*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__module__'): 904*cda5da8dSAndroid Build Coastguard Worker module = sys.modules.get(object.__module__) 905*cda5da8dSAndroid Build Coastguard Worker if getattr(module, '__file__', None): 906*cda5da8dSAndroid Build Coastguard Worker return module.__file__ 907*cda5da8dSAndroid Build Coastguard Worker if object.__module__ == '__main__': 908*cda5da8dSAndroid Build Coastguard Worker raise OSError('source code not available') 909*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is a built-in class'.format(object)) 910*cda5da8dSAndroid Build Coastguard Worker if ismethod(object): 911*cda5da8dSAndroid Build Coastguard Worker object = object.__func__ 912*cda5da8dSAndroid Build Coastguard Worker if isfunction(object): 913*cda5da8dSAndroid Build Coastguard Worker object = object.__code__ 914*cda5da8dSAndroid Build Coastguard Worker if istraceback(object): 915*cda5da8dSAndroid Build Coastguard Worker object = object.tb_frame 916*cda5da8dSAndroid Build Coastguard Worker if isframe(object): 917*cda5da8dSAndroid Build Coastguard Worker object = object.f_code 918*cda5da8dSAndroid Build Coastguard Worker if iscode(object): 919*cda5da8dSAndroid Build Coastguard Worker return object.co_filename 920*cda5da8dSAndroid Build Coastguard Worker raise TypeError('module, class, method, function, traceback, frame, or ' 921*cda5da8dSAndroid Build Coastguard Worker 'code object was expected, got {}'.format( 922*cda5da8dSAndroid Build Coastguard Worker type(object).__name__)) 923*cda5da8dSAndroid Build Coastguard Worker 924*cda5da8dSAndroid Build Coastguard Workerdef getmodulename(path): 925*cda5da8dSAndroid Build Coastguard Worker """Return the module name for a given file, or None.""" 926*cda5da8dSAndroid Build Coastguard Worker fname = os.path.basename(path) 927*cda5da8dSAndroid Build Coastguard Worker # Check for paths that look like an actual module file 928*cda5da8dSAndroid Build Coastguard Worker suffixes = [(-len(suffix), suffix) 929*cda5da8dSAndroid Build Coastguard Worker for suffix in importlib.machinery.all_suffixes()] 930*cda5da8dSAndroid Build Coastguard Worker suffixes.sort() # try longest suffixes first, in case they overlap 931*cda5da8dSAndroid Build Coastguard Worker for neglen, suffix in suffixes: 932*cda5da8dSAndroid Build Coastguard Worker if fname.endswith(suffix): 933*cda5da8dSAndroid Build Coastguard Worker return fname[:neglen] 934*cda5da8dSAndroid Build Coastguard Worker return None 935*cda5da8dSAndroid Build Coastguard Worker 936*cda5da8dSAndroid Build Coastguard Workerdef getsourcefile(object): 937*cda5da8dSAndroid Build Coastguard Worker """Return the filename that can be used to locate an object's source. 938*cda5da8dSAndroid Build Coastguard Worker Return None if no way can be identified to get the source. 939*cda5da8dSAndroid Build Coastguard Worker """ 940*cda5da8dSAndroid Build Coastguard Worker filename = getfile(object) 941*cda5da8dSAndroid Build Coastguard Worker all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:] 942*cda5da8dSAndroid Build Coastguard Worker all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:] 943*cda5da8dSAndroid Build Coastguard Worker if any(filename.endswith(s) for s in all_bytecode_suffixes): 944*cda5da8dSAndroid Build Coastguard Worker filename = (os.path.splitext(filename)[0] + 945*cda5da8dSAndroid Build Coastguard Worker importlib.machinery.SOURCE_SUFFIXES[0]) 946*cda5da8dSAndroid Build Coastguard Worker elif any(filename.endswith(s) for s in 947*cda5da8dSAndroid Build Coastguard Worker importlib.machinery.EXTENSION_SUFFIXES): 948*cda5da8dSAndroid Build Coastguard Worker return None 949*cda5da8dSAndroid Build Coastguard Worker if os.path.exists(filename): 950*cda5da8dSAndroid Build Coastguard Worker return filename 951*cda5da8dSAndroid Build Coastguard Worker # only return a non-existent filename if the module has a PEP 302 loader 952*cda5da8dSAndroid Build Coastguard Worker module = getmodule(object, filename) 953*cda5da8dSAndroid Build Coastguard Worker if getattr(module, '__loader__', None) is not None: 954*cda5da8dSAndroid Build Coastguard Worker return filename 955*cda5da8dSAndroid Build Coastguard Worker elif getattr(getattr(module, "__spec__", None), "loader", None) is not None: 956*cda5da8dSAndroid Build Coastguard Worker return filename 957*cda5da8dSAndroid Build Coastguard Worker # or it is in the linecache 958*cda5da8dSAndroid Build Coastguard Worker elif filename in linecache.cache: 959*cda5da8dSAndroid Build Coastguard Worker return filename 960*cda5da8dSAndroid Build Coastguard Worker 961*cda5da8dSAndroid Build Coastguard Workerdef getabsfile(object, _filename=None): 962*cda5da8dSAndroid Build Coastguard Worker """Return an absolute path to the source or compiled file for an object. 963*cda5da8dSAndroid Build Coastguard Worker 964*cda5da8dSAndroid Build Coastguard Worker The idea is for each object to have a unique origin, so this routine 965*cda5da8dSAndroid Build Coastguard Worker normalizes the result as much as possible.""" 966*cda5da8dSAndroid Build Coastguard Worker if _filename is None: 967*cda5da8dSAndroid Build Coastguard Worker _filename = getsourcefile(object) or getfile(object) 968*cda5da8dSAndroid Build Coastguard Worker return os.path.normcase(os.path.abspath(_filename)) 969*cda5da8dSAndroid Build Coastguard Worker 970*cda5da8dSAndroid Build Coastguard Workermodulesbyfile = {} 971*cda5da8dSAndroid Build Coastguard Worker_filesbymodname = {} 972*cda5da8dSAndroid Build Coastguard Worker 973*cda5da8dSAndroid Build Coastguard Workerdef getmodule(object, _filename=None): 974*cda5da8dSAndroid Build Coastguard Worker """Return the module an object was defined in, or None if not found.""" 975*cda5da8dSAndroid Build Coastguard Worker if ismodule(object): 976*cda5da8dSAndroid Build Coastguard Worker return object 977*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__module__'): 978*cda5da8dSAndroid Build Coastguard Worker return sys.modules.get(object.__module__) 979*cda5da8dSAndroid Build Coastguard Worker # Try the filename to modulename cache 980*cda5da8dSAndroid Build Coastguard Worker if _filename is not None and _filename in modulesbyfile: 981*cda5da8dSAndroid Build Coastguard Worker return sys.modules.get(modulesbyfile[_filename]) 982*cda5da8dSAndroid Build Coastguard Worker # Try the cache again with the absolute file name 983*cda5da8dSAndroid Build Coastguard Worker try: 984*cda5da8dSAndroid Build Coastguard Worker file = getabsfile(object, _filename) 985*cda5da8dSAndroid Build Coastguard Worker except (TypeError, FileNotFoundError): 986*cda5da8dSAndroid Build Coastguard Worker return None 987*cda5da8dSAndroid Build Coastguard Worker if file in modulesbyfile: 988*cda5da8dSAndroid Build Coastguard Worker return sys.modules.get(modulesbyfile[file]) 989*cda5da8dSAndroid Build Coastguard Worker # Update the filename to module name cache and check yet again 990*cda5da8dSAndroid Build Coastguard Worker # Copy sys.modules in order to cope with changes while iterating 991*cda5da8dSAndroid Build Coastguard Worker for modname, module in sys.modules.copy().items(): 992*cda5da8dSAndroid Build Coastguard Worker if ismodule(module) and hasattr(module, '__file__'): 993*cda5da8dSAndroid Build Coastguard Worker f = module.__file__ 994*cda5da8dSAndroid Build Coastguard Worker if f == _filesbymodname.get(modname, None): 995*cda5da8dSAndroid Build Coastguard Worker # Have already mapped this module, so skip it 996*cda5da8dSAndroid Build Coastguard Worker continue 997*cda5da8dSAndroid Build Coastguard Worker _filesbymodname[modname] = f 998*cda5da8dSAndroid Build Coastguard Worker f = getabsfile(module) 999*cda5da8dSAndroid Build Coastguard Worker # Always map to the name the module knows itself by 1000*cda5da8dSAndroid Build Coastguard Worker modulesbyfile[f] = modulesbyfile[ 1001*cda5da8dSAndroid Build Coastguard Worker os.path.realpath(f)] = module.__name__ 1002*cda5da8dSAndroid Build Coastguard Worker if file in modulesbyfile: 1003*cda5da8dSAndroid Build Coastguard Worker return sys.modules.get(modulesbyfile[file]) 1004*cda5da8dSAndroid Build Coastguard Worker # Check the main module 1005*cda5da8dSAndroid Build Coastguard Worker main = sys.modules['__main__'] 1006*cda5da8dSAndroid Build Coastguard Worker if not hasattr(object, '__name__'): 1007*cda5da8dSAndroid Build Coastguard Worker return None 1008*cda5da8dSAndroid Build Coastguard Worker if hasattr(main, object.__name__): 1009*cda5da8dSAndroid Build Coastguard Worker mainobject = getattr(main, object.__name__) 1010*cda5da8dSAndroid Build Coastguard Worker if mainobject is object: 1011*cda5da8dSAndroid Build Coastguard Worker return main 1012*cda5da8dSAndroid Build Coastguard Worker # Check builtins 1013*cda5da8dSAndroid Build Coastguard Worker builtin = sys.modules['builtins'] 1014*cda5da8dSAndroid Build Coastguard Worker if hasattr(builtin, object.__name__): 1015*cda5da8dSAndroid Build Coastguard Worker builtinobject = getattr(builtin, object.__name__) 1016*cda5da8dSAndroid Build Coastguard Worker if builtinobject is object: 1017*cda5da8dSAndroid Build Coastguard Worker return builtin 1018*cda5da8dSAndroid Build Coastguard Worker 1019*cda5da8dSAndroid Build Coastguard Worker 1020*cda5da8dSAndroid Build Coastguard Workerclass ClassFoundException(Exception): 1021*cda5da8dSAndroid Build Coastguard Worker pass 1022*cda5da8dSAndroid Build Coastguard Worker 1023*cda5da8dSAndroid Build Coastguard Worker 1024*cda5da8dSAndroid Build Coastguard Workerclass _ClassFinder(ast.NodeVisitor): 1025*cda5da8dSAndroid Build Coastguard Worker 1026*cda5da8dSAndroid Build Coastguard Worker def __init__(self, qualname): 1027*cda5da8dSAndroid Build Coastguard Worker self.stack = [] 1028*cda5da8dSAndroid Build Coastguard Worker self.qualname = qualname 1029*cda5da8dSAndroid Build Coastguard Worker 1030*cda5da8dSAndroid Build Coastguard Worker def visit_FunctionDef(self, node): 1031*cda5da8dSAndroid Build Coastguard Worker self.stack.append(node.name) 1032*cda5da8dSAndroid Build Coastguard Worker self.stack.append('<locals>') 1033*cda5da8dSAndroid Build Coastguard Worker self.generic_visit(node) 1034*cda5da8dSAndroid Build Coastguard Worker self.stack.pop() 1035*cda5da8dSAndroid Build Coastguard Worker self.stack.pop() 1036*cda5da8dSAndroid Build Coastguard Worker 1037*cda5da8dSAndroid Build Coastguard Worker visit_AsyncFunctionDef = visit_FunctionDef 1038*cda5da8dSAndroid Build Coastguard Worker 1039*cda5da8dSAndroid Build Coastguard Worker def visit_ClassDef(self, node): 1040*cda5da8dSAndroid Build Coastguard Worker self.stack.append(node.name) 1041*cda5da8dSAndroid Build Coastguard Worker if self.qualname == '.'.join(self.stack): 1042*cda5da8dSAndroid Build Coastguard Worker # Return the decorator for the class if present 1043*cda5da8dSAndroid Build Coastguard Worker if node.decorator_list: 1044*cda5da8dSAndroid Build Coastguard Worker line_number = node.decorator_list[0].lineno 1045*cda5da8dSAndroid Build Coastguard Worker else: 1046*cda5da8dSAndroid Build Coastguard Worker line_number = node.lineno 1047*cda5da8dSAndroid Build Coastguard Worker 1048*cda5da8dSAndroid Build Coastguard Worker # decrement by one since lines starts with indexing by zero 1049*cda5da8dSAndroid Build Coastguard Worker line_number -= 1 1050*cda5da8dSAndroid Build Coastguard Worker raise ClassFoundException(line_number) 1051*cda5da8dSAndroid Build Coastguard Worker self.generic_visit(node) 1052*cda5da8dSAndroid Build Coastguard Worker self.stack.pop() 1053*cda5da8dSAndroid Build Coastguard Worker 1054*cda5da8dSAndroid Build Coastguard Worker 1055*cda5da8dSAndroid Build Coastguard Workerdef findsource(object): 1056*cda5da8dSAndroid Build Coastguard Worker """Return the entire source file and starting line number for an object. 1057*cda5da8dSAndroid Build Coastguard Worker 1058*cda5da8dSAndroid Build Coastguard Worker The argument may be a module, class, method, function, traceback, frame, 1059*cda5da8dSAndroid Build Coastguard Worker or code object. The source code is returned as a list of all the lines 1060*cda5da8dSAndroid Build Coastguard Worker in the file and the line number indexes a line in that list. An OSError 1061*cda5da8dSAndroid Build Coastguard Worker is raised if the source code cannot be retrieved.""" 1062*cda5da8dSAndroid Build Coastguard Worker 1063*cda5da8dSAndroid Build Coastguard Worker file = getsourcefile(object) 1064*cda5da8dSAndroid Build Coastguard Worker if file: 1065*cda5da8dSAndroid Build Coastguard Worker # Invalidate cache if needed. 1066*cda5da8dSAndroid Build Coastguard Worker linecache.checkcache(file) 1067*cda5da8dSAndroid Build Coastguard Worker else: 1068*cda5da8dSAndroid Build Coastguard Worker file = getfile(object) 1069*cda5da8dSAndroid Build Coastguard Worker # Allow filenames in form of "<something>" to pass through. 1070*cda5da8dSAndroid Build Coastguard Worker # `doctest` monkeypatches `linecache` module to enable 1071*cda5da8dSAndroid Build Coastguard Worker # inspection, so let `linecache.getlines` to be called. 1072*cda5da8dSAndroid Build Coastguard Worker if not (file.startswith('<') and file.endswith('>')): 1073*cda5da8dSAndroid Build Coastguard Worker raise OSError('source code not available') 1074*cda5da8dSAndroid Build Coastguard Worker 1075*cda5da8dSAndroid Build Coastguard Worker module = getmodule(object, file) 1076*cda5da8dSAndroid Build Coastguard Worker if module: 1077*cda5da8dSAndroid Build Coastguard Worker lines = linecache.getlines(file, module.__dict__) 1078*cda5da8dSAndroid Build Coastguard Worker else: 1079*cda5da8dSAndroid Build Coastguard Worker lines = linecache.getlines(file) 1080*cda5da8dSAndroid Build Coastguard Worker if not lines: 1081*cda5da8dSAndroid Build Coastguard Worker raise OSError('could not get source code') 1082*cda5da8dSAndroid Build Coastguard Worker 1083*cda5da8dSAndroid Build Coastguard Worker if ismodule(object): 1084*cda5da8dSAndroid Build Coastguard Worker return lines, 0 1085*cda5da8dSAndroid Build Coastguard Worker 1086*cda5da8dSAndroid Build Coastguard Worker if isclass(object): 1087*cda5da8dSAndroid Build Coastguard Worker qualname = object.__qualname__ 1088*cda5da8dSAndroid Build Coastguard Worker source = ''.join(lines) 1089*cda5da8dSAndroid Build Coastguard Worker tree = ast.parse(source) 1090*cda5da8dSAndroid Build Coastguard Worker class_finder = _ClassFinder(qualname) 1091*cda5da8dSAndroid Build Coastguard Worker try: 1092*cda5da8dSAndroid Build Coastguard Worker class_finder.visit(tree) 1093*cda5da8dSAndroid Build Coastguard Worker except ClassFoundException as e: 1094*cda5da8dSAndroid Build Coastguard Worker line_number = e.args[0] 1095*cda5da8dSAndroid Build Coastguard Worker return lines, line_number 1096*cda5da8dSAndroid Build Coastguard Worker else: 1097*cda5da8dSAndroid Build Coastguard Worker raise OSError('could not find class definition') 1098*cda5da8dSAndroid Build Coastguard Worker 1099*cda5da8dSAndroid Build Coastguard Worker if ismethod(object): 1100*cda5da8dSAndroid Build Coastguard Worker object = object.__func__ 1101*cda5da8dSAndroid Build Coastguard Worker if isfunction(object): 1102*cda5da8dSAndroid Build Coastguard Worker object = object.__code__ 1103*cda5da8dSAndroid Build Coastguard Worker if istraceback(object): 1104*cda5da8dSAndroid Build Coastguard Worker object = object.tb_frame 1105*cda5da8dSAndroid Build Coastguard Worker if isframe(object): 1106*cda5da8dSAndroid Build Coastguard Worker object = object.f_code 1107*cda5da8dSAndroid Build Coastguard Worker if iscode(object): 1108*cda5da8dSAndroid Build Coastguard Worker if not hasattr(object, 'co_firstlineno'): 1109*cda5da8dSAndroid Build Coastguard Worker raise OSError('could not find function definition') 1110*cda5da8dSAndroid Build Coastguard Worker lnum = object.co_firstlineno - 1 1111*cda5da8dSAndroid Build Coastguard Worker pat = re.compile(r'^(\s*def\s)|(\s*async\s+def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)') 1112*cda5da8dSAndroid Build Coastguard Worker while lnum > 0: 1113*cda5da8dSAndroid Build Coastguard Worker try: 1114*cda5da8dSAndroid Build Coastguard Worker line = lines[lnum] 1115*cda5da8dSAndroid Build Coastguard Worker except IndexError: 1116*cda5da8dSAndroid Build Coastguard Worker raise OSError('lineno is out of bounds') 1117*cda5da8dSAndroid Build Coastguard Worker if pat.match(line): 1118*cda5da8dSAndroid Build Coastguard Worker break 1119*cda5da8dSAndroid Build Coastguard Worker lnum = lnum - 1 1120*cda5da8dSAndroid Build Coastguard Worker return lines, lnum 1121*cda5da8dSAndroid Build Coastguard Worker raise OSError('could not find code object') 1122*cda5da8dSAndroid Build Coastguard Worker 1123*cda5da8dSAndroid Build Coastguard Workerdef getcomments(object): 1124*cda5da8dSAndroid Build Coastguard Worker """Get lines of comments immediately preceding an object's source code. 1125*cda5da8dSAndroid Build Coastguard Worker 1126*cda5da8dSAndroid Build Coastguard Worker Returns None when source can't be found. 1127*cda5da8dSAndroid Build Coastguard Worker """ 1128*cda5da8dSAndroid Build Coastguard Worker try: 1129*cda5da8dSAndroid Build Coastguard Worker lines, lnum = findsource(object) 1130*cda5da8dSAndroid Build Coastguard Worker except (OSError, TypeError): 1131*cda5da8dSAndroid Build Coastguard Worker return None 1132*cda5da8dSAndroid Build Coastguard Worker 1133*cda5da8dSAndroid Build Coastguard Worker if ismodule(object): 1134*cda5da8dSAndroid Build Coastguard Worker # Look for a comment block at the top of the file. 1135*cda5da8dSAndroid Build Coastguard Worker start = 0 1136*cda5da8dSAndroid Build Coastguard Worker if lines and lines[0][:2] == '#!': start = 1 1137*cda5da8dSAndroid Build Coastguard Worker while start < len(lines) and lines[start].strip() in ('', '#'): 1138*cda5da8dSAndroid Build Coastguard Worker start = start + 1 1139*cda5da8dSAndroid Build Coastguard Worker if start < len(lines) and lines[start][:1] == '#': 1140*cda5da8dSAndroid Build Coastguard Worker comments = [] 1141*cda5da8dSAndroid Build Coastguard Worker end = start 1142*cda5da8dSAndroid Build Coastguard Worker while end < len(lines) and lines[end][:1] == '#': 1143*cda5da8dSAndroid Build Coastguard Worker comments.append(lines[end].expandtabs()) 1144*cda5da8dSAndroid Build Coastguard Worker end = end + 1 1145*cda5da8dSAndroid Build Coastguard Worker return ''.join(comments) 1146*cda5da8dSAndroid Build Coastguard Worker 1147*cda5da8dSAndroid Build Coastguard Worker # Look for a preceding block of comments at the same indentation. 1148*cda5da8dSAndroid Build Coastguard Worker elif lnum > 0: 1149*cda5da8dSAndroid Build Coastguard Worker indent = indentsize(lines[lnum]) 1150*cda5da8dSAndroid Build Coastguard Worker end = lnum - 1 1151*cda5da8dSAndroid Build Coastguard Worker if end >= 0 and lines[end].lstrip()[:1] == '#' and \ 1152*cda5da8dSAndroid Build Coastguard Worker indentsize(lines[end]) == indent: 1153*cda5da8dSAndroid Build Coastguard Worker comments = [lines[end].expandtabs().lstrip()] 1154*cda5da8dSAndroid Build Coastguard Worker if end > 0: 1155*cda5da8dSAndroid Build Coastguard Worker end = end - 1 1156*cda5da8dSAndroid Build Coastguard Worker comment = lines[end].expandtabs().lstrip() 1157*cda5da8dSAndroid Build Coastguard Worker while comment[:1] == '#' and indentsize(lines[end]) == indent: 1158*cda5da8dSAndroid Build Coastguard Worker comments[:0] = [comment] 1159*cda5da8dSAndroid Build Coastguard Worker end = end - 1 1160*cda5da8dSAndroid Build Coastguard Worker if end < 0: break 1161*cda5da8dSAndroid Build Coastguard Worker comment = lines[end].expandtabs().lstrip() 1162*cda5da8dSAndroid Build Coastguard Worker while comments and comments[0].strip() == '#': 1163*cda5da8dSAndroid Build Coastguard Worker comments[:1] = [] 1164*cda5da8dSAndroid Build Coastguard Worker while comments and comments[-1].strip() == '#': 1165*cda5da8dSAndroid Build Coastguard Worker comments[-1:] = [] 1166*cda5da8dSAndroid Build Coastguard Worker return ''.join(comments) 1167*cda5da8dSAndroid Build Coastguard Worker 1168*cda5da8dSAndroid Build Coastguard Workerclass EndOfBlock(Exception): pass 1169*cda5da8dSAndroid Build Coastguard Worker 1170*cda5da8dSAndroid Build Coastguard Workerclass BlockFinder: 1171*cda5da8dSAndroid Build Coastguard Worker """Provide a tokeneater() method to detect the end of a code block.""" 1172*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 1173*cda5da8dSAndroid Build Coastguard Worker self.indent = 0 1174*cda5da8dSAndroid Build Coastguard Worker self.islambda = False 1175*cda5da8dSAndroid Build Coastguard Worker self.started = False 1176*cda5da8dSAndroid Build Coastguard Worker self.passline = False 1177*cda5da8dSAndroid Build Coastguard Worker self.indecorator = False 1178*cda5da8dSAndroid Build Coastguard Worker self.last = 1 1179*cda5da8dSAndroid Build Coastguard Worker self.body_col0 = None 1180*cda5da8dSAndroid Build Coastguard Worker 1181*cda5da8dSAndroid Build Coastguard Worker def tokeneater(self, type, token, srowcol, erowcol, line): 1182*cda5da8dSAndroid Build Coastguard Worker if not self.started and not self.indecorator: 1183*cda5da8dSAndroid Build Coastguard Worker # skip any decorators 1184*cda5da8dSAndroid Build Coastguard Worker if token == "@": 1185*cda5da8dSAndroid Build Coastguard Worker self.indecorator = True 1186*cda5da8dSAndroid Build Coastguard Worker # look for the first "def", "class" or "lambda" 1187*cda5da8dSAndroid Build Coastguard Worker elif token in ("def", "class", "lambda"): 1188*cda5da8dSAndroid Build Coastguard Worker if token == "lambda": 1189*cda5da8dSAndroid Build Coastguard Worker self.islambda = True 1190*cda5da8dSAndroid Build Coastguard Worker self.started = True 1191*cda5da8dSAndroid Build Coastguard Worker self.passline = True # skip to the end of the line 1192*cda5da8dSAndroid Build Coastguard Worker elif type == tokenize.NEWLINE: 1193*cda5da8dSAndroid Build Coastguard Worker self.passline = False # stop skipping when a NEWLINE is seen 1194*cda5da8dSAndroid Build Coastguard Worker self.last = srowcol[0] 1195*cda5da8dSAndroid Build Coastguard Worker if self.islambda: # lambdas always end at the first NEWLINE 1196*cda5da8dSAndroid Build Coastguard Worker raise EndOfBlock 1197*cda5da8dSAndroid Build Coastguard Worker # hitting a NEWLINE when in a decorator without args 1198*cda5da8dSAndroid Build Coastguard Worker # ends the decorator 1199*cda5da8dSAndroid Build Coastguard Worker if self.indecorator: 1200*cda5da8dSAndroid Build Coastguard Worker self.indecorator = False 1201*cda5da8dSAndroid Build Coastguard Worker elif self.passline: 1202*cda5da8dSAndroid Build Coastguard Worker pass 1203*cda5da8dSAndroid Build Coastguard Worker elif type == tokenize.INDENT: 1204*cda5da8dSAndroid Build Coastguard Worker if self.body_col0 is None and self.started: 1205*cda5da8dSAndroid Build Coastguard Worker self.body_col0 = erowcol[1] 1206*cda5da8dSAndroid Build Coastguard Worker self.indent = self.indent + 1 1207*cda5da8dSAndroid Build Coastguard Worker self.passline = True 1208*cda5da8dSAndroid Build Coastguard Worker elif type == tokenize.DEDENT: 1209*cda5da8dSAndroid Build Coastguard Worker self.indent = self.indent - 1 1210*cda5da8dSAndroid Build Coastguard Worker # the end of matching indent/dedent pairs end a block 1211*cda5da8dSAndroid Build Coastguard Worker # (note that this only works for "def"/"class" blocks, 1212*cda5da8dSAndroid Build Coastguard Worker # not e.g. for "if: else:" or "try: finally:" blocks) 1213*cda5da8dSAndroid Build Coastguard Worker if self.indent <= 0: 1214*cda5da8dSAndroid Build Coastguard Worker raise EndOfBlock 1215*cda5da8dSAndroid Build Coastguard Worker elif type == tokenize.COMMENT: 1216*cda5da8dSAndroid Build Coastguard Worker if self.body_col0 is not None and srowcol[1] >= self.body_col0: 1217*cda5da8dSAndroid Build Coastguard Worker # Include comments if indented at least as much as the block 1218*cda5da8dSAndroid Build Coastguard Worker self.last = srowcol[0] 1219*cda5da8dSAndroid Build Coastguard Worker elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): 1220*cda5da8dSAndroid Build Coastguard Worker # any other token on the same indentation level end the previous 1221*cda5da8dSAndroid Build Coastguard Worker # block as well, except the pseudo-tokens COMMENT and NL. 1222*cda5da8dSAndroid Build Coastguard Worker raise EndOfBlock 1223*cda5da8dSAndroid Build Coastguard Worker 1224*cda5da8dSAndroid Build Coastguard Workerdef getblock(lines): 1225*cda5da8dSAndroid Build Coastguard Worker """Extract the block of code at the top of the given list of lines.""" 1226*cda5da8dSAndroid Build Coastguard Worker blockfinder = BlockFinder() 1227*cda5da8dSAndroid Build Coastguard Worker try: 1228*cda5da8dSAndroid Build Coastguard Worker tokens = tokenize.generate_tokens(iter(lines).__next__) 1229*cda5da8dSAndroid Build Coastguard Worker for _token in tokens: 1230*cda5da8dSAndroid Build Coastguard Worker blockfinder.tokeneater(*_token) 1231*cda5da8dSAndroid Build Coastguard Worker except (EndOfBlock, IndentationError): 1232*cda5da8dSAndroid Build Coastguard Worker pass 1233*cda5da8dSAndroid Build Coastguard Worker return lines[:blockfinder.last] 1234*cda5da8dSAndroid Build Coastguard Worker 1235*cda5da8dSAndroid Build Coastguard Workerdef getsourcelines(object): 1236*cda5da8dSAndroid Build Coastguard Worker """Return a list of source lines and starting line number for an object. 1237*cda5da8dSAndroid Build Coastguard Worker 1238*cda5da8dSAndroid Build Coastguard Worker The argument may be a module, class, method, function, traceback, frame, 1239*cda5da8dSAndroid Build Coastguard Worker or code object. The source code is returned as a list of the lines 1240*cda5da8dSAndroid Build Coastguard Worker corresponding to the object and the line number indicates where in the 1241*cda5da8dSAndroid Build Coastguard Worker original source file the first line of code was found. An OSError is 1242*cda5da8dSAndroid Build Coastguard Worker raised if the source code cannot be retrieved.""" 1243*cda5da8dSAndroid Build Coastguard Worker object = unwrap(object) 1244*cda5da8dSAndroid Build Coastguard Worker lines, lnum = findsource(object) 1245*cda5da8dSAndroid Build Coastguard Worker 1246*cda5da8dSAndroid Build Coastguard Worker if istraceback(object): 1247*cda5da8dSAndroid Build Coastguard Worker object = object.tb_frame 1248*cda5da8dSAndroid Build Coastguard Worker 1249*cda5da8dSAndroid Build Coastguard Worker # for module or frame that corresponds to module, return all source lines 1250*cda5da8dSAndroid Build Coastguard Worker if (ismodule(object) or 1251*cda5da8dSAndroid Build Coastguard Worker (isframe(object) and object.f_code.co_name == "<module>")): 1252*cda5da8dSAndroid Build Coastguard Worker return lines, 0 1253*cda5da8dSAndroid Build Coastguard Worker else: 1254*cda5da8dSAndroid Build Coastguard Worker return getblock(lines[lnum:]), lnum + 1 1255*cda5da8dSAndroid Build Coastguard Worker 1256*cda5da8dSAndroid Build Coastguard Workerdef getsource(object): 1257*cda5da8dSAndroid Build Coastguard Worker """Return the text of the source code for an object. 1258*cda5da8dSAndroid Build Coastguard Worker 1259*cda5da8dSAndroid Build Coastguard Worker The argument may be a module, class, method, function, traceback, frame, 1260*cda5da8dSAndroid Build Coastguard Worker or code object. The source code is returned as a single string. An 1261*cda5da8dSAndroid Build Coastguard Worker OSError is raised if the source code cannot be retrieved.""" 1262*cda5da8dSAndroid Build Coastguard Worker lines, lnum = getsourcelines(object) 1263*cda5da8dSAndroid Build Coastguard Worker return ''.join(lines) 1264*cda5da8dSAndroid Build Coastguard Worker 1265*cda5da8dSAndroid Build Coastguard Worker# --------------------------------------------------- class tree extraction 1266*cda5da8dSAndroid Build Coastguard Workerdef walktree(classes, children, parent): 1267*cda5da8dSAndroid Build Coastguard Worker """Recursive helper function for getclasstree().""" 1268*cda5da8dSAndroid Build Coastguard Worker results = [] 1269*cda5da8dSAndroid Build Coastguard Worker classes.sort(key=attrgetter('__module__', '__name__')) 1270*cda5da8dSAndroid Build Coastguard Worker for c in classes: 1271*cda5da8dSAndroid Build Coastguard Worker results.append((c, c.__bases__)) 1272*cda5da8dSAndroid Build Coastguard Worker if c in children: 1273*cda5da8dSAndroid Build Coastguard Worker results.append(walktree(children[c], children, c)) 1274*cda5da8dSAndroid Build Coastguard Worker return results 1275*cda5da8dSAndroid Build Coastguard Worker 1276*cda5da8dSAndroid Build Coastguard Workerdef getclasstree(classes, unique=False): 1277*cda5da8dSAndroid Build Coastguard Worker """Arrange the given list of classes into a hierarchy of nested lists. 1278*cda5da8dSAndroid Build Coastguard Worker 1279*cda5da8dSAndroid Build Coastguard Worker Where a nested list appears, it contains classes derived from the class 1280*cda5da8dSAndroid Build Coastguard Worker whose entry immediately precedes the list. Each entry is a 2-tuple 1281*cda5da8dSAndroid Build Coastguard Worker containing a class and a tuple of its base classes. If the 'unique' 1282*cda5da8dSAndroid Build Coastguard Worker argument is true, exactly one entry appears in the returned structure 1283*cda5da8dSAndroid Build Coastguard Worker for each class in the given list. Otherwise, classes using multiple 1284*cda5da8dSAndroid Build Coastguard Worker inheritance and their descendants will appear multiple times.""" 1285*cda5da8dSAndroid Build Coastguard Worker children = {} 1286*cda5da8dSAndroid Build Coastguard Worker roots = [] 1287*cda5da8dSAndroid Build Coastguard Worker for c in classes: 1288*cda5da8dSAndroid Build Coastguard Worker if c.__bases__: 1289*cda5da8dSAndroid Build Coastguard Worker for parent in c.__bases__: 1290*cda5da8dSAndroid Build Coastguard Worker if parent not in children: 1291*cda5da8dSAndroid Build Coastguard Worker children[parent] = [] 1292*cda5da8dSAndroid Build Coastguard Worker if c not in children[parent]: 1293*cda5da8dSAndroid Build Coastguard Worker children[parent].append(c) 1294*cda5da8dSAndroid Build Coastguard Worker if unique and parent in classes: break 1295*cda5da8dSAndroid Build Coastguard Worker elif c not in roots: 1296*cda5da8dSAndroid Build Coastguard Worker roots.append(c) 1297*cda5da8dSAndroid Build Coastguard Worker for parent in children: 1298*cda5da8dSAndroid Build Coastguard Worker if parent not in classes: 1299*cda5da8dSAndroid Build Coastguard Worker roots.append(parent) 1300*cda5da8dSAndroid Build Coastguard Worker return walktree(roots, children, None) 1301*cda5da8dSAndroid Build Coastguard Worker 1302*cda5da8dSAndroid Build Coastguard Worker# ------------------------------------------------ argument list extraction 1303*cda5da8dSAndroid Build Coastguard WorkerArguments = namedtuple('Arguments', 'args, varargs, varkw') 1304*cda5da8dSAndroid Build Coastguard Worker 1305*cda5da8dSAndroid Build Coastguard Workerdef getargs(co): 1306*cda5da8dSAndroid Build Coastguard Worker """Get information about the arguments accepted by a code object. 1307*cda5da8dSAndroid Build Coastguard Worker 1308*cda5da8dSAndroid Build Coastguard Worker Three things are returned: (args, varargs, varkw), where 1309*cda5da8dSAndroid Build Coastguard Worker 'args' is the list of argument names. Keyword-only arguments are 1310*cda5da8dSAndroid Build Coastguard Worker appended. 'varargs' and 'varkw' are the names of the * and ** 1311*cda5da8dSAndroid Build Coastguard Worker arguments or None.""" 1312*cda5da8dSAndroid Build Coastguard Worker if not iscode(co): 1313*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is not a code object'.format(co)) 1314*cda5da8dSAndroid Build Coastguard Worker 1315*cda5da8dSAndroid Build Coastguard Worker names = co.co_varnames 1316*cda5da8dSAndroid Build Coastguard Worker nargs = co.co_argcount 1317*cda5da8dSAndroid Build Coastguard Worker nkwargs = co.co_kwonlyargcount 1318*cda5da8dSAndroid Build Coastguard Worker args = list(names[:nargs]) 1319*cda5da8dSAndroid Build Coastguard Worker kwonlyargs = list(names[nargs:nargs+nkwargs]) 1320*cda5da8dSAndroid Build Coastguard Worker step = 0 1321*cda5da8dSAndroid Build Coastguard Worker 1322*cda5da8dSAndroid Build Coastguard Worker nargs += nkwargs 1323*cda5da8dSAndroid Build Coastguard Worker varargs = None 1324*cda5da8dSAndroid Build Coastguard Worker if co.co_flags & CO_VARARGS: 1325*cda5da8dSAndroid Build Coastguard Worker varargs = co.co_varnames[nargs] 1326*cda5da8dSAndroid Build Coastguard Worker nargs = nargs + 1 1327*cda5da8dSAndroid Build Coastguard Worker varkw = None 1328*cda5da8dSAndroid Build Coastguard Worker if co.co_flags & CO_VARKEYWORDS: 1329*cda5da8dSAndroid Build Coastguard Worker varkw = co.co_varnames[nargs] 1330*cda5da8dSAndroid Build Coastguard Worker return Arguments(args + kwonlyargs, varargs, varkw) 1331*cda5da8dSAndroid Build Coastguard Worker 1332*cda5da8dSAndroid Build Coastguard Worker 1333*cda5da8dSAndroid Build Coastguard WorkerFullArgSpec = namedtuple('FullArgSpec', 1334*cda5da8dSAndroid Build Coastguard Worker 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') 1335*cda5da8dSAndroid Build Coastguard Worker 1336*cda5da8dSAndroid Build Coastguard Workerdef getfullargspec(func): 1337*cda5da8dSAndroid Build Coastguard Worker """Get the names and default values of a callable object's parameters. 1338*cda5da8dSAndroid Build Coastguard Worker 1339*cda5da8dSAndroid Build Coastguard Worker A tuple of seven things is returned: 1340*cda5da8dSAndroid Build Coastguard Worker (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations). 1341*cda5da8dSAndroid Build Coastguard Worker 'args' is a list of the parameter names. 1342*cda5da8dSAndroid Build Coastguard Worker 'varargs' and 'varkw' are the names of the * and ** parameters or None. 1343*cda5da8dSAndroid Build Coastguard Worker 'defaults' is an n-tuple of the default values of the last n parameters. 1344*cda5da8dSAndroid Build Coastguard Worker 'kwonlyargs' is a list of keyword-only parameter names. 1345*cda5da8dSAndroid Build Coastguard Worker 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. 1346*cda5da8dSAndroid Build Coastguard Worker 'annotations' is a dictionary mapping parameter names to annotations. 1347*cda5da8dSAndroid Build Coastguard Worker 1348*cda5da8dSAndroid Build Coastguard Worker Notable differences from inspect.signature(): 1349*cda5da8dSAndroid Build Coastguard Worker - the "self" parameter is always reported, even for bound methods 1350*cda5da8dSAndroid Build Coastguard Worker - wrapper chains defined by __wrapped__ *not* unwrapped automatically 1351*cda5da8dSAndroid Build Coastguard Worker """ 1352*cda5da8dSAndroid Build Coastguard Worker try: 1353*cda5da8dSAndroid Build Coastguard Worker # Re: `skip_bound_arg=False` 1354*cda5da8dSAndroid Build Coastguard Worker # 1355*cda5da8dSAndroid Build Coastguard Worker # There is a notable difference in behaviour between getfullargspec 1356*cda5da8dSAndroid Build Coastguard Worker # and Signature: the former always returns 'self' parameter for bound 1357*cda5da8dSAndroid Build Coastguard Worker # methods, whereas the Signature always shows the actual calling 1358*cda5da8dSAndroid Build Coastguard Worker # signature of the passed object. 1359*cda5da8dSAndroid Build Coastguard Worker # 1360*cda5da8dSAndroid Build Coastguard Worker # To simulate this behaviour, we "unbind" bound methods, to trick 1361*cda5da8dSAndroid Build Coastguard Worker # inspect.signature to always return their first parameter ("self", 1362*cda5da8dSAndroid Build Coastguard Worker # usually) 1363*cda5da8dSAndroid Build Coastguard Worker 1364*cda5da8dSAndroid Build Coastguard Worker # Re: `follow_wrapper_chains=False` 1365*cda5da8dSAndroid Build Coastguard Worker # 1366*cda5da8dSAndroid Build Coastguard Worker # getfullargspec() historically ignored __wrapped__ attributes, 1367*cda5da8dSAndroid Build Coastguard Worker # so we ensure that remains the case in 3.3+ 1368*cda5da8dSAndroid Build Coastguard Worker 1369*cda5da8dSAndroid Build Coastguard Worker sig = _signature_from_callable(func, 1370*cda5da8dSAndroid Build Coastguard Worker follow_wrapper_chains=False, 1371*cda5da8dSAndroid Build Coastguard Worker skip_bound_arg=False, 1372*cda5da8dSAndroid Build Coastguard Worker sigcls=Signature, 1373*cda5da8dSAndroid Build Coastguard Worker eval_str=False) 1374*cda5da8dSAndroid Build Coastguard Worker except Exception as ex: 1375*cda5da8dSAndroid Build Coastguard Worker # Most of the times 'signature' will raise ValueError. 1376*cda5da8dSAndroid Build Coastguard Worker # But, it can also raise AttributeError, and, maybe something 1377*cda5da8dSAndroid Build Coastguard Worker # else. So to be fully backwards compatible, we catch all 1378*cda5da8dSAndroid Build Coastguard Worker # possible exceptions here, and reraise a TypeError. 1379*cda5da8dSAndroid Build Coastguard Worker raise TypeError('unsupported callable') from ex 1380*cda5da8dSAndroid Build Coastguard Worker 1381*cda5da8dSAndroid Build Coastguard Worker args = [] 1382*cda5da8dSAndroid Build Coastguard Worker varargs = None 1383*cda5da8dSAndroid Build Coastguard Worker varkw = None 1384*cda5da8dSAndroid Build Coastguard Worker posonlyargs = [] 1385*cda5da8dSAndroid Build Coastguard Worker kwonlyargs = [] 1386*cda5da8dSAndroid Build Coastguard Worker annotations = {} 1387*cda5da8dSAndroid Build Coastguard Worker defaults = () 1388*cda5da8dSAndroid Build Coastguard Worker kwdefaults = {} 1389*cda5da8dSAndroid Build Coastguard Worker 1390*cda5da8dSAndroid Build Coastguard Worker if sig.return_annotation is not sig.empty: 1391*cda5da8dSAndroid Build Coastguard Worker annotations['return'] = sig.return_annotation 1392*cda5da8dSAndroid Build Coastguard Worker 1393*cda5da8dSAndroid Build Coastguard Worker for param in sig.parameters.values(): 1394*cda5da8dSAndroid Build Coastguard Worker kind = param.kind 1395*cda5da8dSAndroid Build Coastguard Worker name = param.name 1396*cda5da8dSAndroid Build Coastguard Worker 1397*cda5da8dSAndroid Build Coastguard Worker if kind is _POSITIONAL_ONLY: 1398*cda5da8dSAndroid Build Coastguard Worker posonlyargs.append(name) 1399*cda5da8dSAndroid Build Coastguard Worker if param.default is not param.empty: 1400*cda5da8dSAndroid Build Coastguard Worker defaults += (param.default,) 1401*cda5da8dSAndroid Build Coastguard Worker elif kind is _POSITIONAL_OR_KEYWORD: 1402*cda5da8dSAndroid Build Coastguard Worker args.append(name) 1403*cda5da8dSAndroid Build Coastguard Worker if param.default is not param.empty: 1404*cda5da8dSAndroid Build Coastguard Worker defaults += (param.default,) 1405*cda5da8dSAndroid Build Coastguard Worker elif kind is _VAR_POSITIONAL: 1406*cda5da8dSAndroid Build Coastguard Worker varargs = name 1407*cda5da8dSAndroid Build Coastguard Worker elif kind is _KEYWORD_ONLY: 1408*cda5da8dSAndroid Build Coastguard Worker kwonlyargs.append(name) 1409*cda5da8dSAndroid Build Coastguard Worker if param.default is not param.empty: 1410*cda5da8dSAndroid Build Coastguard Worker kwdefaults[name] = param.default 1411*cda5da8dSAndroid Build Coastguard Worker elif kind is _VAR_KEYWORD: 1412*cda5da8dSAndroid Build Coastguard Worker varkw = name 1413*cda5da8dSAndroid Build Coastguard Worker 1414*cda5da8dSAndroid Build Coastguard Worker if param.annotation is not param.empty: 1415*cda5da8dSAndroid Build Coastguard Worker annotations[name] = param.annotation 1416*cda5da8dSAndroid Build Coastguard Worker 1417*cda5da8dSAndroid Build Coastguard Worker if not kwdefaults: 1418*cda5da8dSAndroid Build Coastguard Worker # compatibility with 'func.__kwdefaults__' 1419*cda5da8dSAndroid Build Coastguard Worker kwdefaults = None 1420*cda5da8dSAndroid Build Coastguard Worker 1421*cda5da8dSAndroid Build Coastguard Worker if not defaults: 1422*cda5da8dSAndroid Build Coastguard Worker # compatibility with 'func.__defaults__' 1423*cda5da8dSAndroid Build Coastguard Worker defaults = None 1424*cda5da8dSAndroid Build Coastguard Worker 1425*cda5da8dSAndroid Build Coastguard Worker return FullArgSpec(posonlyargs + args, varargs, varkw, defaults, 1426*cda5da8dSAndroid Build Coastguard Worker kwonlyargs, kwdefaults, annotations) 1427*cda5da8dSAndroid Build Coastguard Worker 1428*cda5da8dSAndroid Build Coastguard Worker 1429*cda5da8dSAndroid Build Coastguard WorkerArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') 1430*cda5da8dSAndroid Build Coastguard Worker 1431*cda5da8dSAndroid Build Coastguard Workerdef getargvalues(frame): 1432*cda5da8dSAndroid Build Coastguard Worker """Get information about arguments passed into a particular frame. 1433*cda5da8dSAndroid Build Coastguard Worker 1434*cda5da8dSAndroid Build Coastguard Worker A tuple of four things is returned: (args, varargs, varkw, locals). 1435*cda5da8dSAndroid Build Coastguard Worker 'args' is a list of the argument names. 1436*cda5da8dSAndroid Build Coastguard Worker 'varargs' and 'varkw' are the names of the * and ** arguments or None. 1437*cda5da8dSAndroid Build Coastguard Worker 'locals' is the locals dictionary of the given frame.""" 1438*cda5da8dSAndroid Build Coastguard Worker args, varargs, varkw = getargs(frame.f_code) 1439*cda5da8dSAndroid Build Coastguard Worker return ArgInfo(args, varargs, varkw, frame.f_locals) 1440*cda5da8dSAndroid Build Coastguard Worker 1441*cda5da8dSAndroid Build Coastguard Workerdef formatannotation(annotation, base_module=None): 1442*cda5da8dSAndroid Build Coastguard Worker if getattr(annotation, '__module__', None) == 'typing': 1443*cda5da8dSAndroid Build Coastguard Worker def repl(match): 1444*cda5da8dSAndroid Build Coastguard Worker text = match.group() 1445*cda5da8dSAndroid Build Coastguard Worker return text.removeprefix('typing.') 1446*cda5da8dSAndroid Build Coastguard Worker return re.sub(r'[\w\.]+', repl, repr(annotation)) 1447*cda5da8dSAndroid Build Coastguard Worker if isinstance(annotation, types.GenericAlias): 1448*cda5da8dSAndroid Build Coastguard Worker return str(annotation) 1449*cda5da8dSAndroid Build Coastguard Worker if isinstance(annotation, type): 1450*cda5da8dSAndroid Build Coastguard Worker if annotation.__module__ in ('builtins', base_module): 1451*cda5da8dSAndroid Build Coastguard Worker return annotation.__qualname__ 1452*cda5da8dSAndroid Build Coastguard Worker return annotation.__module__+'.'+annotation.__qualname__ 1453*cda5da8dSAndroid Build Coastguard Worker return repr(annotation) 1454*cda5da8dSAndroid Build Coastguard Worker 1455*cda5da8dSAndroid Build Coastguard Workerdef formatannotationrelativeto(object): 1456*cda5da8dSAndroid Build Coastguard Worker module = getattr(object, '__module__', None) 1457*cda5da8dSAndroid Build Coastguard Worker def _formatannotation(annotation): 1458*cda5da8dSAndroid Build Coastguard Worker return formatannotation(annotation, module) 1459*cda5da8dSAndroid Build Coastguard Worker return _formatannotation 1460*cda5da8dSAndroid Build Coastguard Worker 1461*cda5da8dSAndroid Build Coastguard Worker 1462*cda5da8dSAndroid Build Coastguard Workerdef formatargvalues(args, varargs, varkw, locals, 1463*cda5da8dSAndroid Build Coastguard Worker formatarg=str, 1464*cda5da8dSAndroid Build Coastguard Worker formatvarargs=lambda name: '*' + name, 1465*cda5da8dSAndroid Build Coastguard Worker formatvarkw=lambda name: '**' + name, 1466*cda5da8dSAndroid Build Coastguard Worker formatvalue=lambda value: '=' + repr(value)): 1467*cda5da8dSAndroid Build Coastguard Worker """Format an argument spec from the 4 values returned by getargvalues. 1468*cda5da8dSAndroid Build Coastguard Worker 1469*cda5da8dSAndroid Build Coastguard Worker The first four arguments are (args, varargs, varkw, locals). The 1470*cda5da8dSAndroid Build Coastguard Worker next four arguments are the corresponding optional formatting functions 1471*cda5da8dSAndroid Build Coastguard Worker that are called to turn names and values into strings. The ninth 1472*cda5da8dSAndroid Build Coastguard Worker argument is an optional function to format the sequence of arguments.""" 1473*cda5da8dSAndroid Build Coastguard Worker def convert(name, locals=locals, 1474*cda5da8dSAndroid Build Coastguard Worker formatarg=formatarg, formatvalue=formatvalue): 1475*cda5da8dSAndroid Build Coastguard Worker return formatarg(name) + formatvalue(locals[name]) 1476*cda5da8dSAndroid Build Coastguard Worker specs = [] 1477*cda5da8dSAndroid Build Coastguard Worker for i in range(len(args)): 1478*cda5da8dSAndroid Build Coastguard Worker specs.append(convert(args[i])) 1479*cda5da8dSAndroid Build Coastguard Worker if varargs: 1480*cda5da8dSAndroid Build Coastguard Worker specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) 1481*cda5da8dSAndroid Build Coastguard Worker if varkw: 1482*cda5da8dSAndroid Build Coastguard Worker specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) 1483*cda5da8dSAndroid Build Coastguard Worker return '(' + ', '.join(specs) + ')' 1484*cda5da8dSAndroid Build Coastguard Worker 1485*cda5da8dSAndroid Build Coastguard Workerdef _missing_arguments(f_name, argnames, pos, values): 1486*cda5da8dSAndroid Build Coastguard Worker names = [repr(name) for name in argnames if name not in values] 1487*cda5da8dSAndroid Build Coastguard Worker missing = len(names) 1488*cda5da8dSAndroid Build Coastguard Worker if missing == 1: 1489*cda5da8dSAndroid Build Coastguard Worker s = names[0] 1490*cda5da8dSAndroid Build Coastguard Worker elif missing == 2: 1491*cda5da8dSAndroid Build Coastguard Worker s = "{} and {}".format(*names) 1492*cda5da8dSAndroid Build Coastguard Worker else: 1493*cda5da8dSAndroid Build Coastguard Worker tail = ", {} and {}".format(*names[-2:]) 1494*cda5da8dSAndroid Build Coastguard Worker del names[-2:] 1495*cda5da8dSAndroid Build Coastguard Worker s = ", ".join(names) + tail 1496*cda5da8dSAndroid Build Coastguard Worker raise TypeError("%s() missing %i required %s argument%s: %s" % 1497*cda5da8dSAndroid Build Coastguard Worker (f_name, missing, 1498*cda5da8dSAndroid Build Coastguard Worker "positional" if pos else "keyword-only", 1499*cda5da8dSAndroid Build Coastguard Worker "" if missing == 1 else "s", s)) 1500*cda5da8dSAndroid Build Coastguard Worker 1501*cda5da8dSAndroid Build Coastguard Workerdef _too_many(f_name, args, kwonly, varargs, defcount, given, values): 1502*cda5da8dSAndroid Build Coastguard Worker atleast = len(args) - defcount 1503*cda5da8dSAndroid Build Coastguard Worker kwonly_given = len([arg for arg in kwonly if arg in values]) 1504*cda5da8dSAndroid Build Coastguard Worker if varargs: 1505*cda5da8dSAndroid Build Coastguard Worker plural = atleast != 1 1506*cda5da8dSAndroid Build Coastguard Worker sig = "at least %d" % (atleast,) 1507*cda5da8dSAndroid Build Coastguard Worker elif defcount: 1508*cda5da8dSAndroid Build Coastguard Worker plural = True 1509*cda5da8dSAndroid Build Coastguard Worker sig = "from %d to %d" % (atleast, len(args)) 1510*cda5da8dSAndroid Build Coastguard Worker else: 1511*cda5da8dSAndroid Build Coastguard Worker plural = len(args) != 1 1512*cda5da8dSAndroid Build Coastguard Worker sig = str(len(args)) 1513*cda5da8dSAndroid Build Coastguard Worker kwonly_sig = "" 1514*cda5da8dSAndroid Build Coastguard Worker if kwonly_given: 1515*cda5da8dSAndroid Build Coastguard Worker msg = " positional argument%s (and %d keyword-only argument%s)" 1516*cda5da8dSAndroid Build Coastguard Worker kwonly_sig = (msg % ("s" if given != 1 else "", kwonly_given, 1517*cda5da8dSAndroid Build Coastguard Worker "s" if kwonly_given != 1 else "")) 1518*cda5da8dSAndroid Build Coastguard Worker raise TypeError("%s() takes %s positional argument%s but %d%s %s given" % 1519*cda5da8dSAndroid Build Coastguard Worker (f_name, sig, "s" if plural else "", given, kwonly_sig, 1520*cda5da8dSAndroid Build Coastguard Worker "was" if given == 1 and not kwonly_given else "were")) 1521*cda5da8dSAndroid Build Coastguard Worker 1522*cda5da8dSAndroid Build Coastguard Workerdef getcallargs(func, /, *positional, **named): 1523*cda5da8dSAndroid Build Coastguard Worker """Get the mapping of arguments to values. 1524*cda5da8dSAndroid Build Coastguard Worker 1525*cda5da8dSAndroid Build Coastguard Worker A dict is returned, with keys the function argument names (including the 1526*cda5da8dSAndroid Build Coastguard Worker names of the * and ** arguments, if any), and values the respective bound 1527*cda5da8dSAndroid Build Coastguard Worker values from 'positional' and 'named'.""" 1528*cda5da8dSAndroid Build Coastguard Worker spec = getfullargspec(func) 1529*cda5da8dSAndroid Build Coastguard Worker args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec 1530*cda5da8dSAndroid Build Coastguard Worker f_name = func.__name__ 1531*cda5da8dSAndroid Build Coastguard Worker arg2value = {} 1532*cda5da8dSAndroid Build Coastguard Worker 1533*cda5da8dSAndroid Build Coastguard Worker 1534*cda5da8dSAndroid Build Coastguard Worker if ismethod(func) and func.__self__ is not None: 1535*cda5da8dSAndroid Build Coastguard Worker # implicit 'self' (or 'cls' for classmethods) argument 1536*cda5da8dSAndroid Build Coastguard Worker positional = (func.__self__,) + positional 1537*cda5da8dSAndroid Build Coastguard Worker num_pos = len(positional) 1538*cda5da8dSAndroid Build Coastguard Worker num_args = len(args) 1539*cda5da8dSAndroid Build Coastguard Worker num_defaults = len(defaults) if defaults else 0 1540*cda5da8dSAndroid Build Coastguard Worker 1541*cda5da8dSAndroid Build Coastguard Worker n = min(num_pos, num_args) 1542*cda5da8dSAndroid Build Coastguard Worker for i in range(n): 1543*cda5da8dSAndroid Build Coastguard Worker arg2value[args[i]] = positional[i] 1544*cda5da8dSAndroid Build Coastguard Worker if varargs: 1545*cda5da8dSAndroid Build Coastguard Worker arg2value[varargs] = tuple(positional[n:]) 1546*cda5da8dSAndroid Build Coastguard Worker possible_kwargs = set(args + kwonlyargs) 1547*cda5da8dSAndroid Build Coastguard Worker if varkw: 1548*cda5da8dSAndroid Build Coastguard Worker arg2value[varkw] = {} 1549*cda5da8dSAndroid Build Coastguard Worker for kw, value in named.items(): 1550*cda5da8dSAndroid Build Coastguard Worker if kw not in possible_kwargs: 1551*cda5da8dSAndroid Build Coastguard Worker if not varkw: 1552*cda5da8dSAndroid Build Coastguard Worker raise TypeError("%s() got an unexpected keyword argument %r" % 1553*cda5da8dSAndroid Build Coastguard Worker (f_name, kw)) 1554*cda5da8dSAndroid Build Coastguard Worker arg2value[varkw][kw] = value 1555*cda5da8dSAndroid Build Coastguard Worker continue 1556*cda5da8dSAndroid Build Coastguard Worker if kw in arg2value: 1557*cda5da8dSAndroid Build Coastguard Worker raise TypeError("%s() got multiple values for argument %r" % 1558*cda5da8dSAndroid Build Coastguard Worker (f_name, kw)) 1559*cda5da8dSAndroid Build Coastguard Worker arg2value[kw] = value 1560*cda5da8dSAndroid Build Coastguard Worker if num_pos > num_args and not varargs: 1561*cda5da8dSAndroid Build Coastguard Worker _too_many(f_name, args, kwonlyargs, varargs, num_defaults, 1562*cda5da8dSAndroid Build Coastguard Worker num_pos, arg2value) 1563*cda5da8dSAndroid Build Coastguard Worker if num_pos < num_args: 1564*cda5da8dSAndroid Build Coastguard Worker req = args[:num_args - num_defaults] 1565*cda5da8dSAndroid Build Coastguard Worker for arg in req: 1566*cda5da8dSAndroid Build Coastguard Worker if arg not in arg2value: 1567*cda5da8dSAndroid Build Coastguard Worker _missing_arguments(f_name, req, True, arg2value) 1568*cda5da8dSAndroid Build Coastguard Worker for i, arg in enumerate(args[num_args - num_defaults:]): 1569*cda5da8dSAndroid Build Coastguard Worker if arg not in arg2value: 1570*cda5da8dSAndroid Build Coastguard Worker arg2value[arg] = defaults[i] 1571*cda5da8dSAndroid Build Coastguard Worker missing = 0 1572*cda5da8dSAndroid Build Coastguard Worker for kwarg in kwonlyargs: 1573*cda5da8dSAndroid Build Coastguard Worker if kwarg not in arg2value: 1574*cda5da8dSAndroid Build Coastguard Worker if kwonlydefaults and kwarg in kwonlydefaults: 1575*cda5da8dSAndroid Build Coastguard Worker arg2value[kwarg] = kwonlydefaults[kwarg] 1576*cda5da8dSAndroid Build Coastguard Worker else: 1577*cda5da8dSAndroid Build Coastguard Worker missing += 1 1578*cda5da8dSAndroid Build Coastguard Worker if missing: 1579*cda5da8dSAndroid Build Coastguard Worker _missing_arguments(f_name, kwonlyargs, False, arg2value) 1580*cda5da8dSAndroid Build Coastguard Worker return arg2value 1581*cda5da8dSAndroid Build Coastguard Worker 1582*cda5da8dSAndroid Build Coastguard WorkerClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound') 1583*cda5da8dSAndroid Build Coastguard Worker 1584*cda5da8dSAndroid Build Coastguard Workerdef getclosurevars(func): 1585*cda5da8dSAndroid Build Coastguard Worker """ 1586*cda5da8dSAndroid Build Coastguard Worker Get the mapping of free variables to their current values. 1587*cda5da8dSAndroid Build Coastguard Worker 1588*cda5da8dSAndroid Build Coastguard Worker Returns a named tuple of dicts mapping the current nonlocal, global 1589*cda5da8dSAndroid Build Coastguard Worker and builtin references as seen by the body of the function. A final 1590*cda5da8dSAndroid Build Coastguard Worker set of unbound names that could not be resolved is also provided. 1591*cda5da8dSAndroid Build Coastguard Worker """ 1592*cda5da8dSAndroid Build Coastguard Worker 1593*cda5da8dSAndroid Build Coastguard Worker if ismethod(func): 1594*cda5da8dSAndroid Build Coastguard Worker func = func.__func__ 1595*cda5da8dSAndroid Build Coastguard Worker 1596*cda5da8dSAndroid Build Coastguard Worker if not isfunction(func): 1597*cda5da8dSAndroid Build Coastguard Worker raise TypeError("{!r} is not a Python function".format(func)) 1598*cda5da8dSAndroid Build Coastguard Worker 1599*cda5da8dSAndroid Build Coastguard Worker code = func.__code__ 1600*cda5da8dSAndroid Build Coastguard Worker # Nonlocal references are named in co_freevars and resolved 1601*cda5da8dSAndroid Build Coastguard Worker # by looking them up in __closure__ by positional index 1602*cda5da8dSAndroid Build Coastguard Worker if func.__closure__ is None: 1603*cda5da8dSAndroid Build Coastguard Worker nonlocal_vars = {} 1604*cda5da8dSAndroid Build Coastguard Worker else: 1605*cda5da8dSAndroid Build Coastguard Worker nonlocal_vars = { 1606*cda5da8dSAndroid Build Coastguard Worker var : cell.cell_contents 1607*cda5da8dSAndroid Build Coastguard Worker for var, cell in zip(code.co_freevars, func.__closure__) 1608*cda5da8dSAndroid Build Coastguard Worker } 1609*cda5da8dSAndroid Build Coastguard Worker 1610*cda5da8dSAndroid Build Coastguard Worker # Global and builtin references are named in co_names and resolved 1611*cda5da8dSAndroid Build Coastguard Worker # by looking them up in __globals__ or __builtins__ 1612*cda5da8dSAndroid Build Coastguard Worker global_ns = func.__globals__ 1613*cda5da8dSAndroid Build Coastguard Worker builtin_ns = global_ns.get("__builtins__", builtins.__dict__) 1614*cda5da8dSAndroid Build Coastguard Worker if ismodule(builtin_ns): 1615*cda5da8dSAndroid Build Coastguard Worker builtin_ns = builtin_ns.__dict__ 1616*cda5da8dSAndroid Build Coastguard Worker global_vars = {} 1617*cda5da8dSAndroid Build Coastguard Worker builtin_vars = {} 1618*cda5da8dSAndroid Build Coastguard Worker unbound_names = set() 1619*cda5da8dSAndroid Build Coastguard Worker for name in code.co_names: 1620*cda5da8dSAndroid Build Coastguard Worker if name in ("None", "True", "False"): 1621*cda5da8dSAndroid Build Coastguard Worker # Because these used to be builtins instead of keywords, they 1622*cda5da8dSAndroid Build Coastguard Worker # may still show up as name references. We ignore them. 1623*cda5da8dSAndroid Build Coastguard Worker continue 1624*cda5da8dSAndroid Build Coastguard Worker try: 1625*cda5da8dSAndroid Build Coastguard Worker global_vars[name] = global_ns[name] 1626*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1627*cda5da8dSAndroid Build Coastguard Worker try: 1628*cda5da8dSAndroid Build Coastguard Worker builtin_vars[name] = builtin_ns[name] 1629*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1630*cda5da8dSAndroid Build Coastguard Worker unbound_names.add(name) 1631*cda5da8dSAndroid Build Coastguard Worker 1632*cda5da8dSAndroid Build Coastguard Worker return ClosureVars(nonlocal_vars, global_vars, 1633*cda5da8dSAndroid Build Coastguard Worker builtin_vars, unbound_names) 1634*cda5da8dSAndroid Build Coastguard Worker 1635*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------------- stack frame extraction 1636*cda5da8dSAndroid Build Coastguard Worker 1637*cda5da8dSAndroid Build Coastguard Worker_Traceback = namedtuple('_Traceback', 'filename lineno function code_context index') 1638*cda5da8dSAndroid Build Coastguard Worker 1639*cda5da8dSAndroid Build Coastguard Workerclass Traceback(_Traceback): 1640*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, filename, lineno, function, code_context, index, *, positions=None): 1641*cda5da8dSAndroid Build Coastguard Worker instance = super().__new__(cls, filename, lineno, function, code_context, index) 1642*cda5da8dSAndroid Build Coastguard Worker instance.positions = positions 1643*cda5da8dSAndroid Build Coastguard Worker return instance 1644*cda5da8dSAndroid Build Coastguard Worker 1645*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1646*cda5da8dSAndroid Build Coastguard Worker return ('Traceback(filename={!r}, lineno={!r}, function={!r}, ' 1647*cda5da8dSAndroid Build Coastguard Worker 'code_context={!r}, index={!r}, positions={!r})'.format( 1648*cda5da8dSAndroid Build Coastguard Worker self.filename, self.lineno, self.function, self.code_context, 1649*cda5da8dSAndroid Build Coastguard Worker self.index, self.positions)) 1650*cda5da8dSAndroid Build Coastguard Worker 1651*cda5da8dSAndroid Build Coastguard Workerdef _get_code_position_from_tb(tb): 1652*cda5da8dSAndroid Build Coastguard Worker code, instruction_index = tb.tb_frame.f_code, tb.tb_lasti 1653*cda5da8dSAndroid Build Coastguard Worker return _get_code_position(code, instruction_index) 1654*cda5da8dSAndroid Build Coastguard Worker 1655*cda5da8dSAndroid Build Coastguard Workerdef _get_code_position(code, instruction_index): 1656*cda5da8dSAndroid Build Coastguard Worker if instruction_index < 0: 1657*cda5da8dSAndroid Build Coastguard Worker return (None, None, None, None) 1658*cda5da8dSAndroid Build Coastguard Worker positions_gen = code.co_positions() 1659*cda5da8dSAndroid Build Coastguard Worker # The nth entry in code.co_positions() corresponds to instruction (2*n)th since Python 3.10+ 1660*cda5da8dSAndroid Build Coastguard Worker return next(itertools.islice(positions_gen, instruction_index // 2, None)) 1661*cda5da8dSAndroid Build Coastguard Worker 1662*cda5da8dSAndroid Build Coastguard Workerdef getframeinfo(frame, context=1): 1663*cda5da8dSAndroid Build Coastguard Worker """Get information about a frame or traceback object. 1664*cda5da8dSAndroid Build Coastguard Worker 1665*cda5da8dSAndroid Build Coastguard Worker A tuple of five things is returned: the filename, the line number of 1666*cda5da8dSAndroid Build Coastguard Worker the current line, the function name, a list of lines of context from 1667*cda5da8dSAndroid Build Coastguard Worker the source code, and the index of the current line within that list. 1668*cda5da8dSAndroid Build Coastguard Worker The optional second argument specifies the number of lines of context 1669*cda5da8dSAndroid Build Coastguard Worker to return, which are centered around the current line.""" 1670*cda5da8dSAndroid Build Coastguard Worker if istraceback(frame): 1671*cda5da8dSAndroid Build Coastguard Worker positions = _get_code_position_from_tb(frame) 1672*cda5da8dSAndroid Build Coastguard Worker lineno = frame.tb_lineno 1673*cda5da8dSAndroid Build Coastguard Worker frame = frame.tb_frame 1674*cda5da8dSAndroid Build Coastguard Worker else: 1675*cda5da8dSAndroid Build Coastguard Worker lineno = frame.f_lineno 1676*cda5da8dSAndroid Build Coastguard Worker positions = _get_code_position(frame.f_code, frame.f_lasti) 1677*cda5da8dSAndroid Build Coastguard Worker 1678*cda5da8dSAndroid Build Coastguard Worker if positions[0] is None: 1679*cda5da8dSAndroid Build Coastguard Worker frame, *positions = (frame, lineno, *positions[1:]) 1680*cda5da8dSAndroid Build Coastguard Worker else: 1681*cda5da8dSAndroid Build Coastguard Worker frame, *positions = (frame, *positions) 1682*cda5da8dSAndroid Build Coastguard Worker 1683*cda5da8dSAndroid Build Coastguard Worker lineno = positions[0] 1684*cda5da8dSAndroid Build Coastguard Worker 1685*cda5da8dSAndroid Build Coastguard Worker if not isframe(frame): 1686*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is not a frame or traceback object'.format(frame)) 1687*cda5da8dSAndroid Build Coastguard Worker 1688*cda5da8dSAndroid Build Coastguard Worker filename = getsourcefile(frame) or getfile(frame) 1689*cda5da8dSAndroid Build Coastguard Worker if context > 0: 1690*cda5da8dSAndroid Build Coastguard Worker start = lineno - 1 - context//2 1691*cda5da8dSAndroid Build Coastguard Worker try: 1692*cda5da8dSAndroid Build Coastguard Worker lines, lnum = findsource(frame) 1693*cda5da8dSAndroid Build Coastguard Worker except OSError: 1694*cda5da8dSAndroid Build Coastguard Worker lines = index = None 1695*cda5da8dSAndroid Build Coastguard Worker else: 1696*cda5da8dSAndroid Build Coastguard Worker start = max(0, min(start, len(lines) - context)) 1697*cda5da8dSAndroid Build Coastguard Worker lines = lines[start:start+context] 1698*cda5da8dSAndroid Build Coastguard Worker index = lineno - 1 - start 1699*cda5da8dSAndroid Build Coastguard Worker else: 1700*cda5da8dSAndroid Build Coastguard Worker lines = index = None 1701*cda5da8dSAndroid Build Coastguard Worker 1702*cda5da8dSAndroid Build Coastguard Worker return Traceback(filename, lineno, frame.f_code.co_name, lines, 1703*cda5da8dSAndroid Build Coastguard Worker index, positions=dis.Positions(*positions)) 1704*cda5da8dSAndroid Build Coastguard Worker 1705*cda5da8dSAndroid Build Coastguard Workerdef getlineno(frame): 1706*cda5da8dSAndroid Build Coastguard Worker """Get the line number from a frame object, allowing for optimization.""" 1707*cda5da8dSAndroid Build Coastguard Worker # FrameType.f_lineno is now a descriptor that grovels co_lnotab 1708*cda5da8dSAndroid Build Coastguard Worker return frame.f_lineno 1709*cda5da8dSAndroid Build Coastguard Worker 1710*cda5da8dSAndroid Build Coastguard Worker_FrameInfo = namedtuple('_FrameInfo', ('frame',) + Traceback._fields) 1711*cda5da8dSAndroid Build Coastguard Workerclass FrameInfo(_FrameInfo): 1712*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, frame, filename, lineno, function, code_context, index, *, positions=None): 1713*cda5da8dSAndroid Build Coastguard Worker instance = super().__new__(cls, frame, filename, lineno, function, code_context, index) 1714*cda5da8dSAndroid Build Coastguard Worker instance.positions = positions 1715*cda5da8dSAndroid Build Coastguard Worker return instance 1716*cda5da8dSAndroid Build Coastguard Worker 1717*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1718*cda5da8dSAndroid Build Coastguard Worker return ('FrameInfo(frame={!r}, filename={!r}, lineno={!r}, function={!r}, ' 1719*cda5da8dSAndroid Build Coastguard Worker 'code_context={!r}, index={!r}, positions={!r})'.format( 1720*cda5da8dSAndroid Build Coastguard Worker self.frame, self.filename, self.lineno, self.function, 1721*cda5da8dSAndroid Build Coastguard Worker self.code_context, self.index, self.positions)) 1722*cda5da8dSAndroid Build Coastguard Worker 1723*cda5da8dSAndroid Build Coastguard Workerdef getouterframes(frame, context=1): 1724*cda5da8dSAndroid Build Coastguard Worker """Get a list of records for a frame and all higher (calling) frames. 1725*cda5da8dSAndroid Build Coastguard Worker 1726*cda5da8dSAndroid Build Coastguard Worker Each record contains a frame object, filename, line number, function 1727*cda5da8dSAndroid Build Coastguard Worker name, a list of lines of context, and index within the context.""" 1728*cda5da8dSAndroid Build Coastguard Worker framelist = [] 1729*cda5da8dSAndroid Build Coastguard Worker while frame: 1730*cda5da8dSAndroid Build Coastguard Worker traceback_info = getframeinfo(frame, context) 1731*cda5da8dSAndroid Build Coastguard Worker frameinfo = (frame,) + traceback_info 1732*cda5da8dSAndroid Build Coastguard Worker framelist.append(FrameInfo(*frameinfo, positions=traceback_info.positions)) 1733*cda5da8dSAndroid Build Coastguard Worker frame = frame.f_back 1734*cda5da8dSAndroid Build Coastguard Worker return framelist 1735*cda5da8dSAndroid Build Coastguard Worker 1736*cda5da8dSAndroid Build Coastguard Workerdef getinnerframes(tb, context=1): 1737*cda5da8dSAndroid Build Coastguard Worker """Get a list of records for a traceback's frame and all lower frames. 1738*cda5da8dSAndroid Build Coastguard Worker 1739*cda5da8dSAndroid Build Coastguard Worker Each record contains a frame object, filename, line number, function 1740*cda5da8dSAndroid Build Coastguard Worker name, a list of lines of context, and index within the context.""" 1741*cda5da8dSAndroid Build Coastguard Worker framelist = [] 1742*cda5da8dSAndroid Build Coastguard Worker while tb: 1743*cda5da8dSAndroid Build Coastguard Worker traceback_info = getframeinfo(tb, context) 1744*cda5da8dSAndroid Build Coastguard Worker frameinfo = (tb.tb_frame,) + traceback_info 1745*cda5da8dSAndroid Build Coastguard Worker framelist.append(FrameInfo(*frameinfo, positions=traceback_info.positions)) 1746*cda5da8dSAndroid Build Coastguard Worker tb = tb.tb_next 1747*cda5da8dSAndroid Build Coastguard Worker return framelist 1748*cda5da8dSAndroid Build Coastguard Worker 1749*cda5da8dSAndroid Build Coastguard Workerdef currentframe(): 1750*cda5da8dSAndroid Build Coastguard Worker """Return the frame of the caller or None if this is not possible.""" 1751*cda5da8dSAndroid Build Coastguard Worker return sys._getframe(1) if hasattr(sys, "_getframe") else None 1752*cda5da8dSAndroid Build Coastguard Worker 1753*cda5da8dSAndroid Build Coastguard Workerdef stack(context=1): 1754*cda5da8dSAndroid Build Coastguard Worker """Return a list of records for the stack above the caller's frame.""" 1755*cda5da8dSAndroid Build Coastguard Worker return getouterframes(sys._getframe(1), context) 1756*cda5da8dSAndroid Build Coastguard Worker 1757*cda5da8dSAndroid Build Coastguard Workerdef trace(context=1): 1758*cda5da8dSAndroid Build Coastguard Worker """Return a list of records for the stack below the current exception.""" 1759*cda5da8dSAndroid Build Coastguard Worker return getinnerframes(sys.exc_info()[2], context) 1760*cda5da8dSAndroid Build Coastguard Worker 1761*cda5da8dSAndroid Build Coastguard Worker 1762*cda5da8dSAndroid Build Coastguard Worker# ------------------------------------------------ static version of getattr 1763*cda5da8dSAndroid Build Coastguard Worker 1764*cda5da8dSAndroid Build Coastguard Worker_sentinel = object() 1765*cda5da8dSAndroid Build Coastguard Worker 1766*cda5da8dSAndroid Build Coastguard Workerdef _static_getmro(klass): 1767*cda5da8dSAndroid Build Coastguard Worker return type.__dict__['__mro__'].__get__(klass) 1768*cda5da8dSAndroid Build Coastguard Worker 1769*cda5da8dSAndroid Build Coastguard Workerdef _check_instance(obj, attr): 1770*cda5da8dSAndroid Build Coastguard Worker instance_dict = {} 1771*cda5da8dSAndroid Build Coastguard Worker try: 1772*cda5da8dSAndroid Build Coastguard Worker instance_dict = object.__getattribute__(obj, "__dict__") 1773*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1774*cda5da8dSAndroid Build Coastguard Worker pass 1775*cda5da8dSAndroid Build Coastguard Worker return dict.get(instance_dict, attr, _sentinel) 1776*cda5da8dSAndroid Build Coastguard Worker 1777*cda5da8dSAndroid Build Coastguard Worker 1778*cda5da8dSAndroid Build Coastguard Workerdef _check_class(klass, attr): 1779*cda5da8dSAndroid Build Coastguard Worker for entry in _static_getmro(klass): 1780*cda5da8dSAndroid Build Coastguard Worker if _shadowed_dict(type(entry)) is _sentinel: 1781*cda5da8dSAndroid Build Coastguard Worker try: 1782*cda5da8dSAndroid Build Coastguard Worker return entry.__dict__[attr] 1783*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1784*cda5da8dSAndroid Build Coastguard Worker pass 1785*cda5da8dSAndroid Build Coastguard Worker return _sentinel 1786*cda5da8dSAndroid Build Coastguard Worker 1787*cda5da8dSAndroid Build Coastguard Workerdef _is_type(obj): 1788*cda5da8dSAndroid Build Coastguard Worker try: 1789*cda5da8dSAndroid Build Coastguard Worker _static_getmro(obj) 1790*cda5da8dSAndroid Build Coastguard Worker except TypeError: 1791*cda5da8dSAndroid Build Coastguard Worker return False 1792*cda5da8dSAndroid Build Coastguard Worker return True 1793*cda5da8dSAndroid Build Coastguard Worker 1794*cda5da8dSAndroid Build Coastguard Workerdef _shadowed_dict(klass): 1795*cda5da8dSAndroid Build Coastguard Worker dict_attr = type.__dict__["__dict__"] 1796*cda5da8dSAndroid Build Coastguard Worker for entry in _static_getmro(klass): 1797*cda5da8dSAndroid Build Coastguard Worker try: 1798*cda5da8dSAndroid Build Coastguard Worker class_dict = dict_attr.__get__(entry)["__dict__"] 1799*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1800*cda5da8dSAndroid Build Coastguard Worker pass 1801*cda5da8dSAndroid Build Coastguard Worker else: 1802*cda5da8dSAndroid Build Coastguard Worker if not (type(class_dict) is types.GetSetDescriptorType and 1803*cda5da8dSAndroid Build Coastguard Worker class_dict.__name__ == "__dict__" and 1804*cda5da8dSAndroid Build Coastguard Worker class_dict.__objclass__ is entry): 1805*cda5da8dSAndroid Build Coastguard Worker return class_dict 1806*cda5da8dSAndroid Build Coastguard Worker return _sentinel 1807*cda5da8dSAndroid Build Coastguard Worker 1808*cda5da8dSAndroid Build Coastguard Workerdef getattr_static(obj, attr, default=_sentinel): 1809*cda5da8dSAndroid Build Coastguard Worker """Retrieve attributes without triggering dynamic lookup via the 1810*cda5da8dSAndroid Build Coastguard Worker descriptor protocol, __getattr__ or __getattribute__. 1811*cda5da8dSAndroid Build Coastguard Worker 1812*cda5da8dSAndroid Build Coastguard Worker Note: this function may not be able to retrieve all attributes 1813*cda5da8dSAndroid Build Coastguard Worker that getattr can fetch (like dynamically created attributes) 1814*cda5da8dSAndroid Build Coastguard Worker and may find attributes that getattr can't (like descriptors 1815*cda5da8dSAndroid Build Coastguard Worker that raise AttributeError). It can also return descriptor objects 1816*cda5da8dSAndroid Build Coastguard Worker instead of instance members in some cases. See the 1817*cda5da8dSAndroid Build Coastguard Worker documentation for details. 1818*cda5da8dSAndroid Build Coastguard Worker """ 1819*cda5da8dSAndroid Build Coastguard Worker instance_result = _sentinel 1820*cda5da8dSAndroid Build Coastguard Worker if not _is_type(obj): 1821*cda5da8dSAndroid Build Coastguard Worker klass = type(obj) 1822*cda5da8dSAndroid Build Coastguard Worker dict_attr = _shadowed_dict(klass) 1823*cda5da8dSAndroid Build Coastguard Worker if (dict_attr is _sentinel or 1824*cda5da8dSAndroid Build Coastguard Worker type(dict_attr) is types.MemberDescriptorType): 1825*cda5da8dSAndroid Build Coastguard Worker instance_result = _check_instance(obj, attr) 1826*cda5da8dSAndroid Build Coastguard Worker else: 1827*cda5da8dSAndroid Build Coastguard Worker klass = obj 1828*cda5da8dSAndroid Build Coastguard Worker 1829*cda5da8dSAndroid Build Coastguard Worker klass_result = _check_class(klass, attr) 1830*cda5da8dSAndroid Build Coastguard Worker 1831*cda5da8dSAndroid Build Coastguard Worker if instance_result is not _sentinel and klass_result is not _sentinel: 1832*cda5da8dSAndroid Build Coastguard Worker if _check_class(type(klass_result), "__get__") is not _sentinel and ( 1833*cda5da8dSAndroid Build Coastguard Worker _check_class(type(klass_result), "__set__") is not _sentinel 1834*cda5da8dSAndroid Build Coastguard Worker or _check_class(type(klass_result), "__delete__") is not _sentinel 1835*cda5da8dSAndroid Build Coastguard Worker ): 1836*cda5da8dSAndroid Build Coastguard Worker return klass_result 1837*cda5da8dSAndroid Build Coastguard Worker 1838*cda5da8dSAndroid Build Coastguard Worker if instance_result is not _sentinel: 1839*cda5da8dSAndroid Build Coastguard Worker return instance_result 1840*cda5da8dSAndroid Build Coastguard Worker if klass_result is not _sentinel: 1841*cda5da8dSAndroid Build Coastguard Worker return klass_result 1842*cda5da8dSAndroid Build Coastguard Worker 1843*cda5da8dSAndroid Build Coastguard Worker if obj is klass: 1844*cda5da8dSAndroid Build Coastguard Worker # for types we check the metaclass too 1845*cda5da8dSAndroid Build Coastguard Worker for entry in _static_getmro(type(klass)): 1846*cda5da8dSAndroid Build Coastguard Worker if _shadowed_dict(type(entry)) is _sentinel: 1847*cda5da8dSAndroid Build Coastguard Worker try: 1848*cda5da8dSAndroid Build Coastguard Worker return entry.__dict__[attr] 1849*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1850*cda5da8dSAndroid Build Coastguard Worker pass 1851*cda5da8dSAndroid Build Coastguard Worker if default is not _sentinel: 1852*cda5da8dSAndroid Build Coastguard Worker return default 1853*cda5da8dSAndroid Build Coastguard Worker raise AttributeError(attr) 1854*cda5da8dSAndroid Build Coastguard Worker 1855*cda5da8dSAndroid Build Coastguard Worker 1856*cda5da8dSAndroid Build Coastguard Worker# ------------------------------------------------ generator introspection 1857*cda5da8dSAndroid Build Coastguard Worker 1858*cda5da8dSAndroid Build Coastguard WorkerGEN_CREATED = 'GEN_CREATED' 1859*cda5da8dSAndroid Build Coastguard WorkerGEN_RUNNING = 'GEN_RUNNING' 1860*cda5da8dSAndroid Build Coastguard WorkerGEN_SUSPENDED = 'GEN_SUSPENDED' 1861*cda5da8dSAndroid Build Coastguard WorkerGEN_CLOSED = 'GEN_CLOSED' 1862*cda5da8dSAndroid Build Coastguard Worker 1863*cda5da8dSAndroid Build Coastguard Workerdef getgeneratorstate(generator): 1864*cda5da8dSAndroid Build Coastguard Worker """Get current state of a generator-iterator. 1865*cda5da8dSAndroid Build Coastguard Worker 1866*cda5da8dSAndroid Build Coastguard Worker Possible states are: 1867*cda5da8dSAndroid Build Coastguard Worker GEN_CREATED: Waiting to start execution. 1868*cda5da8dSAndroid Build Coastguard Worker GEN_RUNNING: Currently being executed by the interpreter. 1869*cda5da8dSAndroid Build Coastguard Worker GEN_SUSPENDED: Currently suspended at a yield expression. 1870*cda5da8dSAndroid Build Coastguard Worker GEN_CLOSED: Execution has completed. 1871*cda5da8dSAndroid Build Coastguard Worker """ 1872*cda5da8dSAndroid Build Coastguard Worker if generator.gi_running: 1873*cda5da8dSAndroid Build Coastguard Worker return GEN_RUNNING 1874*cda5da8dSAndroid Build Coastguard Worker if generator.gi_suspended: 1875*cda5da8dSAndroid Build Coastguard Worker return GEN_SUSPENDED 1876*cda5da8dSAndroid Build Coastguard Worker if generator.gi_frame is None: 1877*cda5da8dSAndroid Build Coastguard Worker return GEN_CLOSED 1878*cda5da8dSAndroid Build Coastguard Worker return GEN_CREATED 1879*cda5da8dSAndroid Build Coastguard Worker 1880*cda5da8dSAndroid Build Coastguard Worker 1881*cda5da8dSAndroid Build Coastguard Workerdef getgeneratorlocals(generator): 1882*cda5da8dSAndroid Build Coastguard Worker """ 1883*cda5da8dSAndroid Build Coastguard Worker Get the mapping of generator local variables to their current values. 1884*cda5da8dSAndroid Build Coastguard Worker 1885*cda5da8dSAndroid Build Coastguard Worker A dict is returned, with the keys the local variable names and values the 1886*cda5da8dSAndroid Build Coastguard Worker bound values.""" 1887*cda5da8dSAndroid Build Coastguard Worker 1888*cda5da8dSAndroid Build Coastguard Worker if not isgenerator(generator): 1889*cda5da8dSAndroid Build Coastguard Worker raise TypeError("{!r} is not a Python generator".format(generator)) 1890*cda5da8dSAndroid Build Coastguard Worker 1891*cda5da8dSAndroid Build Coastguard Worker frame = getattr(generator, "gi_frame", None) 1892*cda5da8dSAndroid Build Coastguard Worker if frame is not None: 1893*cda5da8dSAndroid Build Coastguard Worker return generator.gi_frame.f_locals 1894*cda5da8dSAndroid Build Coastguard Worker else: 1895*cda5da8dSAndroid Build Coastguard Worker return {} 1896*cda5da8dSAndroid Build Coastguard Worker 1897*cda5da8dSAndroid Build Coastguard Worker 1898*cda5da8dSAndroid Build Coastguard Worker# ------------------------------------------------ coroutine introspection 1899*cda5da8dSAndroid Build Coastguard Worker 1900*cda5da8dSAndroid Build Coastguard WorkerCORO_CREATED = 'CORO_CREATED' 1901*cda5da8dSAndroid Build Coastguard WorkerCORO_RUNNING = 'CORO_RUNNING' 1902*cda5da8dSAndroid Build Coastguard WorkerCORO_SUSPENDED = 'CORO_SUSPENDED' 1903*cda5da8dSAndroid Build Coastguard WorkerCORO_CLOSED = 'CORO_CLOSED' 1904*cda5da8dSAndroid Build Coastguard Worker 1905*cda5da8dSAndroid Build Coastguard Workerdef getcoroutinestate(coroutine): 1906*cda5da8dSAndroid Build Coastguard Worker """Get current state of a coroutine object. 1907*cda5da8dSAndroid Build Coastguard Worker 1908*cda5da8dSAndroid Build Coastguard Worker Possible states are: 1909*cda5da8dSAndroid Build Coastguard Worker CORO_CREATED: Waiting to start execution. 1910*cda5da8dSAndroid Build Coastguard Worker CORO_RUNNING: Currently being executed by the interpreter. 1911*cda5da8dSAndroid Build Coastguard Worker CORO_SUSPENDED: Currently suspended at an await expression. 1912*cda5da8dSAndroid Build Coastguard Worker CORO_CLOSED: Execution has completed. 1913*cda5da8dSAndroid Build Coastguard Worker """ 1914*cda5da8dSAndroid Build Coastguard Worker if coroutine.cr_running: 1915*cda5da8dSAndroid Build Coastguard Worker return CORO_RUNNING 1916*cda5da8dSAndroid Build Coastguard Worker if coroutine.cr_suspended: 1917*cda5da8dSAndroid Build Coastguard Worker return CORO_SUSPENDED 1918*cda5da8dSAndroid Build Coastguard Worker if coroutine.cr_frame is None: 1919*cda5da8dSAndroid Build Coastguard Worker return CORO_CLOSED 1920*cda5da8dSAndroid Build Coastguard Worker return CORO_CREATED 1921*cda5da8dSAndroid Build Coastguard Worker 1922*cda5da8dSAndroid Build Coastguard Worker 1923*cda5da8dSAndroid Build Coastguard Workerdef getcoroutinelocals(coroutine): 1924*cda5da8dSAndroid Build Coastguard Worker """ 1925*cda5da8dSAndroid Build Coastguard Worker Get the mapping of coroutine local variables to their current values. 1926*cda5da8dSAndroid Build Coastguard Worker 1927*cda5da8dSAndroid Build Coastguard Worker A dict is returned, with the keys the local variable names and values the 1928*cda5da8dSAndroid Build Coastguard Worker bound values.""" 1929*cda5da8dSAndroid Build Coastguard Worker frame = getattr(coroutine, "cr_frame", None) 1930*cda5da8dSAndroid Build Coastguard Worker if frame is not None: 1931*cda5da8dSAndroid Build Coastguard Worker return frame.f_locals 1932*cda5da8dSAndroid Build Coastguard Worker else: 1933*cda5da8dSAndroid Build Coastguard Worker return {} 1934*cda5da8dSAndroid Build Coastguard Worker 1935*cda5da8dSAndroid Build Coastguard Worker 1936*cda5da8dSAndroid Build Coastguard Worker############################################################################### 1937*cda5da8dSAndroid Build Coastguard Worker### Function Signature Object (PEP 362) 1938*cda5da8dSAndroid Build Coastguard Worker############################################################################### 1939*cda5da8dSAndroid Build Coastguard Worker 1940*cda5da8dSAndroid Build Coastguard Worker 1941*cda5da8dSAndroid Build Coastguard Worker_NonUserDefinedCallables = (types.WrapperDescriptorType, 1942*cda5da8dSAndroid Build Coastguard Worker types.MethodWrapperType, 1943*cda5da8dSAndroid Build Coastguard Worker types.ClassMethodDescriptorType, 1944*cda5da8dSAndroid Build Coastguard Worker types.BuiltinFunctionType) 1945*cda5da8dSAndroid Build Coastguard Worker 1946*cda5da8dSAndroid Build Coastguard Worker 1947*cda5da8dSAndroid Build Coastguard Workerdef _signature_get_user_defined_method(cls, method_name): 1948*cda5da8dSAndroid Build Coastguard Worker """Private helper. Checks if ``cls`` has an attribute 1949*cda5da8dSAndroid Build Coastguard Worker named ``method_name`` and returns it only if it is a 1950*cda5da8dSAndroid Build Coastguard Worker pure python function. 1951*cda5da8dSAndroid Build Coastguard Worker """ 1952*cda5da8dSAndroid Build Coastguard Worker try: 1953*cda5da8dSAndroid Build Coastguard Worker meth = getattr(cls, method_name) 1954*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1955*cda5da8dSAndroid Build Coastguard Worker return 1956*cda5da8dSAndroid Build Coastguard Worker else: 1957*cda5da8dSAndroid Build Coastguard Worker if not isinstance(meth, _NonUserDefinedCallables): 1958*cda5da8dSAndroid Build Coastguard Worker # Once '__signature__' will be added to 'C'-level 1959*cda5da8dSAndroid Build Coastguard Worker # callables, this check won't be necessary 1960*cda5da8dSAndroid Build Coastguard Worker return meth 1961*cda5da8dSAndroid Build Coastguard Worker 1962*cda5da8dSAndroid Build Coastguard Worker 1963*cda5da8dSAndroid Build Coastguard Workerdef _signature_get_partial(wrapped_sig, partial, extra_args=()): 1964*cda5da8dSAndroid Build Coastguard Worker """Private helper to calculate how 'wrapped_sig' signature will 1965*cda5da8dSAndroid Build Coastguard Worker look like after applying a 'functools.partial' object (or alike) 1966*cda5da8dSAndroid Build Coastguard Worker on it. 1967*cda5da8dSAndroid Build Coastguard Worker """ 1968*cda5da8dSAndroid Build Coastguard Worker 1969*cda5da8dSAndroid Build Coastguard Worker old_params = wrapped_sig.parameters 1970*cda5da8dSAndroid Build Coastguard Worker new_params = OrderedDict(old_params.items()) 1971*cda5da8dSAndroid Build Coastguard Worker 1972*cda5da8dSAndroid Build Coastguard Worker partial_args = partial.args or () 1973*cda5da8dSAndroid Build Coastguard Worker partial_keywords = partial.keywords or {} 1974*cda5da8dSAndroid Build Coastguard Worker 1975*cda5da8dSAndroid Build Coastguard Worker if extra_args: 1976*cda5da8dSAndroid Build Coastguard Worker partial_args = extra_args + partial_args 1977*cda5da8dSAndroid Build Coastguard Worker 1978*cda5da8dSAndroid Build Coastguard Worker try: 1979*cda5da8dSAndroid Build Coastguard Worker ba = wrapped_sig.bind_partial(*partial_args, **partial_keywords) 1980*cda5da8dSAndroid Build Coastguard Worker except TypeError as ex: 1981*cda5da8dSAndroid Build Coastguard Worker msg = 'partial object {!r} has incorrect arguments'.format(partial) 1982*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) from ex 1983*cda5da8dSAndroid Build Coastguard Worker 1984*cda5da8dSAndroid Build Coastguard Worker 1985*cda5da8dSAndroid Build Coastguard Worker transform_to_kwonly = False 1986*cda5da8dSAndroid Build Coastguard Worker for param_name, param in old_params.items(): 1987*cda5da8dSAndroid Build Coastguard Worker try: 1988*cda5da8dSAndroid Build Coastguard Worker arg_value = ba.arguments[param_name] 1989*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1990*cda5da8dSAndroid Build Coastguard Worker pass 1991*cda5da8dSAndroid Build Coastguard Worker else: 1992*cda5da8dSAndroid Build Coastguard Worker if param.kind is _POSITIONAL_ONLY: 1993*cda5da8dSAndroid Build Coastguard Worker # If positional-only parameter is bound by partial, 1994*cda5da8dSAndroid Build Coastguard Worker # it effectively disappears from the signature 1995*cda5da8dSAndroid Build Coastguard Worker new_params.pop(param_name) 1996*cda5da8dSAndroid Build Coastguard Worker continue 1997*cda5da8dSAndroid Build Coastguard Worker 1998*cda5da8dSAndroid Build Coastguard Worker if param.kind is _POSITIONAL_OR_KEYWORD: 1999*cda5da8dSAndroid Build Coastguard Worker if param_name in partial_keywords: 2000*cda5da8dSAndroid Build Coastguard Worker # This means that this parameter, and all parameters 2001*cda5da8dSAndroid Build Coastguard Worker # after it should be keyword-only (and var-positional 2002*cda5da8dSAndroid Build Coastguard Worker # should be removed). Here's why. Consider the following 2003*cda5da8dSAndroid Build Coastguard Worker # function: 2004*cda5da8dSAndroid Build Coastguard Worker # foo(a, b, *args, c): 2005*cda5da8dSAndroid Build Coastguard Worker # pass 2006*cda5da8dSAndroid Build Coastguard Worker # 2007*cda5da8dSAndroid Build Coastguard Worker # "partial(foo, a='spam')" will have the following 2008*cda5da8dSAndroid Build Coastguard Worker # signature: "(*, a='spam', b, c)". Because attempting 2009*cda5da8dSAndroid Build Coastguard Worker # to call that partial with "(10, 20)" arguments will 2010*cda5da8dSAndroid Build Coastguard Worker # raise a TypeError, saying that "a" argument received 2011*cda5da8dSAndroid Build Coastguard Worker # multiple values. 2012*cda5da8dSAndroid Build Coastguard Worker transform_to_kwonly = True 2013*cda5da8dSAndroid Build Coastguard Worker # Set the new default value 2014*cda5da8dSAndroid Build Coastguard Worker new_params[param_name] = param.replace(default=arg_value) 2015*cda5da8dSAndroid Build Coastguard Worker else: 2016*cda5da8dSAndroid Build Coastguard Worker # was passed as a positional argument 2017*cda5da8dSAndroid Build Coastguard Worker new_params.pop(param.name) 2018*cda5da8dSAndroid Build Coastguard Worker continue 2019*cda5da8dSAndroid Build Coastguard Worker 2020*cda5da8dSAndroid Build Coastguard Worker if param.kind is _KEYWORD_ONLY: 2021*cda5da8dSAndroid Build Coastguard Worker # Set the new default value 2022*cda5da8dSAndroid Build Coastguard Worker new_params[param_name] = param.replace(default=arg_value) 2023*cda5da8dSAndroid Build Coastguard Worker 2024*cda5da8dSAndroid Build Coastguard Worker if transform_to_kwonly: 2025*cda5da8dSAndroid Build Coastguard Worker assert param.kind is not _POSITIONAL_ONLY 2026*cda5da8dSAndroid Build Coastguard Worker 2027*cda5da8dSAndroid Build Coastguard Worker if param.kind is _POSITIONAL_OR_KEYWORD: 2028*cda5da8dSAndroid Build Coastguard Worker new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY) 2029*cda5da8dSAndroid Build Coastguard Worker new_params[param_name] = new_param 2030*cda5da8dSAndroid Build Coastguard Worker new_params.move_to_end(param_name) 2031*cda5da8dSAndroid Build Coastguard Worker elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD): 2032*cda5da8dSAndroid Build Coastguard Worker new_params.move_to_end(param_name) 2033*cda5da8dSAndroid Build Coastguard Worker elif param.kind is _VAR_POSITIONAL: 2034*cda5da8dSAndroid Build Coastguard Worker new_params.pop(param.name) 2035*cda5da8dSAndroid Build Coastguard Worker 2036*cda5da8dSAndroid Build Coastguard Worker return wrapped_sig.replace(parameters=new_params.values()) 2037*cda5da8dSAndroid Build Coastguard Worker 2038*cda5da8dSAndroid Build Coastguard Worker 2039*cda5da8dSAndroid Build Coastguard Workerdef _signature_bound_method(sig): 2040*cda5da8dSAndroid Build Coastguard Worker """Private helper to transform signatures for unbound 2041*cda5da8dSAndroid Build Coastguard Worker functions to bound methods. 2042*cda5da8dSAndroid Build Coastguard Worker """ 2043*cda5da8dSAndroid Build Coastguard Worker 2044*cda5da8dSAndroid Build Coastguard Worker params = tuple(sig.parameters.values()) 2045*cda5da8dSAndroid Build Coastguard Worker 2046*cda5da8dSAndroid Build Coastguard Worker if not params or params[0].kind in (_VAR_KEYWORD, _KEYWORD_ONLY): 2047*cda5da8dSAndroid Build Coastguard Worker raise ValueError('invalid method signature') 2048*cda5da8dSAndroid Build Coastguard Worker 2049*cda5da8dSAndroid Build Coastguard Worker kind = params[0].kind 2050*cda5da8dSAndroid Build Coastguard Worker if kind in (_POSITIONAL_OR_KEYWORD, _POSITIONAL_ONLY): 2051*cda5da8dSAndroid Build Coastguard Worker # Drop first parameter: 2052*cda5da8dSAndroid Build Coastguard Worker # '(p1, p2[, ...])' -> '(p2[, ...])' 2053*cda5da8dSAndroid Build Coastguard Worker params = params[1:] 2054*cda5da8dSAndroid Build Coastguard Worker else: 2055*cda5da8dSAndroid Build Coastguard Worker if kind is not _VAR_POSITIONAL: 2056*cda5da8dSAndroid Build Coastguard Worker # Unless we add a new parameter type we never 2057*cda5da8dSAndroid Build Coastguard Worker # get here 2058*cda5da8dSAndroid Build Coastguard Worker raise ValueError('invalid argument type') 2059*cda5da8dSAndroid Build Coastguard Worker # It's a var-positional parameter. 2060*cda5da8dSAndroid Build Coastguard Worker # Do nothing. '(*args[, ...])' -> '(*args[, ...])' 2061*cda5da8dSAndroid Build Coastguard Worker 2062*cda5da8dSAndroid Build Coastguard Worker return sig.replace(parameters=params) 2063*cda5da8dSAndroid Build Coastguard Worker 2064*cda5da8dSAndroid Build Coastguard Worker 2065*cda5da8dSAndroid Build Coastguard Workerdef _signature_is_builtin(obj): 2066*cda5da8dSAndroid Build Coastguard Worker """Private helper to test if `obj` is a callable that might 2067*cda5da8dSAndroid Build Coastguard Worker support Argument Clinic's __text_signature__ protocol. 2068*cda5da8dSAndroid Build Coastguard Worker """ 2069*cda5da8dSAndroid Build Coastguard Worker return (isbuiltin(obj) or 2070*cda5da8dSAndroid Build Coastguard Worker ismethoddescriptor(obj) or 2071*cda5da8dSAndroid Build Coastguard Worker isinstance(obj, _NonUserDefinedCallables) or 2072*cda5da8dSAndroid Build Coastguard Worker # Can't test 'isinstance(type)' here, as it would 2073*cda5da8dSAndroid Build Coastguard Worker # also be True for regular python classes 2074*cda5da8dSAndroid Build Coastguard Worker obj in (type, object)) 2075*cda5da8dSAndroid Build Coastguard Worker 2076*cda5da8dSAndroid Build Coastguard Worker 2077*cda5da8dSAndroid Build Coastguard Workerdef _signature_is_functionlike(obj): 2078*cda5da8dSAndroid Build Coastguard Worker """Private helper to test if `obj` is a duck type of FunctionType. 2079*cda5da8dSAndroid Build Coastguard Worker A good example of such objects are functions compiled with 2080*cda5da8dSAndroid Build Coastguard Worker Cython, which have all attributes that a pure Python function 2081*cda5da8dSAndroid Build Coastguard Worker would have, but have their code statically compiled. 2082*cda5da8dSAndroid Build Coastguard Worker """ 2083*cda5da8dSAndroid Build Coastguard Worker 2084*cda5da8dSAndroid Build Coastguard Worker if not callable(obj) or isclass(obj): 2085*cda5da8dSAndroid Build Coastguard Worker # All function-like objects are obviously callables, 2086*cda5da8dSAndroid Build Coastguard Worker # and not classes. 2087*cda5da8dSAndroid Build Coastguard Worker return False 2088*cda5da8dSAndroid Build Coastguard Worker 2089*cda5da8dSAndroid Build Coastguard Worker name = getattr(obj, '__name__', None) 2090*cda5da8dSAndroid Build Coastguard Worker code = getattr(obj, '__code__', None) 2091*cda5da8dSAndroid Build Coastguard Worker defaults = getattr(obj, '__defaults__', _void) # Important to use _void ... 2092*cda5da8dSAndroid Build Coastguard Worker kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here 2093*cda5da8dSAndroid Build Coastguard Worker annotations = getattr(obj, '__annotations__', None) 2094*cda5da8dSAndroid Build Coastguard Worker 2095*cda5da8dSAndroid Build Coastguard Worker return (isinstance(code, types.CodeType) and 2096*cda5da8dSAndroid Build Coastguard Worker isinstance(name, str) and 2097*cda5da8dSAndroid Build Coastguard Worker (defaults is None or isinstance(defaults, tuple)) and 2098*cda5da8dSAndroid Build Coastguard Worker (kwdefaults is None or isinstance(kwdefaults, dict)) and 2099*cda5da8dSAndroid Build Coastguard Worker (isinstance(annotations, (dict)) or annotations is None) ) 2100*cda5da8dSAndroid Build Coastguard Worker 2101*cda5da8dSAndroid Build Coastguard Worker 2102*cda5da8dSAndroid Build Coastguard Workerdef _signature_strip_non_python_syntax(signature): 2103*cda5da8dSAndroid Build Coastguard Worker """ 2104*cda5da8dSAndroid Build Coastguard Worker Private helper function. Takes a signature in Argument Clinic's 2105*cda5da8dSAndroid Build Coastguard Worker extended signature format. 2106*cda5da8dSAndroid Build Coastguard Worker 2107*cda5da8dSAndroid Build Coastguard Worker Returns a tuple of three things: 2108*cda5da8dSAndroid Build Coastguard Worker * that signature re-rendered in standard Python syntax, 2109*cda5da8dSAndroid Build Coastguard Worker * the index of the "self" parameter (generally 0), or None if 2110*cda5da8dSAndroid Build Coastguard Worker the function does not have a "self" parameter, and 2111*cda5da8dSAndroid Build Coastguard Worker * the index of the last "positional only" parameter, 2112*cda5da8dSAndroid Build Coastguard Worker or None if the signature has no positional-only parameters. 2113*cda5da8dSAndroid Build Coastguard Worker """ 2114*cda5da8dSAndroid Build Coastguard Worker 2115*cda5da8dSAndroid Build Coastguard Worker if not signature: 2116*cda5da8dSAndroid Build Coastguard Worker return signature, None, None 2117*cda5da8dSAndroid Build Coastguard Worker 2118*cda5da8dSAndroid Build Coastguard Worker self_parameter = None 2119*cda5da8dSAndroid Build Coastguard Worker last_positional_only = None 2120*cda5da8dSAndroid Build Coastguard Worker 2121*cda5da8dSAndroid Build Coastguard Worker lines = [l.encode('ascii') for l in signature.split('\n') if l] 2122*cda5da8dSAndroid Build Coastguard Worker generator = iter(lines).__next__ 2123*cda5da8dSAndroid Build Coastguard Worker token_stream = tokenize.tokenize(generator) 2124*cda5da8dSAndroid Build Coastguard Worker 2125*cda5da8dSAndroid Build Coastguard Worker delayed_comma = False 2126*cda5da8dSAndroid Build Coastguard Worker skip_next_comma = False 2127*cda5da8dSAndroid Build Coastguard Worker text = [] 2128*cda5da8dSAndroid Build Coastguard Worker add = text.append 2129*cda5da8dSAndroid Build Coastguard Worker 2130*cda5da8dSAndroid Build Coastguard Worker current_parameter = 0 2131*cda5da8dSAndroid Build Coastguard Worker OP = token.OP 2132*cda5da8dSAndroid Build Coastguard Worker ERRORTOKEN = token.ERRORTOKEN 2133*cda5da8dSAndroid Build Coastguard Worker 2134*cda5da8dSAndroid Build Coastguard Worker # token stream always starts with ENCODING token, skip it 2135*cda5da8dSAndroid Build Coastguard Worker t = next(token_stream) 2136*cda5da8dSAndroid Build Coastguard Worker assert t.type == tokenize.ENCODING 2137*cda5da8dSAndroid Build Coastguard Worker 2138*cda5da8dSAndroid Build Coastguard Worker for t in token_stream: 2139*cda5da8dSAndroid Build Coastguard Worker type, string = t.type, t.string 2140*cda5da8dSAndroid Build Coastguard Worker 2141*cda5da8dSAndroid Build Coastguard Worker if type == OP: 2142*cda5da8dSAndroid Build Coastguard Worker if string == ',': 2143*cda5da8dSAndroid Build Coastguard Worker if skip_next_comma: 2144*cda5da8dSAndroid Build Coastguard Worker skip_next_comma = False 2145*cda5da8dSAndroid Build Coastguard Worker else: 2146*cda5da8dSAndroid Build Coastguard Worker assert not delayed_comma 2147*cda5da8dSAndroid Build Coastguard Worker delayed_comma = True 2148*cda5da8dSAndroid Build Coastguard Worker current_parameter += 1 2149*cda5da8dSAndroid Build Coastguard Worker continue 2150*cda5da8dSAndroid Build Coastguard Worker 2151*cda5da8dSAndroid Build Coastguard Worker if string == '/': 2152*cda5da8dSAndroid Build Coastguard Worker assert not skip_next_comma 2153*cda5da8dSAndroid Build Coastguard Worker assert last_positional_only is None 2154*cda5da8dSAndroid Build Coastguard Worker skip_next_comma = True 2155*cda5da8dSAndroid Build Coastguard Worker last_positional_only = current_parameter - 1 2156*cda5da8dSAndroid Build Coastguard Worker continue 2157*cda5da8dSAndroid Build Coastguard Worker 2158*cda5da8dSAndroid Build Coastguard Worker if (type == ERRORTOKEN) and (string == '$'): 2159*cda5da8dSAndroid Build Coastguard Worker assert self_parameter is None 2160*cda5da8dSAndroid Build Coastguard Worker self_parameter = current_parameter 2161*cda5da8dSAndroid Build Coastguard Worker continue 2162*cda5da8dSAndroid Build Coastguard Worker 2163*cda5da8dSAndroid Build Coastguard Worker if delayed_comma: 2164*cda5da8dSAndroid Build Coastguard Worker delayed_comma = False 2165*cda5da8dSAndroid Build Coastguard Worker if not ((type == OP) and (string == ')')): 2166*cda5da8dSAndroid Build Coastguard Worker add(', ') 2167*cda5da8dSAndroid Build Coastguard Worker add(string) 2168*cda5da8dSAndroid Build Coastguard Worker if (string == ','): 2169*cda5da8dSAndroid Build Coastguard Worker add(' ') 2170*cda5da8dSAndroid Build Coastguard Worker clean_signature = ''.join(text) 2171*cda5da8dSAndroid Build Coastguard Worker return clean_signature, self_parameter, last_positional_only 2172*cda5da8dSAndroid Build Coastguard Worker 2173*cda5da8dSAndroid Build Coastguard Worker 2174*cda5da8dSAndroid Build Coastguard Workerdef _signature_fromstr(cls, obj, s, skip_bound_arg=True): 2175*cda5da8dSAndroid Build Coastguard Worker """Private helper to parse content of '__text_signature__' 2176*cda5da8dSAndroid Build Coastguard Worker and return a Signature based on it. 2177*cda5da8dSAndroid Build Coastguard Worker """ 2178*cda5da8dSAndroid Build Coastguard Worker Parameter = cls._parameter_cls 2179*cda5da8dSAndroid Build Coastguard Worker 2180*cda5da8dSAndroid Build Coastguard Worker clean_signature, self_parameter, last_positional_only = \ 2181*cda5da8dSAndroid Build Coastguard Worker _signature_strip_non_python_syntax(s) 2182*cda5da8dSAndroid Build Coastguard Worker 2183*cda5da8dSAndroid Build Coastguard Worker program = "def foo" + clean_signature + ": pass" 2184*cda5da8dSAndroid Build Coastguard Worker 2185*cda5da8dSAndroid Build Coastguard Worker try: 2186*cda5da8dSAndroid Build Coastguard Worker module = ast.parse(program) 2187*cda5da8dSAndroid Build Coastguard Worker except SyntaxError: 2188*cda5da8dSAndroid Build Coastguard Worker module = None 2189*cda5da8dSAndroid Build Coastguard Worker 2190*cda5da8dSAndroid Build Coastguard Worker if not isinstance(module, ast.Module): 2191*cda5da8dSAndroid Build Coastguard Worker raise ValueError("{!r} builtin has invalid signature".format(obj)) 2192*cda5da8dSAndroid Build Coastguard Worker 2193*cda5da8dSAndroid Build Coastguard Worker f = module.body[0] 2194*cda5da8dSAndroid Build Coastguard Worker 2195*cda5da8dSAndroid Build Coastguard Worker parameters = [] 2196*cda5da8dSAndroid Build Coastguard Worker empty = Parameter.empty 2197*cda5da8dSAndroid Build Coastguard Worker 2198*cda5da8dSAndroid Build Coastguard Worker module = None 2199*cda5da8dSAndroid Build Coastguard Worker module_dict = {} 2200*cda5da8dSAndroid Build Coastguard Worker module_name = getattr(obj, '__module__', None) 2201*cda5da8dSAndroid Build Coastguard Worker if module_name: 2202*cda5da8dSAndroid Build Coastguard Worker module = sys.modules.get(module_name, None) 2203*cda5da8dSAndroid Build Coastguard Worker if module: 2204*cda5da8dSAndroid Build Coastguard Worker module_dict = module.__dict__ 2205*cda5da8dSAndroid Build Coastguard Worker sys_module_dict = sys.modules.copy() 2206*cda5da8dSAndroid Build Coastguard Worker 2207*cda5da8dSAndroid Build Coastguard Worker def parse_name(node): 2208*cda5da8dSAndroid Build Coastguard Worker assert isinstance(node, ast.arg) 2209*cda5da8dSAndroid Build Coastguard Worker if node.annotation is not None: 2210*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Annotations are not currently supported") 2211*cda5da8dSAndroid Build Coastguard Worker return node.arg 2212*cda5da8dSAndroid Build Coastguard Worker 2213*cda5da8dSAndroid Build Coastguard Worker def wrap_value(s): 2214*cda5da8dSAndroid Build Coastguard Worker try: 2215*cda5da8dSAndroid Build Coastguard Worker value = eval(s, module_dict) 2216*cda5da8dSAndroid Build Coastguard Worker except NameError: 2217*cda5da8dSAndroid Build Coastguard Worker try: 2218*cda5da8dSAndroid Build Coastguard Worker value = eval(s, sys_module_dict) 2219*cda5da8dSAndroid Build Coastguard Worker except NameError: 2220*cda5da8dSAndroid Build Coastguard Worker raise ValueError 2221*cda5da8dSAndroid Build Coastguard Worker 2222*cda5da8dSAndroid Build Coastguard Worker if isinstance(value, (str, int, float, bytes, bool, type(None))): 2223*cda5da8dSAndroid Build Coastguard Worker return ast.Constant(value) 2224*cda5da8dSAndroid Build Coastguard Worker raise ValueError 2225*cda5da8dSAndroid Build Coastguard Worker 2226*cda5da8dSAndroid Build Coastguard Worker class RewriteSymbolics(ast.NodeTransformer): 2227*cda5da8dSAndroid Build Coastguard Worker def visit_Attribute(self, node): 2228*cda5da8dSAndroid Build Coastguard Worker a = [] 2229*cda5da8dSAndroid Build Coastguard Worker n = node 2230*cda5da8dSAndroid Build Coastguard Worker while isinstance(n, ast.Attribute): 2231*cda5da8dSAndroid Build Coastguard Worker a.append(n.attr) 2232*cda5da8dSAndroid Build Coastguard Worker n = n.value 2233*cda5da8dSAndroid Build Coastguard Worker if not isinstance(n, ast.Name): 2234*cda5da8dSAndroid Build Coastguard Worker raise ValueError 2235*cda5da8dSAndroid Build Coastguard Worker a.append(n.id) 2236*cda5da8dSAndroid Build Coastguard Worker value = ".".join(reversed(a)) 2237*cda5da8dSAndroid Build Coastguard Worker return wrap_value(value) 2238*cda5da8dSAndroid Build Coastguard Worker 2239*cda5da8dSAndroid Build Coastguard Worker def visit_Name(self, node): 2240*cda5da8dSAndroid Build Coastguard Worker if not isinstance(node.ctx, ast.Load): 2241*cda5da8dSAndroid Build Coastguard Worker raise ValueError() 2242*cda5da8dSAndroid Build Coastguard Worker return wrap_value(node.id) 2243*cda5da8dSAndroid Build Coastguard Worker 2244*cda5da8dSAndroid Build Coastguard Worker def visit_BinOp(self, node): 2245*cda5da8dSAndroid Build Coastguard Worker # Support constant folding of a couple simple binary operations 2246*cda5da8dSAndroid Build Coastguard Worker # commonly used to define default values in text signatures 2247*cda5da8dSAndroid Build Coastguard Worker left = self.visit(node.left) 2248*cda5da8dSAndroid Build Coastguard Worker right = self.visit(node.right) 2249*cda5da8dSAndroid Build Coastguard Worker if not isinstance(left, ast.Constant) or not isinstance(right, ast.Constant): 2250*cda5da8dSAndroid Build Coastguard Worker raise ValueError 2251*cda5da8dSAndroid Build Coastguard Worker if isinstance(node.op, ast.Add): 2252*cda5da8dSAndroid Build Coastguard Worker return ast.Constant(left.value + right.value) 2253*cda5da8dSAndroid Build Coastguard Worker elif isinstance(node.op, ast.Sub): 2254*cda5da8dSAndroid Build Coastguard Worker return ast.Constant(left.value - right.value) 2255*cda5da8dSAndroid Build Coastguard Worker elif isinstance(node.op, ast.BitOr): 2256*cda5da8dSAndroid Build Coastguard Worker return ast.Constant(left.value | right.value) 2257*cda5da8dSAndroid Build Coastguard Worker raise ValueError 2258*cda5da8dSAndroid Build Coastguard Worker 2259*cda5da8dSAndroid Build Coastguard Worker def p(name_node, default_node, default=empty): 2260*cda5da8dSAndroid Build Coastguard Worker name = parse_name(name_node) 2261*cda5da8dSAndroid Build Coastguard Worker if default_node and default_node is not _empty: 2262*cda5da8dSAndroid Build Coastguard Worker try: 2263*cda5da8dSAndroid Build Coastguard Worker default_node = RewriteSymbolics().visit(default_node) 2264*cda5da8dSAndroid Build Coastguard Worker default = ast.literal_eval(default_node) 2265*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2266*cda5da8dSAndroid Build Coastguard Worker raise ValueError("{!r} builtin has invalid signature".format(obj)) from None 2267*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, kind, default=default, annotation=empty)) 2268*cda5da8dSAndroid Build Coastguard Worker 2269*cda5da8dSAndroid Build Coastguard Worker # non-keyword-only parameters 2270*cda5da8dSAndroid Build Coastguard Worker args = reversed(f.args.args) 2271*cda5da8dSAndroid Build Coastguard Worker defaults = reversed(f.args.defaults) 2272*cda5da8dSAndroid Build Coastguard Worker iter = itertools.zip_longest(args, defaults, fillvalue=None) 2273*cda5da8dSAndroid Build Coastguard Worker if last_positional_only is not None: 2274*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.POSITIONAL_ONLY 2275*cda5da8dSAndroid Build Coastguard Worker else: 2276*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.POSITIONAL_OR_KEYWORD 2277*cda5da8dSAndroid Build Coastguard Worker for i, (name, default) in enumerate(reversed(list(iter))): 2278*cda5da8dSAndroid Build Coastguard Worker p(name, default) 2279*cda5da8dSAndroid Build Coastguard Worker if i == last_positional_only: 2280*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.POSITIONAL_OR_KEYWORD 2281*cda5da8dSAndroid Build Coastguard Worker 2282*cda5da8dSAndroid Build Coastguard Worker # *args 2283*cda5da8dSAndroid Build Coastguard Worker if f.args.vararg: 2284*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.VAR_POSITIONAL 2285*cda5da8dSAndroid Build Coastguard Worker p(f.args.vararg, empty) 2286*cda5da8dSAndroid Build Coastguard Worker 2287*cda5da8dSAndroid Build Coastguard Worker # keyword-only arguments 2288*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.KEYWORD_ONLY 2289*cda5da8dSAndroid Build Coastguard Worker for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults): 2290*cda5da8dSAndroid Build Coastguard Worker p(name, default) 2291*cda5da8dSAndroid Build Coastguard Worker 2292*cda5da8dSAndroid Build Coastguard Worker # **kwargs 2293*cda5da8dSAndroid Build Coastguard Worker if f.args.kwarg: 2294*cda5da8dSAndroid Build Coastguard Worker kind = Parameter.VAR_KEYWORD 2295*cda5da8dSAndroid Build Coastguard Worker p(f.args.kwarg, empty) 2296*cda5da8dSAndroid Build Coastguard Worker 2297*cda5da8dSAndroid Build Coastguard Worker if self_parameter is not None: 2298*cda5da8dSAndroid Build Coastguard Worker # Possibly strip the bound argument: 2299*cda5da8dSAndroid Build Coastguard Worker # - We *always* strip first bound argument if 2300*cda5da8dSAndroid Build Coastguard Worker # it is a module. 2301*cda5da8dSAndroid Build Coastguard Worker # - We don't strip first bound argument if 2302*cda5da8dSAndroid Build Coastguard Worker # skip_bound_arg is False. 2303*cda5da8dSAndroid Build Coastguard Worker assert parameters 2304*cda5da8dSAndroid Build Coastguard Worker _self = getattr(obj, '__self__', None) 2305*cda5da8dSAndroid Build Coastguard Worker self_isbound = _self is not None 2306*cda5da8dSAndroid Build Coastguard Worker self_ismodule = ismodule(_self) 2307*cda5da8dSAndroid Build Coastguard Worker if self_isbound and (self_ismodule or skip_bound_arg): 2308*cda5da8dSAndroid Build Coastguard Worker parameters.pop(0) 2309*cda5da8dSAndroid Build Coastguard Worker else: 2310*cda5da8dSAndroid Build Coastguard Worker # for builtins, self parameter is always positional-only! 2311*cda5da8dSAndroid Build Coastguard Worker p = parameters[0].replace(kind=Parameter.POSITIONAL_ONLY) 2312*cda5da8dSAndroid Build Coastguard Worker parameters[0] = p 2313*cda5da8dSAndroid Build Coastguard Worker 2314*cda5da8dSAndroid Build Coastguard Worker return cls(parameters, return_annotation=cls.empty) 2315*cda5da8dSAndroid Build Coastguard Worker 2316*cda5da8dSAndroid Build Coastguard Worker 2317*cda5da8dSAndroid Build Coastguard Workerdef _signature_from_builtin(cls, func, skip_bound_arg=True): 2318*cda5da8dSAndroid Build Coastguard Worker """Private helper function to get signature for 2319*cda5da8dSAndroid Build Coastguard Worker builtin callables. 2320*cda5da8dSAndroid Build Coastguard Worker """ 2321*cda5da8dSAndroid Build Coastguard Worker 2322*cda5da8dSAndroid Build Coastguard Worker if not _signature_is_builtin(func): 2323*cda5da8dSAndroid Build Coastguard Worker raise TypeError("{!r} is not a Python builtin " 2324*cda5da8dSAndroid Build Coastguard Worker "function".format(func)) 2325*cda5da8dSAndroid Build Coastguard Worker 2326*cda5da8dSAndroid Build Coastguard Worker s = getattr(func, "__text_signature__", None) 2327*cda5da8dSAndroid Build Coastguard Worker if not s: 2328*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no signature found for builtin {!r}".format(func)) 2329*cda5da8dSAndroid Build Coastguard Worker 2330*cda5da8dSAndroid Build Coastguard Worker return _signature_fromstr(cls, func, s, skip_bound_arg) 2331*cda5da8dSAndroid Build Coastguard Worker 2332*cda5da8dSAndroid Build Coastguard Worker 2333*cda5da8dSAndroid Build Coastguard Workerdef _signature_from_function(cls, func, skip_bound_arg=True, 2334*cda5da8dSAndroid Build Coastguard Worker globals=None, locals=None, eval_str=False): 2335*cda5da8dSAndroid Build Coastguard Worker """Private helper: constructs Signature for the given python function.""" 2336*cda5da8dSAndroid Build Coastguard Worker 2337*cda5da8dSAndroid Build Coastguard Worker is_duck_function = False 2338*cda5da8dSAndroid Build Coastguard Worker if not isfunction(func): 2339*cda5da8dSAndroid Build Coastguard Worker if _signature_is_functionlike(func): 2340*cda5da8dSAndroid Build Coastguard Worker is_duck_function = True 2341*cda5da8dSAndroid Build Coastguard Worker else: 2342*cda5da8dSAndroid Build Coastguard Worker # If it's not a pure Python function, and not a duck type 2343*cda5da8dSAndroid Build Coastguard Worker # of pure function: 2344*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is not a Python function'.format(func)) 2345*cda5da8dSAndroid Build Coastguard Worker 2346*cda5da8dSAndroid Build Coastguard Worker s = getattr(func, "__text_signature__", None) 2347*cda5da8dSAndroid Build Coastguard Worker if s: 2348*cda5da8dSAndroid Build Coastguard Worker return _signature_fromstr(cls, func, s, skip_bound_arg) 2349*cda5da8dSAndroid Build Coastguard Worker 2350*cda5da8dSAndroid Build Coastguard Worker Parameter = cls._parameter_cls 2351*cda5da8dSAndroid Build Coastguard Worker 2352*cda5da8dSAndroid Build Coastguard Worker # Parameter information. 2353*cda5da8dSAndroid Build Coastguard Worker func_code = func.__code__ 2354*cda5da8dSAndroid Build Coastguard Worker pos_count = func_code.co_argcount 2355*cda5da8dSAndroid Build Coastguard Worker arg_names = func_code.co_varnames 2356*cda5da8dSAndroid Build Coastguard Worker posonly_count = func_code.co_posonlyargcount 2357*cda5da8dSAndroid Build Coastguard Worker positional = arg_names[:pos_count] 2358*cda5da8dSAndroid Build Coastguard Worker keyword_only_count = func_code.co_kwonlyargcount 2359*cda5da8dSAndroid Build Coastguard Worker keyword_only = arg_names[pos_count:pos_count + keyword_only_count] 2360*cda5da8dSAndroid Build Coastguard Worker annotations = get_annotations(func, globals=globals, locals=locals, eval_str=eval_str) 2361*cda5da8dSAndroid Build Coastguard Worker defaults = func.__defaults__ 2362*cda5da8dSAndroid Build Coastguard Worker kwdefaults = func.__kwdefaults__ 2363*cda5da8dSAndroid Build Coastguard Worker 2364*cda5da8dSAndroid Build Coastguard Worker if defaults: 2365*cda5da8dSAndroid Build Coastguard Worker pos_default_count = len(defaults) 2366*cda5da8dSAndroid Build Coastguard Worker else: 2367*cda5da8dSAndroid Build Coastguard Worker pos_default_count = 0 2368*cda5da8dSAndroid Build Coastguard Worker 2369*cda5da8dSAndroid Build Coastguard Worker parameters = [] 2370*cda5da8dSAndroid Build Coastguard Worker 2371*cda5da8dSAndroid Build Coastguard Worker non_default_count = pos_count - pos_default_count 2372*cda5da8dSAndroid Build Coastguard Worker posonly_left = posonly_count 2373*cda5da8dSAndroid Build Coastguard Worker 2374*cda5da8dSAndroid Build Coastguard Worker # Non-keyword-only parameters w/o defaults. 2375*cda5da8dSAndroid Build Coastguard Worker for name in positional[:non_default_count]: 2376*cda5da8dSAndroid Build Coastguard Worker kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD 2377*cda5da8dSAndroid Build Coastguard Worker annotation = annotations.get(name, _empty) 2378*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, annotation=annotation, 2379*cda5da8dSAndroid Build Coastguard Worker kind=kind)) 2380*cda5da8dSAndroid Build Coastguard Worker if posonly_left: 2381*cda5da8dSAndroid Build Coastguard Worker posonly_left -= 1 2382*cda5da8dSAndroid Build Coastguard Worker 2383*cda5da8dSAndroid Build Coastguard Worker # ... w/ defaults. 2384*cda5da8dSAndroid Build Coastguard Worker for offset, name in enumerate(positional[non_default_count:]): 2385*cda5da8dSAndroid Build Coastguard Worker kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD 2386*cda5da8dSAndroid Build Coastguard Worker annotation = annotations.get(name, _empty) 2387*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, annotation=annotation, 2388*cda5da8dSAndroid Build Coastguard Worker kind=kind, 2389*cda5da8dSAndroid Build Coastguard Worker default=defaults[offset])) 2390*cda5da8dSAndroid Build Coastguard Worker if posonly_left: 2391*cda5da8dSAndroid Build Coastguard Worker posonly_left -= 1 2392*cda5da8dSAndroid Build Coastguard Worker 2393*cda5da8dSAndroid Build Coastguard Worker # *args 2394*cda5da8dSAndroid Build Coastguard Worker if func_code.co_flags & CO_VARARGS: 2395*cda5da8dSAndroid Build Coastguard Worker name = arg_names[pos_count + keyword_only_count] 2396*cda5da8dSAndroid Build Coastguard Worker annotation = annotations.get(name, _empty) 2397*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, annotation=annotation, 2398*cda5da8dSAndroid Build Coastguard Worker kind=_VAR_POSITIONAL)) 2399*cda5da8dSAndroid Build Coastguard Worker 2400*cda5da8dSAndroid Build Coastguard Worker # Keyword-only parameters. 2401*cda5da8dSAndroid Build Coastguard Worker for name in keyword_only: 2402*cda5da8dSAndroid Build Coastguard Worker default = _empty 2403*cda5da8dSAndroid Build Coastguard Worker if kwdefaults is not None: 2404*cda5da8dSAndroid Build Coastguard Worker default = kwdefaults.get(name, _empty) 2405*cda5da8dSAndroid Build Coastguard Worker 2406*cda5da8dSAndroid Build Coastguard Worker annotation = annotations.get(name, _empty) 2407*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, annotation=annotation, 2408*cda5da8dSAndroid Build Coastguard Worker kind=_KEYWORD_ONLY, 2409*cda5da8dSAndroid Build Coastguard Worker default=default)) 2410*cda5da8dSAndroid Build Coastguard Worker # **kwargs 2411*cda5da8dSAndroid Build Coastguard Worker if func_code.co_flags & CO_VARKEYWORDS: 2412*cda5da8dSAndroid Build Coastguard Worker index = pos_count + keyword_only_count 2413*cda5da8dSAndroid Build Coastguard Worker if func_code.co_flags & CO_VARARGS: 2414*cda5da8dSAndroid Build Coastguard Worker index += 1 2415*cda5da8dSAndroid Build Coastguard Worker 2416*cda5da8dSAndroid Build Coastguard Worker name = arg_names[index] 2417*cda5da8dSAndroid Build Coastguard Worker annotation = annotations.get(name, _empty) 2418*cda5da8dSAndroid Build Coastguard Worker parameters.append(Parameter(name, annotation=annotation, 2419*cda5da8dSAndroid Build Coastguard Worker kind=_VAR_KEYWORD)) 2420*cda5da8dSAndroid Build Coastguard Worker 2421*cda5da8dSAndroid Build Coastguard Worker # Is 'func' is a pure Python function - don't validate the 2422*cda5da8dSAndroid Build Coastguard Worker # parameters list (for correct order and defaults), it should be OK. 2423*cda5da8dSAndroid Build Coastguard Worker return cls(parameters, 2424*cda5da8dSAndroid Build Coastguard Worker return_annotation=annotations.get('return', _empty), 2425*cda5da8dSAndroid Build Coastguard Worker __validate_parameters__=is_duck_function) 2426*cda5da8dSAndroid Build Coastguard Worker 2427*cda5da8dSAndroid Build Coastguard Worker 2428*cda5da8dSAndroid Build Coastguard Workerdef _signature_from_callable(obj, *, 2429*cda5da8dSAndroid Build Coastguard Worker follow_wrapper_chains=True, 2430*cda5da8dSAndroid Build Coastguard Worker skip_bound_arg=True, 2431*cda5da8dSAndroid Build Coastguard Worker globals=None, 2432*cda5da8dSAndroid Build Coastguard Worker locals=None, 2433*cda5da8dSAndroid Build Coastguard Worker eval_str=False, 2434*cda5da8dSAndroid Build Coastguard Worker sigcls): 2435*cda5da8dSAndroid Build Coastguard Worker 2436*cda5da8dSAndroid Build Coastguard Worker """Private helper function to get signature for arbitrary 2437*cda5da8dSAndroid Build Coastguard Worker callable objects. 2438*cda5da8dSAndroid Build Coastguard Worker """ 2439*cda5da8dSAndroid Build Coastguard Worker 2440*cda5da8dSAndroid Build Coastguard Worker _get_signature_of = functools.partial(_signature_from_callable, 2441*cda5da8dSAndroid Build Coastguard Worker follow_wrapper_chains=follow_wrapper_chains, 2442*cda5da8dSAndroid Build Coastguard Worker skip_bound_arg=skip_bound_arg, 2443*cda5da8dSAndroid Build Coastguard Worker globals=globals, 2444*cda5da8dSAndroid Build Coastguard Worker locals=locals, 2445*cda5da8dSAndroid Build Coastguard Worker sigcls=sigcls, 2446*cda5da8dSAndroid Build Coastguard Worker eval_str=eval_str) 2447*cda5da8dSAndroid Build Coastguard Worker 2448*cda5da8dSAndroid Build Coastguard Worker if not callable(obj): 2449*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{!r} is not a callable object'.format(obj)) 2450*cda5da8dSAndroid Build Coastguard Worker 2451*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, types.MethodType): 2452*cda5da8dSAndroid Build Coastguard Worker # In this case we skip the first parameter of the underlying 2453*cda5da8dSAndroid Build Coastguard Worker # function (usually `self` or `cls`). 2454*cda5da8dSAndroid Build Coastguard Worker sig = _get_signature_of(obj.__func__) 2455*cda5da8dSAndroid Build Coastguard Worker 2456*cda5da8dSAndroid Build Coastguard Worker if skip_bound_arg: 2457*cda5da8dSAndroid Build Coastguard Worker return _signature_bound_method(sig) 2458*cda5da8dSAndroid Build Coastguard Worker else: 2459*cda5da8dSAndroid Build Coastguard Worker return sig 2460*cda5da8dSAndroid Build Coastguard Worker 2461*cda5da8dSAndroid Build Coastguard Worker # Was this function wrapped by a decorator? 2462*cda5da8dSAndroid Build Coastguard Worker if follow_wrapper_chains: 2463*cda5da8dSAndroid Build Coastguard Worker # Unwrap until we find an explicit signature or a MethodType (which will be 2464*cda5da8dSAndroid Build Coastguard Worker # handled explicitly below). 2465*cda5da8dSAndroid Build Coastguard Worker obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__") 2466*cda5da8dSAndroid Build Coastguard Worker or isinstance(f, types.MethodType))) 2467*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, types.MethodType): 2468*cda5da8dSAndroid Build Coastguard Worker # If the unwrapped object is a *method*, we might want to 2469*cda5da8dSAndroid Build Coastguard Worker # skip its first parameter (self). 2470*cda5da8dSAndroid Build Coastguard Worker # See test_signature_wrapped_bound_method for details. 2471*cda5da8dSAndroid Build Coastguard Worker return _get_signature_of(obj) 2472*cda5da8dSAndroid Build Coastguard Worker 2473*cda5da8dSAndroid Build Coastguard Worker try: 2474*cda5da8dSAndroid Build Coastguard Worker sig = obj.__signature__ 2475*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2476*cda5da8dSAndroid Build Coastguard Worker pass 2477*cda5da8dSAndroid Build Coastguard Worker else: 2478*cda5da8dSAndroid Build Coastguard Worker if sig is not None: 2479*cda5da8dSAndroid Build Coastguard Worker if not isinstance(sig, Signature): 2480*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 2481*cda5da8dSAndroid Build Coastguard Worker 'unexpected object {!r} in __signature__ ' 2482*cda5da8dSAndroid Build Coastguard Worker 'attribute'.format(sig)) 2483*cda5da8dSAndroid Build Coastguard Worker return sig 2484*cda5da8dSAndroid Build Coastguard Worker 2485*cda5da8dSAndroid Build Coastguard Worker try: 2486*cda5da8dSAndroid Build Coastguard Worker partialmethod = obj._partialmethod 2487*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2488*cda5da8dSAndroid Build Coastguard Worker pass 2489*cda5da8dSAndroid Build Coastguard Worker else: 2490*cda5da8dSAndroid Build Coastguard Worker if isinstance(partialmethod, functools.partialmethod): 2491*cda5da8dSAndroid Build Coastguard Worker # Unbound partialmethod (see functools.partialmethod) 2492*cda5da8dSAndroid Build Coastguard Worker # This means, that we need to calculate the signature 2493*cda5da8dSAndroid Build Coastguard Worker # as if it's a regular partial object, but taking into 2494*cda5da8dSAndroid Build Coastguard Worker # account that the first positional argument 2495*cda5da8dSAndroid Build Coastguard Worker # (usually `self`, or `cls`) will not be passed 2496*cda5da8dSAndroid Build Coastguard Worker # automatically (as for boundmethods) 2497*cda5da8dSAndroid Build Coastguard Worker 2498*cda5da8dSAndroid Build Coastguard Worker wrapped_sig = _get_signature_of(partialmethod.func) 2499*cda5da8dSAndroid Build Coastguard Worker 2500*cda5da8dSAndroid Build Coastguard Worker sig = _signature_get_partial(wrapped_sig, partialmethod, (None,)) 2501*cda5da8dSAndroid Build Coastguard Worker first_wrapped_param = tuple(wrapped_sig.parameters.values())[0] 2502*cda5da8dSAndroid Build Coastguard Worker if first_wrapped_param.kind is Parameter.VAR_POSITIONAL: 2503*cda5da8dSAndroid Build Coastguard Worker # First argument of the wrapped callable is `*args`, as in 2504*cda5da8dSAndroid Build Coastguard Worker # `partialmethod(lambda *args)`. 2505*cda5da8dSAndroid Build Coastguard Worker return sig 2506*cda5da8dSAndroid Build Coastguard Worker else: 2507*cda5da8dSAndroid Build Coastguard Worker sig_params = tuple(sig.parameters.values()) 2508*cda5da8dSAndroid Build Coastguard Worker assert (not sig_params or 2509*cda5da8dSAndroid Build Coastguard Worker first_wrapped_param is not sig_params[0]) 2510*cda5da8dSAndroid Build Coastguard Worker new_params = (first_wrapped_param,) + sig_params 2511*cda5da8dSAndroid Build Coastguard Worker return sig.replace(parameters=new_params) 2512*cda5da8dSAndroid Build Coastguard Worker 2513*cda5da8dSAndroid Build Coastguard Worker if isfunction(obj) or _signature_is_functionlike(obj): 2514*cda5da8dSAndroid Build Coastguard Worker # If it's a pure Python function, or an object that is duck type 2515*cda5da8dSAndroid Build Coastguard Worker # of a Python function (Cython functions, for instance), then: 2516*cda5da8dSAndroid Build Coastguard Worker return _signature_from_function(sigcls, obj, 2517*cda5da8dSAndroid Build Coastguard Worker skip_bound_arg=skip_bound_arg, 2518*cda5da8dSAndroid Build Coastguard Worker globals=globals, locals=locals, eval_str=eval_str) 2519*cda5da8dSAndroid Build Coastguard Worker 2520*cda5da8dSAndroid Build Coastguard Worker if _signature_is_builtin(obj): 2521*cda5da8dSAndroid Build Coastguard Worker return _signature_from_builtin(sigcls, obj, 2522*cda5da8dSAndroid Build Coastguard Worker skip_bound_arg=skip_bound_arg) 2523*cda5da8dSAndroid Build Coastguard Worker 2524*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, functools.partial): 2525*cda5da8dSAndroid Build Coastguard Worker wrapped_sig = _get_signature_of(obj.func) 2526*cda5da8dSAndroid Build Coastguard Worker return _signature_get_partial(wrapped_sig, obj) 2527*cda5da8dSAndroid Build Coastguard Worker 2528*cda5da8dSAndroid Build Coastguard Worker sig = None 2529*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, type): 2530*cda5da8dSAndroid Build Coastguard Worker # obj is a class or a metaclass 2531*cda5da8dSAndroid Build Coastguard Worker 2532*cda5da8dSAndroid Build Coastguard Worker # First, let's see if it has an overloaded __call__ defined 2533*cda5da8dSAndroid Build Coastguard Worker # in its metaclass 2534*cda5da8dSAndroid Build Coastguard Worker call = _signature_get_user_defined_method(type(obj), '__call__') 2535*cda5da8dSAndroid Build Coastguard Worker if call is not None: 2536*cda5da8dSAndroid Build Coastguard Worker sig = _get_signature_of(call) 2537*cda5da8dSAndroid Build Coastguard Worker else: 2538*cda5da8dSAndroid Build Coastguard Worker factory_method = None 2539*cda5da8dSAndroid Build Coastguard Worker new = _signature_get_user_defined_method(obj, '__new__') 2540*cda5da8dSAndroid Build Coastguard Worker init = _signature_get_user_defined_method(obj, '__init__') 2541*cda5da8dSAndroid Build Coastguard Worker 2542*cda5da8dSAndroid Build Coastguard Worker # Go through the MRO and see if any class has user-defined 2543*cda5da8dSAndroid Build Coastguard Worker # pure Python __new__ or __init__ method 2544*cda5da8dSAndroid Build Coastguard Worker for base in obj.__mro__: 2545*cda5da8dSAndroid Build Coastguard Worker # Now we check if the 'obj' class has an own '__new__' method 2546*cda5da8dSAndroid Build Coastguard Worker if new is not None and '__new__' in base.__dict__: 2547*cda5da8dSAndroid Build Coastguard Worker factory_method = new 2548*cda5da8dSAndroid Build Coastguard Worker break 2549*cda5da8dSAndroid Build Coastguard Worker # or an own '__init__' method 2550*cda5da8dSAndroid Build Coastguard Worker elif init is not None and '__init__' in base.__dict__: 2551*cda5da8dSAndroid Build Coastguard Worker factory_method = init 2552*cda5da8dSAndroid Build Coastguard Worker break 2553*cda5da8dSAndroid Build Coastguard Worker 2554*cda5da8dSAndroid Build Coastguard Worker if factory_method is not None: 2555*cda5da8dSAndroid Build Coastguard Worker sig = _get_signature_of(factory_method) 2556*cda5da8dSAndroid Build Coastguard Worker 2557*cda5da8dSAndroid Build Coastguard Worker if sig is None: 2558*cda5da8dSAndroid Build Coastguard Worker # At this point we know, that `obj` is a class, with no user- 2559*cda5da8dSAndroid Build Coastguard Worker # defined '__init__', '__new__', or class-level '__call__' 2560*cda5da8dSAndroid Build Coastguard Worker 2561*cda5da8dSAndroid Build Coastguard Worker for base in obj.__mro__[:-1]: 2562*cda5da8dSAndroid Build Coastguard Worker # Since '__text_signature__' is implemented as a 2563*cda5da8dSAndroid Build Coastguard Worker # descriptor that extracts text signature from the 2564*cda5da8dSAndroid Build Coastguard Worker # class docstring, if 'obj' is derived from a builtin 2565*cda5da8dSAndroid Build Coastguard Worker # class, its own '__text_signature__' may be 'None'. 2566*cda5da8dSAndroid Build Coastguard Worker # Therefore, we go through the MRO (except the last 2567*cda5da8dSAndroid Build Coastguard Worker # class in there, which is 'object') to find the first 2568*cda5da8dSAndroid Build Coastguard Worker # class with non-empty text signature. 2569*cda5da8dSAndroid Build Coastguard Worker try: 2570*cda5da8dSAndroid Build Coastguard Worker text_sig = base.__text_signature__ 2571*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2572*cda5da8dSAndroid Build Coastguard Worker pass 2573*cda5da8dSAndroid Build Coastguard Worker else: 2574*cda5da8dSAndroid Build Coastguard Worker if text_sig: 2575*cda5da8dSAndroid Build Coastguard Worker # If 'base' class has a __text_signature__ attribute: 2576*cda5da8dSAndroid Build Coastguard Worker # return a signature based on it 2577*cda5da8dSAndroid Build Coastguard Worker return _signature_fromstr(sigcls, base, text_sig) 2578*cda5da8dSAndroid Build Coastguard Worker 2579*cda5da8dSAndroid Build Coastguard Worker # No '__text_signature__' was found for the 'obj' class. 2580*cda5da8dSAndroid Build Coastguard Worker # Last option is to check if its '__init__' is 2581*cda5da8dSAndroid Build Coastguard Worker # object.__init__ or type.__init__. 2582*cda5da8dSAndroid Build Coastguard Worker if type not in obj.__mro__: 2583*cda5da8dSAndroid Build Coastguard Worker # We have a class (not metaclass), but no user-defined 2584*cda5da8dSAndroid Build Coastguard Worker # __init__ or __new__ for it 2585*cda5da8dSAndroid Build Coastguard Worker if (obj.__init__ is object.__init__ and 2586*cda5da8dSAndroid Build Coastguard Worker obj.__new__ is object.__new__): 2587*cda5da8dSAndroid Build Coastguard Worker # Return a signature of 'object' builtin. 2588*cda5da8dSAndroid Build Coastguard Worker return sigcls.from_callable(object) 2589*cda5da8dSAndroid Build Coastguard Worker else: 2590*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 2591*cda5da8dSAndroid Build Coastguard Worker 'no signature found for builtin type {!r}'.format(obj)) 2592*cda5da8dSAndroid Build Coastguard Worker 2593*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(obj, _NonUserDefinedCallables): 2594*cda5da8dSAndroid Build Coastguard Worker # An object with __call__ 2595*cda5da8dSAndroid Build Coastguard Worker # We also check that the 'obj' is not an instance of 2596*cda5da8dSAndroid Build Coastguard Worker # types.WrapperDescriptorType or types.MethodWrapperType to avoid 2597*cda5da8dSAndroid Build Coastguard Worker # infinite recursion (and even potential segfault) 2598*cda5da8dSAndroid Build Coastguard Worker call = _signature_get_user_defined_method(type(obj), '__call__') 2599*cda5da8dSAndroid Build Coastguard Worker if call is not None: 2600*cda5da8dSAndroid Build Coastguard Worker try: 2601*cda5da8dSAndroid Build Coastguard Worker sig = _get_signature_of(call) 2602*cda5da8dSAndroid Build Coastguard Worker except ValueError as ex: 2603*cda5da8dSAndroid Build Coastguard Worker msg = 'no signature found for {!r}'.format(obj) 2604*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) from ex 2605*cda5da8dSAndroid Build Coastguard Worker 2606*cda5da8dSAndroid Build Coastguard Worker if sig is not None: 2607*cda5da8dSAndroid Build Coastguard Worker # For classes and objects we skip the first parameter of their 2608*cda5da8dSAndroid Build Coastguard Worker # __call__, __new__, or __init__ methods 2609*cda5da8dSAndroid Build Coastguard Worker if skip_bound_arg: 2610*cda5da8dSAndroid Build Coastguard Worker return _signature_bound_method(sig) 2611*cda5da8dSAndroid Build Coastguard Worker else: 2612*cda5da8dSAndroid Build Coastguard Worker return sig 2613*cda5da8dSAndroid Build Coastguard Worker 2614*cda5da8dSAndroid Build Coastguard Worker if isinstance(obj, types.BuiltinFunctionType): 2615*cda5da8dSAndroid Build Coastguard Worker # Raise a nicer error message for builtins 2616*cda5da8dSAndroid Build Coastguard Worker msg = 'no signature found for builtin function {!r}'.format(obj) 2617*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 2618*cda5da8dSAndroid Build Coastguard Worker 2619*cda5da8dSAndroid Build Coastguard Worker raise ValueError('callable {!r} is not supported by signature'.format(obj)) 2620*cda5da8dSAndroid Build Coastguard Worker 2621*cda5da8dSAndroid Build Coastguard Worker 2622*cda5da8dSAndroid Build Coastguard Workerclass _void: 2623*cda5da8dSAndroid Build Coastguard Worker """A private marker - used in Parameter & Signature.""" 2624*cda5da8dSAndroid Build Coastguard Worker 2625*cda5da8dSAndroid Build Coastguard Worker 2626*cda5da8dSAndroid Build Coastguard Workerclass _empty: 2627*cda5da8dSAndroid Build Coastguard Worker """Marker object for Signature.empty and Parameter.empty.""" 2628*cda5da8dSAndroid Build Coastguard Worker 2629*cda5da8dSAndroid Build Coastguard Worker 2630*cda5da8dSAndroid Build Coastguard Workerclass _ParameterKind(enum.IntEnum): 2631*cda5da8dSAndroid Build Coastguard Worker POSITIONAL_ONLY = 'positional-only' 2632*cda5da8dSAndroid Build Coastguard Worker POSITIONAL_OR_KEYWORD = 'positional or keyword' 2633*cda5da8dSAndroid Build Coastguard Worker VAR_POSITIONAL = 'variadic positional' 2634*cda5da8dSAndroid Build Coastguard Worker KEYWORD_ONLY = 'keyword-only' 2635*cda5da8dSAndroid Build Coastguard Worker VAR_KEYWORD = 'variadic keyword' 2636*cda5da8dSAndroid Build Coastguard Worker 2637*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, description): 2638*cda5da8dSAndroid Build Coastguard Worker value = len(cls.__members__) 2639*cda5da8dSAndroid Build Coastguard Worker member = int.__new__(cls, value) 2640*cda5da8dSAndroid Build Coastguard Worker member._value_ = value 2641*cda5da8dSAndroid Build Coastguard Worker member.description = description 2642*cda5da8dSAndroid Build Coastguard Worker return member 2643*cda5da8dSAndroid Build Coastguard Worker 2644*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 2645*cda5da8dSAndroid Build Coastguard Worker return self.name 2646*cda5da8dSAndroid Build Coastguard Worker 2647*cda5da8dSAndroid Build Coastguard Worker_POSITIONAL_ONLY = _ParameterKind.POSITIONAL_ONLY 2648*cda5da8dSAndroid Build Coastguard Worker_POSITIONAL_OR_KEYWORD = _ParameterKind.POSITIONAL_OR_KEYWORD 2649*cda5da8dSAndroid Build Coastguard Worker_VAR_POSITIONAL = _ParameterKind.VAR_POSITIONAL 2650*cda5da8dSAndroid Build Coastguard Worker_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY 2651*cda5da8dSAndroid Build Coastguard Worker_VAR_KEYWORD = _ParameterKind.VAR_KEYWORD 2652*cda5da8dSAndroid Build Coastguard Worker 2653*cda5da8dSAndroid Build Coastguard Worker 2654*cda5da8dSAndroid Build Coastguard Workerclass Parameter: 2655*cda5da8dSAndroid Build Coastguard Worker """Represents a parameter in a function signature. 2656*cda5da8dSAndroid Build Coastguard Worker 2657*cda5da8dSAndroid Build Coastguard Worker Has the following public attributes: 2658*cda5da8dSAndroid Build Coastguard Worker 2659*cda5da8dSAndroid Build Coastguard Worker * name : str 2660*cda5da8dSAndroid Build Coastguard Worker The name of the parameter as a string. 2661*cda5da8dSAndroid Build Coastguard Worker * default : object 2662*cda5da8dSAndroid Build Coastguard Worker The default value for the parameter if specified. If the 2663*cda5da8dSAndroid Build Coastguard Worker parameter has no default value, this attribute is set to 2664*cda5da8dSAndroid Build Coastguard Worker `Parameter.empty`. 2665*cda5da8dSAndroid Build Coastguard Worker * annotation 2666*cda5da8dSAndroid Build Coastguard Worker The annotation for the parameter if specified. If the 2667*cda5da8dSAndroid Build Coastguard Worker parameter has no annotation, this attribute is set to 2668*cda5da8dSAndroid Build Coastguard Worker `Parameter.empty`. 2669*cda5da8dSAndroid Build Coastguard Worker * kind : str 2670*cda5da8dSAndroid Build Coastguard Worker Describes how argument values are bound to the parameter. 2671*cda5da8dSAndroid Build Coastguard Worker Possible values: `Parameter.POSITIONAL_ONLY`, 2672*cda5da8dSAndroid Build Coastguard Worker `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`, 2673*cda5da8dSAndroid Build Coastguard Worker `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`. 2674*cda5da8dSAndroid Build Coastguard Worker """ 2675*cda5da8dSAndroid Build Coastguard Worker 2676*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('_name', '_kind', '_default', '_annotation') 2677*cda5da8dSAndroid Build Coastguard Worker 2678*cda5da8dSAndroid Build Coastguard Worker POSITIONAL_ONLY = _POSITIONAL_ONLY 2679*cda5da8dSAndroid Build Coastguard Worker POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD 2680*cda5da8dSAndroid Build Coastguard Worker VAR_POSITIONAL = _VAR_POSITIONAL 2681*cda5da8dSAndroid Build Coastguard Worker KEYWORD_ONLY = _KEYWORD_ONLY 2682*cda5da8dSAndroid Build Coastguard Worker VAR_KEYWORD = _VAR_KEYWORD 2683*cda5da8dSAndroid Build Coastguard Worker 2684*cda5da8dSAndroid Build Coastguard Worker empty = _empty 2685*cda5da8dSAndroid Build Coastguard Worker 2686*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, kind, *, default=_empty, annotation=_empty): 2687*cda5da8dSAndroid Build Coastguard Worker try: 2688*cda5da8dSAndroid Build Coastguard Worker self._kind = _ParameterKind(kind) 2689*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2690*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'value {kind!r} is not a valid Parameter.kind') 2691*cda5da8dSAndroid Build Coastguard Worker if default is not _empty: 2692*cda5da8dSAndroid Build Coastguard Worker if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): 2693*cda5da8dSAndroid Build Coastguard Worker msg = '{} parameters cannot have default values' 2694*cda5da8dSAndroid Build Coastguard Worker msg = msg.format(self._kind.description) 2695*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 2696*cda5da8dSAndroid Build Coastguard Worker self._default = default 2697*cda5da8dSAndroid Build Coastguard Worker self._annotation = annotation 2698*cda5da8dSAndroid Build Coastguard Worker 2699*cda5da8dSAndroid Build Coastguard Worker if name is _empty: 2700*cda5da8dSAndroid Build Coastguard Worker raise ValueError('name is a required attribute for Parameter') 2701*cda5da8dSAndroid Build Coastguard Worker 2702*cda5da8dSAndroid Build Coastguard Worker if not isinstance(name, str): 2703*cda5da8dSAndroid Build Coastguard Worker msg = 'name must be a str, not a {}'.format(type(name).__name__) 2704*cda5da8dSAndroid Build Coastguard Worker raise TypeError(msg) 2705*cda5da8dSAndroid Build Coastguard Worker 2706*cda5da8dSAndroid Build Coastguard Worker if name[0] == '.' and name[1:].isdigit(): 2707*cda5da8dSAndroid Build Coastguard Worker # These are implicit arguments generated by comprehensions. In 2708*cda5da8dSAndroid Build Coastguard Worker # order to provide a friendlier interface to users, we recast 2709*cda5da8dSAndroid Build Coastguard Worker # their name as "implicitN" and treat them as positional-only. 2710*cda5da8dSAndroid Build Coastguard Worker # See issue 19611. 2711*cda5da8dSAndroid Build Coastguard Worker if self._kind != _POSITIONAL_OR_KEYWORD: 2712*cda5da8dSAndroid Build Coastguard Worker msg = ( 2713*cda5da8dSAndroid Build Coastguard Worker 'implicit arguments must be passed as ' 2714*cda5da8dSAndroid Build Coastguard Worker 'positional or keyword arguments, not {}' 2715*cda5da8dSAndroid Build Coastguard Worker ) 2716*cda5da8dSAndroid Build Coastguard Worker msg = msg.format(self._kind.description) 2717*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 2718*cda5da8dSAndroid Build Coastguard Worker self._kind = _POSITIONAL_ONLY 2719*cda5da8dSAndroid Build Coastguard Worker name = 'implicit{}'.format(name[1:]) 2720*cda5da8dSAndroid Build Coastguard Worker 2721*cda5da8dSAndroid Build Coastguard Worker # It's possible for C functions to have a positional-only parameter 2722*cda5da8dSAndroid Build Coastguard Worker # where the name is a keyword, so for compatibility we'll allow it. 2723*cda5da8dSAndroid Build Coastguard Worker is_keyword = iskeyword(name) and self._kind is not _POSITIONAL_ONLY 2724*cda5da8dSAndroid Build Coastguard Worker if is_keyword or not name.isidentifier(): 2725*cda5da8dSAndroid Build Coastguard Worker raise ValueError('{!r} is not a valid parameter name'.format(name)) 2726*cda5da8dSAndroid Build Coastguard Worker 2727*cda5da8dSAndroid Build Coastguard Worker self._name = name 2728*cda5da8dSAndroid Build Coastguard Worker 2729*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 2730*cda5da8dSAndroid Build Coastguard Worker return (type(self), 2731*cda5da8dSAndroid Build Coastguard Worker (self._name, self._kind), 2732*cda5da8dSAndroid Build Coastguard Worker {'_default': self._default, 2733*cda5da8dSAndroid Build Coastguard Worker '_annotation': self._annotation}) 2734*cda5da8dSAndroid Build Coastguard Worker 2735*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 2736*cda5da8dSAndroid Build Coastguard Worker self._default = state['_default'] 2737*cda5da8dSAndroid Build Coastguard Worker self._annotation = state['_annotation'] 2738*cda5da8dSAndroid Build Coastguard Worker 2739*cda5da8dSAndroid Build Coastguard Worker @property 2740*cda5da8dSAndroid Build Coastguard Worker def name(self): 2741*cda5da8dSAndroid Build Coastguard Worker return self._name 2742*cda5da8dSAndroid Build Coastguard Worker 2743*cda5da8dSAndroid Build Coastguard Worker @property 2744*cda5da8dSAndroid Build Coastguard Worker def default(self): 2745*cda5da8dSAndroid Build Coastguard Worker return self._default 2746*cda5da8dSAndroid Build Coastguard Worker 2747*cda5da8dSAndroid Build Coastguard Worker @property 2748*cda5da8dSAndroid Build Coastguard Worker def annotation(self): 2749*cda5da8dSAndroid Build Coastguard Worker return self._annotation 2750*cda5da8dSAndroid Build Coastguard Worker 2751*cda5da8dSAndroid Build Coastguard Worker @property 2752*cda5da8dSAndroid Build Coastguard Worker def kind(self): 2753*cda5da8dSAndroid Build Coastguard Worker return self._kind 2754*cda5da8dSAndroid Build Coastguard Worker 2755*cda5da8dSAndroid Build Coastguard Worker def replace(self, *, name=_void, kind=_void, 2756*cda5da8dSAndroid Build Coastguard Worker annotation=_void, default=_void): 2757*cda5da8dSAndroid Build Coastguard Worker """Creates a customized copy of the Parameter.""" 2758*cda5da8dSAndroid Build Coastguard Worker 2759*cda5da8dSAndroid Build Coastguard Worker if name is _void: 2760*cda5da8dSAndroid Build Coastguard Worker name = self._name 2761*cda5da8dSAndroid Build Coastguard Worker 2762*cda5da8dSAndroid Build Coastguard Worker if kind is _void: 2763*cda5da8dSAndroid Build Coastguard Worker kind = self._kind 2764*cda5da8dSAndroid Build Coastguard Worker 2765*cda5da8dSAndroid Build Coastguard Worker if annotation is _void: 2766*cda5da8dSAndroid Build Coastguard Worker annotation = self._annotation 2767*cda5da8dSAndroid Build Coastguard Worker 2768*cda5da8dSAndroid Build Coastguard Worker if default is _void: 2769*cda5da8dSAndroid Build Coastguard Worker default = self._default 2770*cda5da8dSAndroid Build Coastguard Worker 2771*cda5da8dSAndroid Build Coastguard Worker return type(self)(name, kind, default=default, annotation=annotation) 2772*cda5da8dSAndroid Build Coastguard Worker 2773*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 2774*cda5da8dSAndroid Build Coastguard Worker kind = self.kind 2775*cda5da8dSAndroid Build Coastguard Worker formatted = self._name 2776*cda5da8dSAndroid Build Coastguard Worker 2777*cda5da8dSAndroid Build Coastguard Worker # Add annotation and default value 2778*cda5da8dSAndroid Build Coastguard Worker if self._annotation is not _empty: 2779*cda5da8dSAndroid Build Coastguard Worker formatted = '{}: {}'.format(formatted, 2780*cda5da8dSAndroid Build Coastguard Worker formatannotation(self._annotation)) 2781*cda5da8dSAndroid Build Coastguard Worker 2782*cda5da8dSAndroid Build Coastguard Worker if self._default is not _empty: 2783*cda5da8dSAndroid Build Coastguard Worker if self._annotation is not _empty: 2784*cda5da8dSAndroid Build Coastguard Worker formatted = '{} = {}'.format(formatted, repr(self._default)) 2785*cda5da8dSAndroid Build Coastguard Worker else: 2786*cda5da8dSAndroid Build Coastguard Worker formatted = '{}={}'.format(formatted, repr(self._default)) 2787*cda5da8dSAndroid Build Coastguard Worker 2788*cda5da8dSAndroid Build Coastguard Worker if kind == _VAR_POSITIONAL: 2789*cda5da8dSAndroid Build Coastguard Worker formatted = '*' + formatted 2790*cda5da8dSAndroid Build Coastguard Worker elif kind == _VAR_KEYWORD: 2791*cda5da8dSAndroid Build Coastguard Worker formatted = '**' + formatted 2792*cda5da8dSAndroid Build Coastguard Worker 2793*cda5da8dSAndroid Build Coastguard Worker return formatted 2794*cda5da8dSAndroid Build Coastguard Worker 2795*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2796*cda5da8dSAndroid Build Coastguard Worker return '<{} "{}">'.format(self.__class__.__name__, self) 2797*cda5da8dSAndroid Build Coastguard Worker 2798*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 2799*cda5da8dSAndroid Build Coastguard Worker return hash((self.name, self.kind, self.annotation, self.default)) 2800*cda5da8dSAndroid Build Coastguard Worker 2801*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 2802*cda5da8dSAndroid Build Coastguard Worker if self is other: 2803*cda5da8dSAndroid Build Coastguard Worker return True 2804*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, Parameter): 2805*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2806*cda5da8dSAndroid Build Coastguard Worker return (self._name == other._name and 2807*cda5da8dSAndroid Build Coastguard Worker self._kind == other._kind and 2808*cda5da8dSAndroid Build Coastguard Worker self._default == other._default and 2809*cda5da8dSAndroid Build Coastguard Worker self._annotation == other._annotation) 2810*cda5da8dSAndroid Build Coastguard Worker 2811*cda5da8dSAndroid Build Coastguard Worker 2812*cda5da8dSAndroid Build Coastguard Workerclass BoundArguments: 2813*cda5da8dSAndroid Build Coastguard Worker """Result of `Signature.bind` call. Holds the mapping of arguments 2814*cda5da8dSAndroid Build Coastguard Worker to the function's parameters. 2815*cda5da8dSAndroid Build Coastguard Worker 2816*cda5da8dSAndroid Build Coastguard Worker Has the following public attributes: 2817*cda5da8dSAndroid Build Coastguard Worker 2818*cda5da8dSAndroid Build Coastguard Worker * arguments : dict 2819*cda5da8dSAndroid Build Coastguard Worker An ordered mutable mapping of parameters' names to arguments' values. 2820*cda5da8dSAndroid Build Coastguard Worker Does not contain arguments' default values. 2821*cda5da8dSAndroid Build Coastguard Worker * signature : Signature 2822*cda5da8dSAndroid Build Coastguard Worker The Signature object that created this instance. 2823*cda5da8dSAndroid Build Coastguard Worker * args : tuple 2824*cda5da8dSAndroid Build Coastguard Worker Tuple of positional arguments values. 2825*cda5da8dSAndroid Build Coastguard Worker * kwargs : dict 2826*cda5da8dSAndroid Build Coastguard Worker Dict of keyword arguments values. 2827*cda5da8dSAndroid Build Coastguard Worker """ 2828*cda5da8dSAndroid Build Coastguard Worker 2829*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('arguments', '_signature', '__weakref__') 2830*cda5da8dSAndroid Build Coastguard Worker 2831*cda5da8dSAndroid Build Coastguard Worker def __init__(self, signature, arguments): 2832*cda5da8dSAndroid Build Coastguard Worker self.arguments = arguments 2833*cda5da8dSAndroid Build Coastguard Worker self._signature = signature 2834*cda5da8dSAndroid Build Coastguard Worker 2835*cda5da8dSAndroid Build Coastguard Worker @property 2836*cda5da8dSAndroid Build Coastguard Worker def signature(self): 2837*cda5da8dSAndroid Build Coastguard Worker return self._signature 2838*cda5da8dSAndroid Build Coastguard Worker 2839*cda5da8dSAndroid Build Coastguard Worker @property 2840*cda5da8dSAndroid Build Coastguard Worker def args(self): 2841*cda5da8dSAndroid Build Coastguard Worker args = [] 2842*cda5da8dSAndroid Build Coastguard Worker for param_name, param in self._signature.parameters.items(): 2843*cda5da8dSAndroid Build Coastguard Worker if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): 2844*cda5da8dSAndroid Build Coastguard Worker break 2845*cda5da8dSAndroid Build Coastguard Worker 2846*cda5da8dSAndroid Build Coastguard Worker try: 2847*cda5da8dSAndroid Build Coastguard Worker arg = self.arguments[param_name] 2848*cda5da8dSAndroid Build Coastguard Worker except KeyError: 2849*cda5da8dSAndroid Build Coastguard Worker # We're done here. Other arguments 2850*cda5da8dSAndroid Build Coastguard Worker # will be mapped in 'BoundArguments.kwargs' 2851*cda5da8dSAndroid Build Coastguard Worker break 2852*cda5da8dSAndroid Build Coastguard Worker else: 2853*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_POSITIONAL: 2854*cda5da8dSAndroid Build Coastguard Worker # *args 2855*cda5da8dSAndroid Build Coastguard Worker args.extend(arg) 2856*cda5da8dSAndroid Build Coastguard Worker else: 2857*cda5da8dSAndroid Build Coastguard Worker # plain argument 2858*cda5da8dSAndroid Build Coastguard Worker args.append(arg) 2859*cda5da8dSAndroid Build Coastguard Worker 2860*cda5da8dSAndroid Build Coastguard Worker return tuple(args) 2861*cda5da8dSAndroid Build Coastguard Worker 2862*cda5da8dSAndroid Build Coastguard Worker @property 2863*cda5da8dSAndroid Build Coastguard Worker def kwargs(self): 2864*cda5da8dSAndroid Build Coastguard Worker kwargs = {} 2865*cda5da8dSAndroid Build Coastguard Worker kwargs_started = False 2866*cda5da8dSAndroid Build Coastguard Worker for param_name, param in self._signature.parameters.items(): 2867*cda5da8dSAndroid Build Coastguard Worker if not kwargs_started: 2868*cda5da8dSAndroid Build Coastguard Worker if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): 2869*cda5da8dSAndroid Build Coastguard Worker kwargs_started = True 2870*cda5da8dSAndroid Build Coastguard Worker else: 2871*cda5da8dSAndroid Build Coastguard Worker if param_name not in self.arguments: 2872*cda5da8dSAndroid Build Coastguard Worker kwargs_started = True 2873*cda5da8dSAndroid Build Coastguard Worker continue 2874*cda5da8dSAndroid Build Coastguard Worker 2875*cda5da8dSAndroid Build Coastguard Worker if not kwargs_started: 2876*cda5da8dSAndroid Build Coastguard Worker continue 2877*cda5da8dSAndroid Build Coastguard Worker 2878*cda5da8dSAndroid Build Coastguard Worker try: 2879*cda5da8dSAndroid Build Coastguard Worker arg = self.arguments[param_name] 2880*cda5da8dSAndroid Build Coastguard Worker except KeyError: 2881*cda5da8dSAndroid Build Coastguard Worker pass 2882*cda5da8dSAndroid Build Coastguard Worker else: 2883*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_KEYWORD: 2884*cda5da8dSAndroid Build Coastguard Worker # **kwargs 2885*cda5da8dSAndroid Build Coastguard Worker kwargs.update(arg) 2886*cda5da8dSAndroid Build Coastguard Worker else: 2887*cda5da8dSAndroid Build Coastguard Worker # plain keyword argument 2888*cda5da8dSAndroid Build Coastguard Worker kwargs[param_name] = arg 2889*cda5da8dSAndroid Build Coastguard Worker 2890*cda5da8dSAndroid Build Coastguard Worker return kwargs 2891*cda5da8dSAndroid Build Coastguard Worker 2892*cda5da8dSAndroid Build Coastguard Worker def apply_defaults(self): 2893*cda5da8dSAndroid Build Coastguard Worker """Set default values for missing arguments. 2894*cda5da8dSAndroid Build Coastguard Worker 2895*cda5da8dSAndroid Build Coastguard Worker For variable-positional arguments (*args) the default is an 2896*cda5da8dSAndroid Build Coastguard Worker empty tuple. 2897*cda5da8dSAndroid Build Coastguard Worker 2898*cda5da8dSAndroid Build Coastguard Worker For variable-keyword arguments (**kwargs) the default is an 2899*cda5da8dSAndroid Build Coastguard Worker empty dict. 2900*cda5da8dSAndroid Build Coastguard Worker """ 2901*cda5da8dSAndroid Build Coastguard Worker arguments = self.arguments 2902*cda5da8dSAndroid Build Coastguard Worker new_arguments = [] 2903*cda5da8dSAndroid Build Coastguard Worker for name, param in self._signature.parameters.items(): 2904*cda5da8dSAndroid Build Coastguard Worker try: 2905*cda5da8dSAndroid Build Coastguard Worker new_arguments.append((name, arguments[name])) 2906*cda5da8dSAndroid Build Coastguard Worker except KeyError: 2907*cda5da8dSAndroid Build Coastguard Worker if param.default is not _empty: 2908*cda5da8dSAndroid Build Coastguard Worker val = param.default 2909*cda5da8dSAndroid Build Coastguard Worker elif param.kind is _VAR_POSITIONAL: 2910*cda5da8dSAndroid Build Coastguard Worker val = () 2911*cda5da8dSAndroid Build Coastguard Worker elif param.kind is _VAR_KEYWORD: 2912*cda5da8dSAndroid Build Coastguard Worker val = {} 2913*cda5da8dSAndroid Build Coastguard Worker else: 2914*cda5da8dSAndroid Build Coastguard Worker # This BoundArguments was likely produced by 2915*cda5da8dSAndroid Build Coastguard Worker # Signature.bind_partial(). 2916*cda5da8dSAndroid Build Coastguard Worker continue 2917*cda5da8dSAndroid Build Coastguard Worker new_arguments.append((name, val)) 2918*cda5da8dSAndroid Build Coastguard Worker self.arguments = dict(new_arguments) 2919*cda5da8dSAndroid Build Coastguard Worker 2920*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 2921*cda5da8dSAndroid Build Coastguard Worker if self is other: 2922*cda5da8dSAndroid Build Coastguard Worker return True 2923*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, BoundArguments): 2924*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2925*cda5da8dSAndroid Build Coastguard Worker return (self.signature == other.signature and 2926*cda5da8dSAndroid Build Coastguard Worker self.arguments == other.arguments) 2927*cda5da8dSAndroid Build Coastguard Worker 2928*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 2929*cda5da8dSAndroid Build Coastguard Worker self._signature = state['_signature'] 2930*cda5da8dSAndroid Build Coastguard Worker self.arguments = state['arguments'] 2931*cda5da8dSAndroid Build Coastguard Worker 2932*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 2933*cda5da8dSAndroid Build Coastguard Worker return {'_signature': self._signature, 'arguments': self.arguments} 2934*cda5da8dSAndroid Build Coastguard Worker 2935*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2936*cda5da8dSAndroid Build Coastguard Worker args = [] 2937*cda5da8dSAndroid Build Coastguard Worker for arg, value in self.arguments.items(): 2938*cda5da8dSAndroid Build Coastguard Worker args.append('{}={!r}'.format(arg, value)) 2939*cda5da8dSAndroid Build Coastguard Worker return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args)) 2940*cda5da8dSAndroid Build Coastguard Worker 2941*cda5da8dSAndroid Build Coastguard Worker 2942*cda5da8dSAndroid Build Coastguard Workerclass Signature: 2943*cda5da8dSAndroid Build Coastguard Worker """A Signature object represents the overall signature of a function. 2944*cda5da8dSAndroid Build Coastguard Worker It stores a Parameter object for each parameter accepted by the 2945*cda5da8dSAndroid Build Coastguard Worker function, as well as information specific to the function itself. 2946*cda5da8dSAndroid Build Coastguard Worker 2947*cda5da8dSAndroid Build Coastguard Worker A Signature object has the following public attributes and methods: 2948*cda5da8dSAndroid Build Coastguard Worker 2949*cda5da8dSAndroid Build Coastguard Worker * parameters : OrderedDict 2950*cda5da8dSAndroid Build Coastguard Worker An ordered mapping of parameters' names to the corresponding 2951*cda5da8dSAndroid Build Coastguard Worker Parameter objects (keyword-only arguments are in the same order 2952*cda5da8dSAndroid Build Coastguard Worker as listed in `code.co_varnames`). 2953*cda5da8dSAndroid Build Coastguard Worker * return_annotation : object 2954*cda5da8dSAndroid Build Coastguard Worker The annotation for the return type of the function if specified. 2955*cda5da8dSAndroid Build Coastguard Worker If the function has no annotation for its return type, this 2956*cda5da8dSAndroid Build Coastguard Worker attribute is set to `Signature.empty`. 2957*cda5da8dSAndroid Build Coastguard Worker * bind(*args, **kwargs) -> BoundArguments 2958*cda5da8dSAndroid Build Coastguard Worker Creates a mapping from positional and keyword arguments to 2959*cda5da8dSAndroid Build Coastguard Worker parameters. 2960*cda5da8dSAndroid Build Coastguard Worker * bind_partial(*args, **kwargs) -> BoundArguments 2961*cda5da8dSAndroid Build Coastguard Worker Creates a partial mapping from positional and keyword arguments 2962*cda5da8dSAndroid Build Coastguard Worker to parameters (simulating 'functools.partial' behavior.) 2963*cda5da8dSAndroid Build Coastguard Worker """ 2964*cda5da8dSAndroid Build Coastguard Worker 2965*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('_return_annotation', '_parameters') 2966*cda5da8dSAndroid Build Coastguard Worker 2967*cda5da8dSAndroid Build Coastguard Worker _parameter_cls = Parameter 2968*cda5da8dSAndroid Build Coastguard Worker _bound_arguments_cls = BoundArguments 2969*cda5da8dSAndroid Build Coastguard Worker 2970*cda5da8dSAndroid Build Coastguard Worker empty = _empty 2971*cda5da8dSAndroid Build Coastguard Worker 2972*cda5da8dSAndroid Build Coastguard Worker def __init__(self, parameters=None, *, return_annotation=_empty, 2973*cda5da8dSAndroid Build Coastguard Worker __validate_parameters__=True): 2974*cda5da8dSAndroid Build Coastguard Worker """Constructs Signature from the given list of Parameter 2975*cda5da8dSAndroid Build Coastguard Worker objects and 'return_annotation'. All arguments are optional. 2976*cda5da8dSAndroid Build Coastguard Worker """ 2977*cda5da8dSAndroid Build Coastguard Worker 2978*cda5da8dSAndroid Build Coastguard Worker if parameters is None: 2979*cda5da8dSAndroid Build Coastguard Worker params = OrderedDict() 2980*cda5da8dSAndroid Build Coastguard Worker else: 2981*cda5da8dSAndroid Build Coastguard Worker if __validate_parameters__: 2982*cda5da8dSAndroid Build Coastguard Worker params = OrderedDict() 2983*cda5da8dSAndroid Build Coastguard Worker top_kind = _POSITIONAL_ONLY 2984*cda5da8dSAndroid Build Coastguard Worker seen_default = False 2985*cda5da8dSAndroid Build Coastguard Worker 2986*cda5da8dSAndroid Build Coastguard Worker for param in parameters: 2987*cda5da8dSAndroid Build Coastguard Worker kind = param.kind 2988*cda5da8dSAndroid Build Coastguard Worker name = param.name 2989*cda5da8dSAndroid Build Coastguard Worker 2990*cda5da8dSAndroid Build Coastguard Worker if kind < top_kind: 2991*cda5da8dSAndroid Build Coastguard Worker msg = ( 2992*cda5da8dSAndroid Build Coastguard Worker 'wrong parameter order: {} parameter before {} ' 2993*cda5da8dSAndroid Build Coastguard Worker 'parameter' 2994*cda5da8dSAndroid Build Coastguard Worker ) 2995*cda5da8dSAndroid Build Coastguard Worker msg = msg.format(top_kind.description, 2996*cda5da8dSAndroid Build Coastguard Worker kind.description) 2997*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 2998*cda5da8dSAndroid Build Coastguard Worker elif kind > top_kind: 2999*cda5da8dSAndroid Build Coastguard Worker top_kind = kind 3000*cda5da8dSAndroid Build Coastguard Worker 3001*cda5da8dSAndroid Build Coastguard Worker if kind in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD): 3002*cda5da8dSAndroid Build Coastguard Worker if param.default is _empty: 3003*cda5da8dSAndroid Build Coastguard Worker if seen_default: 3004*cda5da8dSAndroid Build Coastguard Worker # No default for this parameter, but the 3005*cda5da8dSAndroid Build Coastguard Worker # previous parameter of had a default 3006*cda5da8dSAndroid Build Coastguard Worker msg = 'non-default argument follows default ' \ 3007*cda5da8dSAndroid Build Coastguard Worker 'argument' 3008*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 3009*cda5da8dSAndroid Build Coastguard Worker else: 3010*cda5da8dSAndroid Build Coastguard Worker # There is a default for this parameter. 3011*cda5da8dSAndroid Build Coastguard Worker seen_default = True 3012*cda5da8dSAndroid Build Coastguard Worker 3013*cda5da8dSAndroid Build Coastguard Worker if name in params: 3014*cda5da8dSAndroid Build Coastguard Worker msg = 'duplicate parameter name: {!r}'.format(name) 3015*cda5da8dSAndroid Build Coastguard Worker raise ValueError(msg) 3016*cda5da8dSAndroid Build Coastguard Worker 3017*cda5da8dSAndroid Build Coastguard Worker params[name] = param 3018*cda5da8dSAndroid Build Coastguard Worker else: 3019*cda5da8dSAndroid Build Coastguard Worker params = OrderedDict((param.name, param) for param in parameters) 3020*cda5da8dSAndroid Build Coastguard Worker 3021*cda5da8dSAndroid Build Coastguard Worker self._parameters = types.MappingProxyType(params) 3022*cda5da8dSAndroid Build Coastguard Worker self._return_annotation = return_annotation 3023*cda5da8dSAndroid Build Coastguard Worker 3024*cda5da8dSAndroid Build Coastguard Worker @classmethod 3025*cda5da8dSAndroid Build Coastguard Worker def from_callable(cls, obj, *, 3026*cda5da8dSAndroid Build Coastguard Worker follow_wrapped=True, globals=None, locals=None, eval_str=False): 3027*cda5da8dSAndroid Build Coastguard Worker """Constructs Signature for the given callable object.""" 3028*cda5da8dSAndroid Build Coastguard Worker return _signature_from_callable(obj, sigcls=cls, 3029*cda5da8dSAndroid Build Coastguard Worker follow_wrapper_chains=follow_wrapped, 3030*cda5da8dSAndroid Build Coastguard Worker globals=globals, locals=locals, eval_str=eval_str) 3031*cda5da8dSAndroid Build Coastguard Worker 3032*cda5da8dSAndroid Build Coastguard Worker @property 3033*cda5da8dSAndroid Build Coastguard Worker def parameters(self): 3034*cda5da8dSAndroid Build Coastguard Worker return self._parameters 3035*cda5da8dSAndroid Build Coastguard Worker 3036*cda5da8dSAndroid Build Coastguard Worker @property 3037*cda5da8dSAndroid Build Coastguard Worker def return_annotation(self): 3038*cda5da8dSAndroid Build Coastguard Worker return self._return_annotation 3039*cda5da8dSAndroid Build Coastguard Worker 3040*cda5da8dSAndroid Build Coastguard Worker def replace(self, *, parameters=_void, return_annotation=_void): 3041*cda5da8dSAndroid Build Coastguard Worker """Creates a customized copy of the Signature. 3042*cda5da8dSAndroid Build Coastguard Worker Pass 'parameters' and/or 'return_annotation' arguments 3043*cda5da8dSAndroid Build Coastguard Worker to override them in the new copy. 3044*cda5da8dSAndroid Build Coastguard Worker """ 3045*cda5da8dSAndroid Build Coastguard Worker 3046*cda5da8dSAndroid Build Coastguard Worker if parameters is _void: 3047*cda5da8dSAndroid Build Coastguard Worker parameters = self.parameters.values() 3048*cda5da8dSAndroid Build Coastguard Worker 3049*cda5da8dSAndroid Build Coastguard Worker if return_annotation is _void: 3050*cda5da8dSAndroid Build Coastguard Worker return_annotation = self._return_annotation 3051*cda5da8dSAndroid Build Coastguard Worker 3052*cda5da8dSAndroid Build Coastguard Worker return type(self)(parameters, 3053*cda5da8dSAndroid Build Coastguard Worker return_annotation=return_annotation) 3054*cda5da8dSAndroid Build Coastguard Worker 3055*cda5da8dSAndroid Build Coastguard Worker def _hash_basis(self): 3056*cda5da8dSAndroid Build Coastguard Worker params = tuple(param for param in self.parameters.values() 3057*cda5da8dSAndroid Build Coastguard Worker if param.kind != _KEYWORD_ONLY) 3058*cda5da8dSAndroid Build Coastguard Worker 3059*cda5da8dSAndroid Build Coastguard Worker kwo_params = {param.name: param for param in self.parameters.values() 3060*cda5da8dSAndroid Build Coastguard Worker if param.kind == _KEYWORD_ONLY} 3061*cda5da8dSAndroid Build Coastguard Worker 3062*cda5da8dSAndroid Build Coastguard Worker return params, kwo_params, self.return_annotation 3063*cda5da8dSAndroid Build Coastguard Worker 3064*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 3065*cda5da8dSAndroid Build Coastguard Worker params, kwo_params, return_annotation = self._hash_basis() 3066*cda5da8dSAndroid Build Coastguard Worker kwo_params = frozenset(kwo_params.values()) 3067*cda5da8dSAndroid Build Coastguard Worker return hash((params, kwo_params, return_annotation)) 3068*cda5da8dSAndroid Build Coastguard Worker 3069*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 3070*cda5da8dSAndroid Build Coastguard Worker if self is other: 3071*cda5da8dSAndroid Build Coastguard Worker return True 3072*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, Signature): 3073*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 3074*cda5da8dSAndroid Build Coastguard Worker return self._hash_basis() == other._hash_basis() 3075*cda5da8dSAndroid Build Coastguard Worker 3076*cda5da8dSAndroid Build Coastguard Worker def _bind(self, args, kwargs, *, partial=False): 3077*cda5da8dSAndroid Build Coastguard Worker """Private method. Don't use directly.""" 3078*cda5da8dSAndroid Build Coastguard Worker 3079*cda5da8dSAndroid Build Coastguard Worker arguments = {} 3080*cda5da8dSAndroid Build Coastguard Worker 3081*cda5da8dSAndroid Build Coastguard Worker parameters = iter(self.parameters.values()) 3082*cda5da8dSAndroid Build Coastguard Worker parameters_ex = () 3083*cda5da8dSAndroid Build Coastguard Worker arg_vals = iter(args) 3084*cda5da8dSAndroid Build Coastguard Worker 3085*cda5da8dSAndroid Build Coastguard Worker while True: 3086*cda5da8dSAndroid Build Coastguard Worker # Let's iterate through the positional arguments and corresponding 3087*cda5da8dSAndroid Build Coastguard Worker # parameters 3088*cda5da8dSAndroid Build Coastguard Worker try: 3089*cda5da8dSAndroid Build Coastguard Worker arg_val = next(arg_vals) 3090*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 3091*cda5da8dSAndroid Build Coastguard Worker # No more positional arguments 3092*cda5da8dSAndroid Build Coastguard Worker try: 3093*cda5da8dSAndroid Build Coastguard Worker param = next(parameters) 3094*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 3095*cda5da8dSAndroid Build Coastguard Worker # No more parameters. That's it. Just need to check that 3096*cda5da8dSAndroid Build Coastguard Worker # we have no `kwargs` after this while loop 3097*cda5da8dSAndroid Build Coastguard Worker break 3098*cda5da8dSAndroid Build Coastguard Worker else: 3099*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_POSITIONAL: 3100*cda5da8dSAndroid Build Coastguard Worker # That's OK, just empty *args. Let's start parsing 3101*cda5da8dSAndroid Build Coastguard Worker # kwargs 3102*cda5da8dSAndroid Build Coastguard Worker break 3103*cda5da8dSAndroid Build Coastguard Worker elif param.name in kwargs: 3104*cda5da8dSAndroid Build Coastguard Worker if param.kind == _POSITIONAL_ONLY: 3105*cda5da8dSAndroid Build Coastguard Worker msg = '{arg!r} parameter is positional only, ' \ 3106*cda5da8dSAndroid Build Coastguard Worker 'but was passed as a keyword' 3107*cda5da8dSAndroid Build Coastguard Worker msg = msg.format(arg=param.name) 3108*cda5da8dSAndroid Build Coastguard Worker raise TypeError(msg) from None 3109*cda5da8dSAndroid Build Coastguard Worker parameters_ex = (param,) 3110*cda5da8dSAndroid Build Coastguard Worker break 3111*cda5da8dSAndroid Build Coastguard Worker elif (param.kind == _VAR_KEYWORD or 3112*cda5da8dSAndroid Build Coastguard Worker param.default is not _empty): 3113*cda5da8dSAndroid Build Coastguard Worker # That's fine too - we have a default value for this 3114*cda5da8dSAndroid Build Coastguard Worker # parameter. So, lets start parsing `kwargs`, starting 3115*cda5da8dSAndroid Build Coastguard Worker # with the current parameter 3116*cda5da8dSAndroid Build Coastguard Worker parameters_ex = (param,) 3117*cda5da8dSAndroid Build Coastguard Worker break 3118*cda5da8dSAndroid Build Coastguard Worker else: 3119*cda5da8dSAndroid Build Coastguard Worker # No default, not VAR_KEYWORD, not VAR_POSITIONAL, 3120*cda5da8dSAndroid Build Coastguard Worker # not in `kwargs` 3121*cda5da8dSAndroid Build Coastguard Worker if partial: 3122*cda5da8dSAndroid Build Coastguard Worker parameters_ex = (param,) 3123*cda5da8dSAndroid Build Coastguard Worker break 3124*cda5da8dSAndroid Build Coastguard Worker else: 3125*cda5da8dSAndroid Build Coastguard Worker msg = 'missing a required argument: {arg!r}' 3126*cda5da8dSAndroid Build Coastguard Worker msg = msg.format(arg=param.name) 3127*cda5da8dSAndroid Build Coastguard Worker raise TypeError(msg) from None 3128*cda5da8dSAndroid Build Coastguard Worker else: 3129*cda5da8dSAndroid Build Coastguard Worker # We have a positional argument to process 3130*cda5da8dSAndroid Build Coastguard Worker try: 3131*cda5da8dSAndroid Build Coastguard Worker param = next(parameters) 3132*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 3133*cda5da8dSAndroid Build Coastguard Worker raise TypeError('too many positional arguments') from None 3134*cda5da8dSAndroid Build Coastguard Worker else: 3135*cda5da8dSAndroid Build Coastguard Worker if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): 3136*cda5da8dSAndroid Build Coastguard Worker # Looks like we have no parameter for this positional 3137*cda5da8dSAndroid Build Coastguard Worker # argument 3138*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 3139*cda5da8dSAndroid Build Coastguard Worker 'too many positional arguments') from None 3140*cda5da8dSAndroid Build Coastguard Worker 3141*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_POSITIONAL: 3142*cda5da8dSAndroid Build Coastguard Worker # We have an '*args'-like argument, let's fill it with 3143*cda5da8dSAndroid Build Coastguard Worker # all positional arguments we have left and move on to 3144*cda5da8dSAndroid Build Coastguard Worker # the next phase 3145*cda5da8dSAndroid Build Coastguard Worker values = [arg_val] 3146*cda5da8dSAndroid Build Coastguard Worker values.extend(arg_vals) 3147*cda5da8dSAndroid Build Coastguard Worker arguments[param.name] = tuple(values) 3148*cda5da8dSAndroid Build Coastguard Worker break 3149*cda5da8dSAndroid Build Coastguard Worker 3150*cda5da8dSAndroid Build Coastguard Worker if param.name in kwargs and param.kind != _POSITIONAL_ONLY: 3151*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 3152*cda5da8dSAndroid Build Coastguard Worker 'multiple values for argument {arg!r}'.format( 3153*cda5da8dSAndroid Build Coastguard Worker arg=param.name)) from None 3154*cda5da8dSAndroid Build Coastguard Worker 3155*cda5da8dSAndroid Build Coastguard Worker arguments[param.name] = arg_val 3156*cda5da8dSAndroid Build Coastguard Worker 3157*cda5da8dSAndroid Build Coastguard Worker # Now, we iterate through the remaining parameters to process 3158*cda5da8dSAndroid Build Coastguard Worker # keyword arguments 3159*cda5da8dSAndroid Build Coastguard Worker kwargs_param = None 3160*cda5da8dSAndroid Build Coastguard Worker for param in itertools.chain(parameters_ex, parameters): 3161*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_KEYWORD: 3162*cda5da8dSAndroid Build Coastguard Worker # Memorize that we have a '**kwargs'-like parameter 3163*cda5da8dSAndroid Build Coastguard Worker kwargs_param = param 3164*cda5da8dSAndroid Build Coastguard Worker continue 3165*cda5da8dSAndroid Build Coastguard Worker 3166*cda5da8dSAndroid Build Coastguard Worker if param.kind == _VAR_POSITIONAL: 3167*cda5da8dSAndroid Build Coastguard Worker # Named arguments don't refer to '*args'-like parameters. 3168*cda5da8dSAndroid Build Coastguard Worker # We only arrive here if the positional arguments ended 3169*cda5da8dSAndroid Build Coastguard Worker # before reaching the last parameter before *args. 3170*cda5da8dSAndroid Build Coastguard Worker continue 3171*cda5da8dSAndroid Build Coastguard Worker 3172*cda5da8dSAndroid Build Coastguard Worker param_name = param.name 3173*cda5da8dSAndroid Build Coastguard Worker try: 3174*cda5da8dSAndroid Build Coastguard Worker arg_val = kwargs.pop(param_name) 3175*cda5da8dSAndroid Build Coastguard Worker except KeyError: 3176*cda5da8dSAndroid Build Coastguard Worker # We have no value for this parameter. It's fine though, 3177*cda5da8dSAndroid Build Coastguard Worker # if it has a default value, or it is an '*args'-like 3178*cda5da8dSAndroid Build Coastguard Worker # parameter, left alone by the processing of positional 3179*cda5da8dSAndroid Build Coastguard Worker # arguments. 3180*cda5da8dSAndroid Build Coastguard Worker if (not partial and param.kind != _VAR_POSITIONAL and 3181*cda5da8dSAndroid Build Coastguard Worker param.default is _empty): 3182*cda5da8dSAndroid Build Coastguard Worker raise TypeError('missing a required argument: {arg!r}'. \ 3183*cda5da8dSAndroid Build Coastguard Worker format(arg=param_name)) from None 3184*cda5da8dSAndroid Build Coastguard Worker 3185*cda5da8dSAndroid Build Coastguard Worker else: 3186*cda5da8dSAndroid Build Coastguard Worker if param.kind == _POSITIONAL_ONLY: 3187*cda5da8dSAndroid Build Coastguard Worker # This should never happen in case of a properly built 3188*cda5da8dSAndroid Build Coastguard Worker # Signature object (but let's have this check here 3189*cda5da8dSAndroid Build Coastguard Worker # to ensure correct behaviour just in case) 3190*cda5da8dSAndroid Build Coastguard Worker raise TypeError('{arg!r} parameter is positional only, ' 3191*cda5da8dSAndroid Build Coastguard Worker 'but was passed as a keyword'. \ 3192*cda5da8dSAndroid Build Coastguard Worker format(arg=param.name)) 3193*cda5da8dSAndroid Build Coastguard Worker 3194*cda5da8dSAndroid Build Coastguard Worker arguments[param_name] = arg_val 3195*cda5da8dSAndroid Build Coastguard Worker 3196*cda5da8dSAndroid Build Coastguard Worker if kwargs: 3197*cda5da8dSAndroid Build Coastguard Worker if kwargs_param is not None: 3198*cda5da8dSAndroid Build Coastguard Worker # Process our '**kwargs'-like parameter 3199*cda5da8dSAndroid Build Coastguard Worker arguments[kwargs_param.name] = kwargs 3200*cda5da8dSAndroid Build Coastguard Worker else: 3201*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 3202*cda5da8dSAndroid Build Coastguard Worker 'got an unexpected keyword argument {arg!r}'.format( 3203*cda5da8dSAndroid Build Coastguard Worker arg=next(iter(kwargs)))) 3204*cda5da8dSAndroid Build Coastguard Worker 3205*cda5da8dSAndroid Build Coastguard Worker return self._bound_arguments_cls(self, arguments) 3206*cda5da8dSAndroid Build Coastguard Worker 3207*cda5da8dSAndroid Build Coastguard Worker def bind(self, /, *args, **kwargs): 3208*cda5da8dSAndroid Build Coastguard Worker """Get a BoundArguments object, that maps the passed `args` 3209*cda5da8dSAndroid Build Coastguard Worker and `kwargs` to the function's signature. Raises `TypeError` 3210*cda5da8dSAndroid Build Coastguard Worker if the passed arguments can not be bound. 3211*cda5da8dSAndroid Build Coastguard Worker """ 3212*cda5da8dSAndroid Build Coastguard Worker return self._bind(args, kwargs) 3213*cda5da8dSAndroid Build Coastguard Worker 3214*cda5da8dSAndroid Build Coastguard Worker def bind_partial(self, /, *args, **kwargs): 3215*cda5da8dSAndroid Build Coastguard Worker """Get a BoundArguments object, that partially maps the 3216*cda5da8dSAndroid Build Coastguard Worker passed `args` and `kwargs` to the function's signature. 3217*cda5da8dSAndroid Build Coastguard Worker Raises `TypeError` if the passed arguments can not be bound. 3218*cda5da8dSAndroid Build Coastguard Worker """ 3219*cda5da8dSAndroid Build Coastguard Worker return self._bind(args, kwargs, partial=True) 3220*cda5da8dSAndroid Build Coastguard Worker 3221*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 3222*cda5da8dSAndroid Build Coastguard Worker return (type(self), 3223*cda5da8dSAndroid Build Coastguard Worker (tuple(self._parameters.values()),), 3224*cda5da8dSAndroid Build Coastguard Worker {'_return_annotation': self._return_annotation}) 3225*cda5da8dSAndroid Build Coastguard Worker 3226*cda5da8dSAndroid Build Coastguard Worker def __setstate__(self, state): 3227*cda5da8dSAndroid Build Coastguard Worker self._return_annotation = state['_return_annotation'] 3228*cda5da8dSAndroid Build Coastguard Worker 3229*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 3230*cda5da8dSAndroid Build Coastguard Worker return '<{} {}>'.format(self.__class__.__name__, self) 3231*cda5da8dSAndroid Build Coastguard Worker 3232*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 3233*cda5da8dSAndroid Build Coastguard Worker result = [] 3234*cda5da8dSAndroid Build Coastguard Worker render_pos_only_separator = False 3235*cda5da8dSAndroid Build Coastguard Worker render_kw_only_separator = True 3236*cda5da8dSAndroid Build Coastguard Worker for param in self.parameters.values(): 3237*cda5da8dSAndroid Build Coastguard Worker formatted = str(param) 3238*cda5da8dSAndroid Build Coastguard Worker 3239*cda5da8dSAndroid Build Coastguard Worker kind = param.kind 3240*cda5da8dSAndroid Build Coastguard Worker 3241*cda5da8dSAndroid Build Coastguard Worker if kind == _POSITIONAL_ONLY: 3242*cda5da8dSAndroid Build Coastguard Worker render_pos_only_separator = True 3243*cda5da8dSAndroid Build Coastguard Worker elif render_pos_only_separator: 3244*cda5da8dSAndroid Build Coastguard Worker # It's not a positional-only parameter, and the flag 3245*cda5da8dSAndroid Build Coastguard Worker # is set to 'True' (there were pos-only params before.) 3246*cda5da8dSAndroid Build Coastguard Worker result.append('/') 3247*cda5da8dSAndroid Build Coastguard Worker render_pos_only_separator = False 3248*cda5da8dSAndroid Build Coastguard Worker 3249*cda5da8dSAndroid Build Coastguard Worker if kind == _VAR_POSITIONAL: 3250*cda5da8dSAndroid Build Coastguard Worker # OK, we have an '*args'-like parameter, so we won't need 3251*cda5da8dSAndroid Build Coastguard Worker # a '*' to separate keyword-only arguments 3252*cda5da8dSAndroid Build Coastguard Worker render_kw_only_separator = False 3253*cda5da8dSAndroid Build Coastguard Worker elif kind == _KEYWORD_ONLY and render_kw_only_separator: 3254*cda5da8dSAndroid Build Coastguard Worker # We have a keyword-only parameter to render and we haven't 3255*cda5da8dSAndroid Build Coastguard Worker # rendered an '*args'-like parameter before, so add a '*' 3256*cda5da8dSAndroid Build Coastguard Worker # separator to the parameters list ("foo(arg1, *, arg2)" case) 3257*cda5da8dSAndroid Build Coastguard Worker result.append('*') 3258*cda5da8dSAndroid Build Coastguard Worker # This condition should be only triggered once, so 3259*cda5da8dSAndroid Build Coastguard Worker # reset the flag 3260*cda5da8dSAndroid Build Coastguard Worker render_kw_only_separator = False 3261*cda5da8dSAndroid Build Coastguard Worker 3262*cda5da8dSAndroid Build Coastguard Worker result.append(formatted) 3263*cda5da8dSAndroid Build Coastguard Worker 3264*cda5da8dSAndroid Build Coastguard Worker if render_pos_only_separator: 3265*cda5da8dSAndroid Build Coastguard Worker # There were only positional-only parameters, hence the 3266*cda5da8dSAndroid Build Coastguard Worker # flag was not reset to 'False' 3267*cda5da8dSAndroid Build Coastguard Worker result.append('/') 3268*cda5da8dSAndroid Build Coastguard Worker 3269*cda5da8dSAndroid Build Coastguard Worker rendered = '({})'.format(', '.join(result)) 3270*cda5da8dSAndroid Build Coastguard Worker 3271*cda5da8dSAndroid Build Coastguard Worker if self.return_annotation is not _empty: 3272*cda5da8dSAndroid Build Coastguard Worker anno = formatannotation(self.return_annotation) 3273*cda5da8dSAndroid Build Coastguard Worker rendered += ' -> {}'.format(anno) 3274*cda5da8dSAndroid Build Coastguard Worker 3275*cda5da8dSAndroid Build Coastguard Worker return rendered 3276*cda5da8dSAndroid Build Coastguard Worker 3277*cda5da8dSAndroid Build Coastguard Worker 3278*cda5da8dSAndroid Build Coastguard Workerdef signature(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False): 3279*cda5da8dSAndroid Build Coastguard Worker """Get a signature object for the passed callable.""" 3280*cda5da8dSAndroid Build Coastguard Worker return Signature.from_callable(obj, follow_wrapped=follow_wrapped, 3281*cda5da8dSAndroid Build Coastguard Worker globals=globals, locals=locals, eval_str=eval_str) 3282*cda5da8dSAndroid Build Coastguard Worker 3283*cda5da8dSAndroid Build Coastguard Worker 3284*cda5da8dSAndroid Build Coastguard Workerdef _main(): 3285*cda5da8dSAndroid Build Coastguard Worker """ Logic for inspecting an object given at command line """ 3286*cda5da8dSAndroid Build Coastguard Worker import argparse 3287*cda5da8dSAndroid Build Coastguard Worker import importlib 3288*cda5da8dSAndroid Build Coastguard Worker 3289*cda5da8dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 3290*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 3291*cda5da8dSAndroid Build Coastguard Worker 'object', 3292*cda5da8dSAndroid Build Coastguard Worker help="The object to be analysed. " 3293*cda5da8dSAndroid Build Coastguard Worker "It supports the 'module:qualname' syntax") 3294*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 3295*cda5da8dSAndroid Build Coastguard Worker '-d', '--details', action='store_true', 3296*cda5da8dSAndroid Build Coastguard Worker help='Display info about the module rather than its source code') 3297*cda5da8dSAndroid Build Coastguard Worker 3298*cda5da8dSAndroid Build Coastguard Worker args = parser.parse_args() 3299*cda5da8dSAndroid Build Coastguard Worker 3300*cda5da8dSAndroid Build Coastguard Worker target = args.object 3301*cda5da8dSAndroid Build Coastguard Worker mod_name, has_attrs, attrs = target.partition(":") 3302*cda5da8dSAndroid Build Coastguard Worker try: 3303*cda5da8dSAndroid Build Coastguard Worker obj = module = importlib.import_module(mod_name) 3304*cda5da8dSAndroid Build Coastguard Worker except Exception as exc: 3305*cda5da8dSAndroid Build Coastguard Worker msg = "Failed to import {} ({}: {})".format(mod_name, 3306*cda5da8dSAndroid Build Coastguard Worker type(exc).__name__, 3307*cda5da8dSAndroid Build Coastguard Worker exc) 3308*cda5da8dSAndroid Build Coastguard Worker print(msg, file=sys.stderr) 3309*cda5da8dSAndroid Build Coastguard Worker sys.exit(2) 3310*cda5da8dSAndroid Build Coastguard Worker 3311*cda5da8dSAndroid Build Coastguard Worker if has_attrs: 3312*cda5da8dSAndroid Build Coastguard Worker parts = attrs.split(".") 3313*cda5da8dSAndroid Build Coastguard Worker obj = module 3314*cda5da8dSAndroid Build Coastguard Worker for part in parts: 3315*cda5da8dSAndroid Build Coastguard Worker obj = getattr(obj, part) 3316*cda5da8dSAndroid Build Coastguard Worker 3317*cda5da8dSAndroid Build Coastguard Worker if module.__name__ in sys.builtin_module_names: 3318*cda5da8dSAndroid Build Coastguard Worker print("Can't get info for builtin modules.", file=sys.stderr) 3319*cda5da8dSAndroid Build Coastguard Worker sys.exit(1) 3320*cda5da8dSAndroid Build Coastguard Worker 3321*cda5da8dSAndroid Build Coastguard Worker if args.details: 3322*cda5da8dSAndroid Build Coastguard Worker print('Target: {}'.format(target)) 3323*cda5da8dSAndroid Build Coastguard Worker print('Origin: {}'.format(getsourcefile(module))) 3324*cda5da8dSAndroid Build Coastguard Worker print('Cached: {}'.format(module.__cached__)) 3325*cda5da8dSAndroid Build Coastguard Worker if obj is module: 3326*cda5da8dSAndroid Build Coastguard Worker print('Loader: {}'.format(repr(module.__loader__))) 3327*cda5da8dSAndroid Build Coastguard Worker if hasattr(module, '__path__'): 3328*cda5da8dSAndroid Build Coastguard Worker print('Submodule search path: {}'.format(module.__path__)) 3329*cda5da8dSAndroid Build Coastguard Worker else: 3330*cda5da8dSAndroid Build Coastguard Worker try: 3331*cda5da8dSAndroid Build Coastguard Worker __, lineno = findsource(obj) 3332*cda5da8dSAndroid Build Coastguard Worker except Exception: 3333*cda5da8dSAndroid Build Coastguard Worker pass 3334*cda5da8dSAndroid Build Coastguard Worker else: 3335*cda5da8dSAndroid Build Coastguard Worker print('Line: {}'.format(lineno)) 3336*cda5da8dSAndroid Build Coastguard Worker 3337*cda5da8dSAndroid Build Coastguard Worker print('\n') 3338*cda5da8dSAndroid Build Coastguard Worker else: 3339*cda5da8dSAndroid Build Coastguard Worker print(getsource(obj)) 3340*cda5da8dSAndroid Build Coastguard Worker 3341*cda5da8dSAndroid Build Coastguard Worker 3342*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 3343*cda5da8dSAndroid Build Coastguard Worker _main() 3344