Ϫfh6dZddlmZddlZddlZddlZddlZddlmZm Z ddl m Z m Z ddlmZddlmZddlmZmZdd lmZdd lmZeZd gZeduZerej;d nej;d dZdZGddZ GddZ!Gdde Z"Gdde Z#Gdde Z$e e$GddZ%e%Z&e e$GddZ'ee'ejPe$dZ)Gdd Z*e*Z+d$d!Z,d"Z-d#Z.y)%a_ This module aims to provide a unified, object-oriented view of Python's runtime hierarchy. Python is a very dynamic language with wide variety of introspection utilities. However, these utilities can be hard to use, because there is no consistent API. The introspection API in python is made up of attributes (__name__, __module__, func_name, etc) on instances, modules, classes and functions which vary between those four types, utility modules such as 'inspect' which provide some functionality, the 'imp' module, the "compiler" module, the semantics of PEP 302 support, and setuptools, among other things. At the top, you have "PythonPath", an abstract representation of sys.path which includes methods to locate top-level modules, with or without loading them. The top-level exposed functions in this module for accessing the system path are "walkModules", "iterModules", and "getModule". From most to least specific, here are the objects provided:: PythonPath # sys.path | v PathEntry # one entry on sys.path: an importer | v PythonModule # a module or package that can be loaded | v PythonAttribute # an attribute of a module (function or class) | v PythonAttribute # an attribute of a function or class | v ... Here's an example of idiomatic usage: this is what you would do to list all of the modules outside the standard library's python-files directory:: import os stdlibdir = os.path.dirname(os.__file__) from twisted.python.modules import iterModules for modinfo in iterModules(): if (modinfo.pathEntry.filePath.path != stdlibdir and not modinfo.isPackage()): print('unpackaged: %s: %s' % ( modinfo.name, modinfo.filePath.path)) @var theSystemPath: The very top of the Python object space. @type theSystemPath: L{PythonPath} ) annotationsN)dirnamesplit) Interface implementer nativeString)registerAdapter)FilePathUnlistableError)namedAny) ZipArchivez.pyz.pyoz.pycc8t|}d|vxr d|vxrd|vS)z cheezy fake test for proper identifier-ness. @param string: a L{str} which might or might not be a valid python identifier. @return: True or False  .-r)string textStrings 8/usr/lib/python3/dist-packages/twisted/python/modules.py_isPythonIdentifierrWs-f%J j TS %: Ts*?TTcN|jd}t|d}|dk(S)Nr__init__)splitext splitpath)fpathextlessbasends r_isPackagePathr cs/nnq!G w  "F Z rc<eZdZdZdZd dZdZdZdZdZ dZ y ) _ModuleIteratorHelperz This mixin provides common behavior between python module and path entries, since the mechanism for searching sys.path and __path__ attributes is remarkably similar. c #TKi}|jjsy|jD]c} t|j }|D]@}|j d}|jdt| }|tvrft|sH|j|}|jdddk(rq||vsvd||<t|||j}||k7sJ||st|r|js|j|j}tD]Y}|j!d|z} | js(||vs-d||<t|| |j}||k7sJ|@Cfy#t $rYtwxYww)a Loop over the modules present below this entry or package on PYTHONPATH. For modules which are not packages, this will yield nothing. For packages and path entries, this will only yield modules one level down; i.e. if there is a package a.b.c, iterModules on a will only return a.b. If you want to descend deeply, use walkModules. @return: a generator which yields PythonModule instances that describe modules which can be, or have been, imported. NrrrT)filePathexists _packagePathssortedchildrenr rbasenamelenPYTHON_EXTENSIONSr_subModuleNamer PythonModule _getEntryisdirchild) selfyielded placeToLookr)potentialTopLevelextpotentialBasenamemodnamepminitpys r iterModulesz!_ModuleIteratorHelper.iterModulesrs}}##% --/( "K !+"6"6"89&." "!'00215$5$>$>$@CH9$M!++//@A "112CDG}}S)"-;!g-+/()'3DdnnFVW!Tz)z 23DE0668 "112C2L2L2NOG0"!2!8!8c9I!J!==?wg/E/3GG,!-gvt~~?O!PB#%:-:"$H!"7" " ( "#  s<2F(FA7F(BF(F("6F( F%!F($F%%F(c#vK||jD]}|j|Ed{y7w)z Similar to L{iterModules}, this yields self, and then every module in my package or entry, and every submodule in each package or entry. In other words, this is deep, and L{iterModules} is shallow. importPackagesNr; walkModulesr2r>packages rr@z!_ModuleIteratorHelper.walkModulessA '') JG**.*I I I J Is -979c|S)z This is a hook to provide packages with the ability to specify their names as a prefix to submodules here. r2mns rr-z$_ModuleIteratorHelper._subModuleNames  rct)z Implement in subclasses to specify where to look for modules. @return: iterable of FilePath-like objects. NotImplementedErrorr2s rr'z#_ModuleIteratorHelper._packagePathss "##rct)z Implement in subclasses to specify what path entry submodules will come from. @return: a PathEntry instance. rHrJs rr/z_ModuleIteratorHelper._getEntrys "##rc|jD]$}|j|j|k(s"|cSt|)a( Retrieve a module from below this path or package. @param modname: a str naming a module to be loaded. For entries, this is a top-level, undotted package name, and for packages it is the name of the module without the package prefix. For example, if you have a PythonModule representing the 'twisted' package, you could use:: twistedPackageObj['python']['modules'] to retrieve this module. @raise KeyError: if the module is not found. @return: a PythonModule. )r;namer-KeyError)r2r8modules r __getitem__z!_ModuleIteratorHelper.__getitem__sE"&&( F{{d11'::  wrct)aD Implemented to raise NotImplementedError for clarity, so that attempting to loop over this object won't call __getitem__. Note: in the future there might be some sensible default for iteration, like 'walkEverything', so this is deliberately untested and undefined behavior. rHrJs r__iter__z_ModuleIteratorHelper.__iter__s "##rNF) __name__ __module__ __qualname____doc__r;r@r-r'r/rPrRrDrrr"r"ks, 9"v J$$ , $rr"cJeZdZdZ ddZd dZdZefdZdZ y) PythonAttributeag I represent a function, class, or other object that is present. @ivar name: the fully-qualified python name of this attribute. @ivar onObject: a reference to a PythonModule or other PythonAttribute that is this attribute's logical parent. @ivar name: the fully qualified python name of the attribute represented by this class. c<||_||_||_||_y)aJ Create a PythonAttribute. This is a private constructor. Do not construct me directly, use PythonModule.iterAttributes. @param name: the FQPN @param onObject: see ivar @param loaded: always True, for now @param pythonValue: the value of the attribute we're pointing to. N)rMonObject_loaded pythonValue)r2rMr[loadedr]s rrzPythonAttribute.__init__s!    &rc"d|jdS)NzPythonAttribute<>rMrJs r__repr__zPythonAttribute.__repr__s!$))a00rc|jS)a  Return a boolean describing whether the attribute this describes has actually been loaded into memory by importing its module. Note: this currently always returns true; there is no Python parser support in this module yet. )r\rJs risLoadedzPythonAttribute.isLoadeds||rc|jS)z Load the value associated with this attribute. @return: an arbitrary Python object, or 'default' if there is an error loading it. )r]r2defaults rloadzPythonAttribute.loadsrc#Ktj|jD]%\}}t|jdz|z|d|'yw)NrT)inspect getmembersrhrYrMr2rMvals riterAttributeszPythonAttribute.iterAttributes&sJ ++DIIK8 KID#!$))c/D"8$cJ J KsA AN) rMstrr[rYr^boolr]objectreturnNonerrro) rTrUrVrWrrbrd_nothingrhrnrDrrrYrYsN ''#2'<@'OU' '"1$ KrrYczeZdZdZ d dZdZddZdZdZdZ e fdZ dd Z dfd Z d Zd ZxZS)r.a? Representation of a module which could be imported from sys.path. @ivar name: the fully qualified python name of this module. @ivar filePath: a FilePath-like object which points to the location of this module. @ivar pathEntry: a L{PathEntry} instance which this module was located from. ct|}|jdrJ||_||_|j |_||_y)z Create a PythonModule. Do not construct this directly, instead inspect a PythonPath or other PythonModule instances. @param name: see ivar @param filePath: see ivar @param pathEntry: see ivar z .__init__N)r endswithrMr%parent parentPath pathEntry)r2rMr%r{_names rrzPythonModule.__init__8sCT">>+...   "//+"rc|jSN)r{rJs rr/zPythonModule._getEntryJs ~~rc"d|jdS)zK Return a string representation including the module name. z PythonModule>,,99$))D D h&  s.1AAc`t|tr|j|jk(StS)z= PythonModules with the same name are equal. ) isinstancer.rMNotImplemented)r2others r__eq__zPythonModule.__eq__s' e\ *::* *rch|r |jr|jt| |S)Nr=)rrhsuperr@)r2r> __class__s rr@zPythonModule.walkModuless+ dnn. IIKw"."AArc&|jdz|zS)zG submodules of this module are prefixed with our name. rrarEs rr-zPythonModule._subModuleNamesyy3##rc#K|jsy|jr|j}t|dr|jD]}||j j k(r+|j jsJ|j G|jjj|}|js}|yy|j yw)zZ Yield a sequence of FilePath-like objects which represent path segments. N__path__) rrdrhhasattrrrzpathr&r{r _smartPath)r2rhfnsmps rr'zPythonModule._packagePathss~~  ==?99;DtZ(--&BT__111#55777"oo-"nn77BB2F::<"%I&)// !s CC  C )rMror%z FilePath[str]r{ PathEntryrrrsrt)rrqrrrprS)rTrUrVrWrr/rbrdrnrrurhrr@r-r' __classcell__)rs@rr.r.+sg ###0#=F# #$. OK*-$0B $ "rr.c*eZdZdZdZdZddZdZy)rz I am a proxy for a single entry on sys.path. @ivar filePath: a FilePath-like object pointing at the filesystem location or archive file where this path entry is stored. @ivar pythonPath: a PythonPath instance. c ||_||_y)zE Create a PathEntry. This is a private constructor. N)r%r)r2r%rs rrzPathEntry.__init__s! $rc|Sr~rDrJs rr/zPathEntry._getEntrys rc"d|jdS)Nz PathEntryz%PythonPath.__init__..`sWr)r_sysPathFactory_sysPathr sysPathHooks importerCacher)r2rrrrrsysPathFactorys ` rrzPythonPath.__init__0sJ^  ,N  #3N- $(*(rc"|jS)zL Retrieve the current value of the module search path list. )rrJs rrzPythonPath.sysPathjs ##%%rc|}d|jvrI|jdj|jjddd}d|jvrIt t |j rtt|j }nt|j }||jvr'tj|d|jdd|S)zl Determine where a given Python module object came from by looking at path entries. rNr$z (for module zR) not in path importer cache (PEP 302 violation - check your local configuration).) stacklevel) rTrjoinrr r __file__rrwarningswarn)r2modobj topPackageObjrvals r_findEntryPathStringzPythonPath._findEntryPathStringqs  ]+++ OO//55c:3B?@M]+++ (=#9#9: ;7=#9#9:;D=112D t)) ) MM*   rc|jj|t}|tur$|jD] } ||} |turd}t |t j|S#t$rYBwxYw)z Given a path entry from sys.path which may refer to an importer, return the appropriate FilePath-like instance. @param pathName: a str describing the path. @return: a FilePath-like object. N)rrrur ImportErrorr_theDefaultMapperr)r2pathNameimportrhooks rrzPythonPath._smartPaths$$((8< h )) "8nG  (" *;<DDXNN #sA,, A87A8c#lK|jD]!}|j|}t||#yw)zm Iterate the entries on my sysPath. @return: a generator yielding PathEntry objects N)rrr)r2rfps r iterEntrieszPythonPath.iterEntriess6   &H*BB% % &s24c|jj|}|Rt|j|j ||}|j|j }t |||Sd|vr|}|jdD]}||} |S|jD]}|j|k(s|cSt|)a Get a python module by its given fully-qualified name. @param modname: The fully-qualified Python module name to load. @type modname: C{str} @return: an object representing the module identified by C{modname} @rtype: L{PythonModule} @raise KeyError: if the module name is not a valid module name, or no such module can be identified as loadable. r) rrrrrrr.rr;rMrN)r2r8 moduleObjectpemppkgrMrOs rrPzPythonPath.__getitem__s **73  # 9 9, GH$B!6!67BR0 0 '>C c* $i J&&( F{{g%  wrcF |j|y#t$rYywxYw)z Check to see whether or not a module exists on my import path. @param module: The name of the module to look for on my import path. @type module: C{str} TF)rPrN)r2rOs r __contains__zPythonPath.__contains__s*    V $  s   c<d|jd|jdS)zO Display my sysPath and moduleDict in a string representation. z PythonPath(,))rrrJs rrbzPythonPath.__repr__s#T\\,Adoo-@BBrc#jK|jD]}|jEd{y7w)z< Yield all top-level modules on my sysPath. N)rr;)r2entrys rr;zPythonPath.iterModuless5%%' +E((* * * + *s '313c#nK|jD]}|jdEd{y7w)z Similar to L{iterModules}, this yields every module on the path, then every submodule in each package or entry. Fr=Nr?rAs rr@zPythonPath.walkModuless< '') AG**%*@ @ @ A @s )535rtrS)rTrUrVrWrmodules path_hookspath_importer_cacher rpropertyrrrrrPrrbr;r@rDrrrrsp*;;^^--8)t&& DO(&$ L C +Arrc.tj|S)z} Deeply iterate all modules on the global python path. @param importPackages: Import packages as they are seen. r=) theSystemPathr@r=s rr@r@s  $ $N $ CCrc*tjS)zu Iterate all modules and top-level packages on the global Python path, but do not descend into packages. )rr;rDrrr;r;s  $ $ &&rct|S)z1 Retrieve a module from the system path. )r) moduleNames r getModulers  $$rrS)/rW __future__rrjrr zipimportos.pathrrrzope.interfacerrtwisted.python.compatr twisted.python.componentsr twisted.python.filepathr r twisted.python.reflectr twisted.python.zippathrrqrur,OPTIMIZED_MODEappendrr r"rYr.rrrrr zipimporterrrrr@r;rrDrrrsC 4l# 01.5=+- 8GDV$V$ U D$D$N6K6KrJ"(J"Z%6  $ && &$%  < Y224EF[A[A| D'%r