o b[h@sdZddlZddlZddlZddlZddlmZmZddl m Z ddl m Z m Z ddlmZddlmZddlmZmZdd lmZdd lmZeZd gZeduZerZed ned ddZddZGdddZ GdddZ!Gddde Z"Gddde Z#Gddde Z$e e$GdddZ%e%Z&e e$GdddZ'ee'ej(e$d d!Z)Gd"d#d#Z*e*Z+d+d%d&Z,d'd(Z-d)d*Z.dS),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} N)dirnamesplit)cast) Interface implementer nativeString)registerAdapter)FilePathUnlistableError)namedAny) ZipArchivez.pyz.pyoz.pyccCs t|}d|vod|vod|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 textStringr8/usr/lib/python3/dist-packages/twisted/python/modules.py_isPythonIdentifierWsrcCs |d}t|d}|dkS)Nr__init__)splitext splitpath)fpathextlessbasendrrr_isPackagePathcs  rc@sJeZdZdZddZdddZddZd d Zd d Zd dZ ddZ dS)_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 csTi}|js dS|D]}zt|}Wn ty!Yqw|D]}|d}|dt| }|t vrit |s@q$| |}| dddkrOq$||vrhd||<t |||}||kseJ|Vq$|sst |rs|stq$| |}t D](}|d|} | r||vrd||<t || |}||ksJ|Vnq}q$qdS)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$potentialTopLevelextpotentialBasenamemodnamepminitpyrrr iterModulesrsX       z!_ModuleIteratorHelper.iterModulesFccs,|V|D] }|j|dEdHqdS)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. importPackagesNr6 walkModulesr-r8packagerrrr:s  z!_ModuleIteratorHelper.walkModulescCs|S)z This is a hook to provide packages with the ability to specify their names as a prefix to submodules here. rr-mnrrrr(sz$_ModuleIteratorHelper._subModuleNamecCt)z Implement in subclasses to specify where to look for modules. @return: iterable of FilePath-like objects. NotImplementedErrorr-rrrr"sz#_ModuleIteratorHelper._packagePathscCr?)z Implement in subclasses to specify what path entry submodules will come from. @return: a PathEntry instance. r@rBrrrr*z_ModuleIteratorHelper._getEntrycCs.|D]}|j||kr|Sqt|)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. )r6namer(KeyError)r-r3modulerrr __getitem__s z!_ModuleIteratorHelper.__getitem__cCr?)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. r@rBrrr__iter__s z_ModuleIteratorHelper.__iter__NF) __name__ __module__ __qualname____doc__r6r:r(r"r*rGrHrrrrrks ;  rc@sBeZdZdZddZdefddZddZefd d Z d d Z d S)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. cCs||_||_||_||_dS)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)rDonObject_loaded pythonValue)r-rDrOloadedrQrrrrs  zPythonAttribute.__init__returncCd|jdS)NzPythonAttribute<>rDrBrrr__repr__zPythonAttribute.__repr__cC|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. )rPrBrrrisLoadedszPythonAttribute.isLoadedcCrY)z Load the value associated with this attribute. @return: an arbitrary Python object, or 'default' if there is an error loading it. )rQr-defaultrrrloadrCzPythonAttribute.loadccs8t|D]\}}t|jd||d|VqdS)NrT)inspect getmembersr]rNrDr-rDvalrrriterAttributes$szPythonAttribute.iterAttributesN) rJrKrLrMrstrrWrZ_nothingr]rbrrrrrNs  rNcseZdZdZddZddZdefddZd d Zd d Z d dZ e fddZ de defddZdfdd ZddZddZZS)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. cCs6t|}|dr J||_||_||_||_dS)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)rendswithrDr parent parentPath pathEntry)r-rDr rh_namerrrr6s    zPythonModule.__init__cCrYN)rhrBrrrr*FszPythonModule._getEntryrScCrT)zK Return a string representation including the module name. z PythonModule|}t|dr:|jD]$}||jjkr+|js&J|jVq|jj |}|r9|VqdSdS|jVdS)zZ Yield a sequence of FilePath-like objects which represent path segments. N__path__) rorZr]hasattrrzrgpathr!rhrl _smartPath)r-r]fnsmprrrr"s"     zPythonModule._packagePathsrI)rJrKrLrMrr*rcrWrZrbrordr]objectrtrvr:r(r" __classcell__rrrxrr))s  r)c@s6eZdZdZddZddZdefddZd d Zd S) PathEntryz 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. cCs||_||_dS)zE Create a PathEntry. This is a private constructor. N)r rl)r-r rlrrrrs zPathEntry.__init__cCs|SrjrrBrrrr*szPathEntry._getEntryrScCrT)Nz PathEntry\rz%PythonPath.__init__..)r_sysPathFactory_sysPathrm sysPathHooks importerCacherp)r-rrmrrrpsysPathFactoryrrrr,s/ zPythonPath.__init__cCs|S)zL Retrieve the current value of the module search path list. )rrBrrrrfzPythonPath.sysPathcCs|}d|jvr|jd|jddd}d|jvstt|jr+tt|j}nt|j}||jvrAt j d||jfdd|S)zl Determine where a given Python module object came from by looking at path entries. rNrzc%s (for module %s) not in path importer cache (PEP 302 violation - check your local configuration).) stacklevel) rJrmjoinrrr __file__rrwarningswarn)r-modobj topPackageObjrvalrrr_findEntryPathStringms"    zPythonPath._findEntryPathStringc Cs\|j|t}|tur&|jD]}z||}WqtyYqw|tur&d}t|t|S)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)rrnrdr ImportErrorr_theDefaultMapperr)r-pathNameimportrhookrrrr}s    zPythonPath._smartPathccs(|jD] }||}t||VqdS)zm Iterate the entries on my sysPath. @return: a generator yielding PathEntry objects N)rr}r)r-rfprrr iterEntriess   zPythonPath.iterEntriescCs|j|}|dur!t||||}||j}t|||Sd|vr5|}|dD]}||}q,|S|D] }|j |krD|Sq9t |)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. Nr) rmrnrr}rrr)rr6rDrE)r-r3 moduleObjectpemppkgrDrFrrrrGs"      zPythonPath.__getitem__cCs&z||WdStyYdSw)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)rGrE)r-rFrrr __contains__s   zPythonPath.__contains__rScCsd|jd|jdS)zO Display my sysPath and moduleDict in a string representation. z PythonPath(,))rrmrBrrrrWszPythonPath.__repr__ccs"|D] }|EdHqdS)z< Yield all top-level modules on my sysPath. N)rr6)r-entryrrrr6s zPythonPath.iterModulesFccs&|D] }|jddEdHqdS)z Similar to L{iterModules}, this yields every module on the path, then every submodule in each package or entry. Fr7Nr9r;rrrr:s zPythonPath.walkModulesrI)rJrKrLrMrmodules path_hookspath_importer_cacher rpropertyrrr}rrGrrcrWr6r:rrrrrs& : " & rFcCs tj|dS)z} Deeply iterate all modules on the global python path. @param importPackages: Import packages as they are seen. r7) theSystemPathr:r7rrrr:s r:cCstS)zu Iterate all modules and top-level packages on the global Python path, but do not descend into packages. )rr6rrrrr6rr6cCst|S)z1 Retrieve a module from the system path. )r) moduleNamerrr getModule srrI)/rMr^rr zipimportos.pathrrrtypingrzope.interfacerrtwisted.python.compatrtwisted.python.componentsr twisted.python.filepathr r twisted.python.reflectr twisted.python.zippathr rrdr'OPTIMIZED_MODEappendrrrrNr)rrrrr zipimporterrrrr:r6rrrrrsR7        7  _