modules.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. # -*- test-case-name: twisted.test.test_modules -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. This module aims to provide a unified, object-oriented view of Python's
  6. runtime hierarchy.
  7. Python is a very dynamic language with wide variety of introspection utilities.
  8. However, these utilities can be hard to use, because there is no consistent
  9. API. The introspection API in python is made up of attributes (__name__,
  10. __module__, func_name, etc) on instances, modules, classes and functions which
  11. vary between those four types, utility modules such as 'inspect' which provide
  12. some functionality, the 'imp' module, the "compiler" module, the semantics of
  13. PEP 302 support, and setuptools, among other things.
  14. At the top, you have "PythonPath", an abstract representation of sys.path which
  15. includes methods to locate top-level modules, with or without loading them.
  16. The top-level exposed functions in this module for accessing the system path
  17. are "walkModules", "iterModules", and "getModule".
  18. From most to least specific, here are the objects provided::
  19. PythonPath # sys.path
  20. |
  21. v
  22. PathEntry # one entry on sys.path: an importer
  23. |
  24. v
  25. PythonModule # a module or package that can be loaded
  26. |
  27. v
  28. PythonAttribute # an attribute of a module (function or class)
  29. |
  30. v
  31. PythonAttribute # an attribute of a function or class
  32. |
  33. v
  34. ...
  35. Here's an example of idiomatic usage: this is what you would do to list all of
  36. the modules outside the standard library's python-files directory::
  37. import os
  38. stdlibdir = os.path.dirname(os.__file__)
  39. from twisted.python.modules import iterModules
  40. for modinfo in iterModules():
  41. if (modinfo.pathEntry.filePath.path != stdlibdir
  42. and not modinfo.isPackage()):
  43. print('unpackaged: %s: %s' % (
  44. modinfo.name, modinfo.filePath.path))
  45. @var theSystemPath: The very top of the Python object space.
  46. @type: L{PythonPath}
  47. """
  48. from __future__ import division, absolute_import, print_function
  49. __metaclass__ = type
  50. # let's try to keep path imports to a minimum...
  51. from os.path import dirname, split as splitpath
  52. import sys
  53. import inspect
  54. import warnings
  55. import zipimport
  56. from zope.interface import Interface, implementer
  57. from twisted.python.compat import nativeString
  58. from twisted.python.components import registerAdapter
  59. from twisted.python.filepath import FilePath, UnlistableError
  60. from twisted.python.reflect import namedAny
  61. from twisted.python.zippath import ZipArchive
  62. _nothing = object()
  63. PYTHON_EXTENSIONS = ['.py']
  64. OPTIMIZED_MODE = __doc__ is None
  65. if OPTIMIZED_MODE:
  66. PYTHON_EXTENSIONS.append('.pyo')
  67. else:
  68. PYTHON_EXTENSIONS.append('.pyc')
  69. def _isPythonIdentifier(string):
  70. """
  71. cheezy fake test for proper identifier-ness.
  72. @param string: a L{str} which might or might not be a valid python
  73. identifier.
  74. @return: True or False
  75. """
  76. textString = nativeString(string)
  77. return (' ' not in textString and
  78. '.' not in textString and
  79. '-' not in textString)
  80. def _isPackagePath(fpath):
  81. # Determine if a FilePath-like object is a Python package. TODO: deal with
  82. # __init__module.(so|dll|pyd)?
  83. extless = fpath.splitext()[0]
  84. basend = splitpath(extless)[1]
  85. return basend == "__init__"
  86. class _ModuleIteratorHelper:
  87. """
  88. This mixin provides common behavior between python module and path entries,
  89. since the mechanism for searching sys.path and __path__ attributes is
  90. remarkably similar.
  91. """
  92. def iterModules(self):
  93. """
  94. Loop over the modules present below this entry or package on PYTHONPATH.
  95. For modules which are not packages, this will yield nothing.
  96. For packages and path entries, this will only yield modules one level
  97. down; i.e. if there is a package a.b.c, iterModules on a will only
  98. return a.b. If you want to descend deeply, use walkModules.
  99. @return: a generator which yields PythonModule instances that describe
  100. modules which can be, or have been, imported.
  101. """
  102. yielded = {}
  103. if not self.filePath.exists():
  104. return
  105. for placeToLook in self._packagePaths():
  106. try:
  107. children = sorted(placeToLook.children())
  108. except UnlistableError:
  109. continue
  110. for potentialTopLevel in children:
  111. ext = potentialTopLevel.splitext()[1]
  112. potentialBasename = potentialTopLevel.basename()[:-len(ext)]
  113. if ext in PYTHON_EXTENSIONS:
  114. # TODO: this should be a little choosier about which path entry
  115. # it selects first, and it should do all the .so checking and
  116. # crud
  117. if not _isPythonIdentifier(potentialBasename):
  118. continue
  119. modname = self._subModuleName(potentialBasename)
  120. if modname.split(".")[-1] == '__init__':
  121. # This marks the directory as a package so it can't be
  122. # a module.
  123. continue
  124. if modname not in yielded:
  125. yielded[modname] = True
  126. pm = PythonModule(modname, potentialTopLevel, self._getEntry())
  127. assert pm != self
  128. yield pm
  129. else:
  130. if (ext or not _isPythonIdentifier(potentialBasename)
  131. or not potentialTopLevel.isdir()):
  132. continue
  133. modname = self._subModuleName(potentialTopLevel.basename())
  134. for ext in PYTHON_EXTENSIONS:
  135. initpy = potentialTopLevel.child("__init__"+ext)
  136. if initpy.exists() and modname not in yielded:
  137. yielded[modname] = True
  138. pm = PythonModule(modname, initpy, self._getEntry())
  139. assert pm != self
  140. yield pm
  141. break
  142. def walkModules(self, importPackages=False):
  143. """
  144. Similar to L{iterModules}, this yields self, and then every module in my
  145. package or entry, and every submodule in each package or entry.
  146. In other words, this is deep, and L{iterModules} is shallow.
  147. """
  148. yield self
  149. for package in self.iterModules():
  150. for module in package.walkModules(importPackages=importPackages):
  151. yield module
  152. def _subModuleName(self, mn):
  153. """
  154. This is a hook to provide packages with the ability to specify their names
  155. as a prefix to submodules here.
  156. """
  157. return mn
  158. def _packagePaths(self):
  159. """
  160. Implement in subclasses to specify where to look for modules.
  161. @return: iterable of FilePath-like objects.
  162. """
  163. raise NotImplementedError()
  164. def _getEntry(self):
  165. """
  166. Implement in subclasses to specify what path entry submodules will come
  167. from.
  168. @return: a PathEntry instance.
  169. """
  170. raise NotImplementedError()
  171. def __getitem__(self, modname):
  172. """
  173. Retrieve a module from below this path or package.
  174. @param modname: a str naming a module to be loaded. For entries, this
  175. is a top-level, undotted package name, and for packages it is the name
  176. of the module without the package prefix. For example, if you have a
  177. PythonModule representing the 'twisted' package, you could use::
  178. twistedPackageObj['python']['modules']
  179. to retrieve this module.
  180. @raise: KeyError if the module is not found.
  181. @return: a PythonModule.
  182. """
  183. for module in self.iterModules():
  184. if module.name == self._subModuleName(modname):
  185. return module
  186. raise KeyError(modname)
  187. def __iter__(self):
  188. """
  189. Implemented to raise NotImplementedError for clarity, so that attempting to
  190. loop over this object won't call __getitem__.
  191. Note: in the future there might be some sensible default for iteration,
  192. like 'walkEverything', so this is deliberately untested and undefined
  193. behavior.
  194. """
  195. raise NotImplementedError()
  196. class PythonAttribute:
  197. """
  198. I represent a function, class, or other object that is present.
  199. @ivar name: the fully-qualified python name of this attribute.
  200. @ivar onObject: a reference to a PythonModule or other PythonAttribute that
  201. is this attribute's logical parent.
  202. @ivar name: the fully qualified python name of the attribute represented by
  203. this class.
  204. """
  205. def __init__(self, name, onObject, loaded, pythonValue):
  206. """
  207. Create a PythonAttribute. This is a private constructor. Do not construct
  208. me directly, use PythonModule.iterAttributes.
  209. @param name: the FQPN
  210. @param onObject: see ivar
  211. @param loaded: always True, for now
  212. @param pythonValue: the value of the attribute we're pointing to.
  213. """
  214. self.name = name
  215. self.onObject = onObject
  216. self._loaded = loaded
  217. self.pythonValue = pythonValue
  218. def __repr__(self):
  219. return 'PythonAttribute<%r>'%(self.name,)
  220. def isLoaded(self):
  221. """
  222. Return a boolean describing whether the attribute this describes has
  223. actually been loaded into memory by importing its module.
  224. Note: this currently always returns true; there is no Python parser
  225. support in this module yet.
  226. """
  227. return self._loaded
  228. def load(self, default=_nothing):
  229. """
  230. Load the value associated with this attribute.
  231. @return: an arbitrary Python object, or 'default' if there is an error
  232. loading it.
  233. """
  234. return self.pythonValue
  235. def iterAttributes(self):
  236. for name, val in inspect.getmembers(self.load()):
  237. yield PythonAttribute(self.name+'.'+name, self, True, val)
  238. class PythonModule(_ModuleIteratorHelper):
  239. """
  240. Representation of a module which could be imported from sys.path.
  241. @ivar name: the fully qualified python name of this module.
  242. @ivar filePath: a FilePath-like object which points to the location of this
  243. module.
  244. @ivar pathEntry: a L{PathEntry} instance which this module was located
  245. from.
  246. """
  247. def __init__(self, name, filePath, pathEntry):
  248. """
  249. Create a PythonModule. Do not construct this directly, instead inspect a
  250. PythonPath or other PythonModule instances.
  251. @param name: see ivar
  252. @param filePath: see ivar
  253. @param pathEntry: see ivar
  254. """
  255. _name = nativeString(name)
  256. assert not _name.endswith(".__init__")
  257. self.name = _name
  258. self.filePath = filePath
  259. self.parentPath = filePath.parent()
  260. self.pathEntry = pathEntry
  261. def _getEntry(self):
  262. return self.pathEntry
  263. def __repr__(self):
  264. """
  265. Return a string representation including the module name.
  266. """
  267. return 'PythonModule<%r>' % (self.name,)
  268. def isLoaded(self):
  269. """
  270. Determine if the module is loaded into sys.modules.
  271. @return: a boolean: true if loaded, false if not.
  272. """
  273. return self.pathEntry.pythonPath.moduleDict.get(self.name) is not None
  274. def iterAttributes(self):
  275. """
  276. List all the attributes defined in this module.
  277. Note: Future work is planned here to make it possible to list python
  278. attributes on a module without loading the module by inspecting ASTs or
  279. bytecode, but currently any iteration of PythonModule objects insists
  280. they must be loaded, and will use inspect.getmodule.
  281. @raise NotImplementedError: if this module is not loaded.
  282. @return: a generator yielding PythonAttribute instances describing the
  283. attributes of this module.
  284. """
  285. if not self.isLoaded():
  286. raise NotImplementedError(
  287. "You can't load attributes from non-loaded modules yet.")
  288. for name, val in inspect.getmembers(self.load()):
  289. yield PythonAttribute(self.name+'.'+name, self, True, val)
  290. def isPackage(self):
  291. """
  292. Returns true if this module is also a package, and might yield something
  293. from iterModules.
  294. """
  295. return _isPackagePath(self.filePath)
  296. def load(self, default=_nothing):
  297. """
  298. Load this module.
  299. @param default: if specified, the value to return in case of an error.
  300. @return: a genuine python module.
  301. @raise: any type of exception. Importing modules is a risky business;
  302. the erorrs of any code run at module scope may be raised from here, as
  303. well as ImportError if something bizarre happened to the system path
  304. between the discovery of this PythonModule object and the attempt to
  305. import it. If you specify a default, the error will be swallowed
  306. entirely, and not logged.
  307. @rtype: types.ModuleType.
  308. """
  309. try:
  310. return self.pathEntry.pythonPath.moduleLoader(self.name)
  311. except: # this needs more thought...
  312. if default is not _nothing:
  313. return default
  314. raise
  315. def __eq__(self, other):
  316. """
  317. PythonModules with the same name are equal.
  318. """
  319. if not isinstance(other, PythonModule):
  320. return False
  321. return other.name == self.name
  322. def __ne__(self, other):
  323. """
  324. PythonModules with different names are not equal.
  325. """
  326. if not isinstance(other, PythonModule):
  327. return True
  328. return other.name != self.name
  329. def walkModules(self, importPackages=False):
  330. if importPackages and self.isPackage():
  331. self.load()
  332. return super(PythonModule, self).walkModules(importPackages=importPackages)
  333. def _subModuleName(self, mn):
  334. """
  335. submodules of this module are prefixed with our name.
  336. """
  337. return self.name + '.' + mn
  338. def _packagePaths(self):
  339. """
  340. Yield a sequence of FilePath-like objects which represent path segments.
  341. """
  342. if not self.isPackage():
  343. return
  344. if self.isLoaded():
  345. load = self.load()
  346. if hasattr(load, '__path__'):
  347. for fn in load.__path__:
  348. if fn == self.parentPath.path:
  349. # this should _really_ exist.
  350. assert self.parentPath.exists()
  351. yield self.parentPath
  352. else:
  353. smp = self.pathEntry.pythonPath._smartPath(fn)
  354. if smp.exists():
  355. yield smp
  356. else:
  357. yield self.parentPath
  358. class PathEntry(_ModuleIteratorHelper):
  359. """
  360. I am a proxy for a single entry on sys.path.
  361. @ivar filePath: a FilePath-like object pointing at the filesystem location
  362. or archive file where this path entry is stored.
  363. @ivar pythonPath: a PythonPath instance.
  364. """
  365. def __init__(self, filePath, pythonPath):
  366. """
  367. Create a PathEntry. This is a private constructor.
  368. """
  369. self.filePath = filePath
  370. self.pythonPath = pythonPath
  371. def _getEntry(self):
  372. return self
  373. def __repr__(self):
  374. return 'PathEntry<%r>' % (self.filePath,)
  375. def _packagePaths(self):
  376. yield self.filePath
  377. class IPathImportMapper(Interface):
  378. """
  379. This is an internal interface, used to map importers to factories for
  380. FilePath-like objects.
  381. """
  382. def mapPath(self, pathLikeString):
  383. """
  384. Return a FilePath-like object.
  385. @param pathLikeString: a path-like string, like one that might be
  386. passed to an import hook.
  387. @return: a L{FilePath}, or something like it (currently only a
  388. L{ZipPath}, but more might be added later).
  389. """
  390. @implementer(IPathImportMapper)
  391. class _DefaultMapImpl:
  392. """ Wrapper for the default importer, i.e. None. """
  393. def mapPath(self, fsPathString):
  394. return FilePath(fsPathString)
  395. _theDefaultMapper = _DefaultMapImpl()
  396. @implementer(IPathImportMapper)
  397. class _ZipMapImpl:
  398. """ IPathImportMapper implementation for zipimport.ZipImporter. """
  399. def __init__(self, importer):
  400. self.importer = importer
  401. def mapPath(self, fsPathString):
  402. """
  403. Map the given FS path to a ZipPath, by looking at the ZipImporter's
  404. "archive" attribute and using it as our ZipArchive root, then walking
  405. down into the archive from there.
  406. @return: a L{zippath.ZipPath} or L{zippath.ZipArchive} instance.
  407. """
  408. za = ZipArchive(self.importer.archive)
  409. myPath = FilePath(self.importer.archive)
  410. itsPath = FilePath(fsPathString)
  411. if myPath == itsPath:
  412. return za
  413. # This is NOT a general-purpose rule for sys.path or __file__:
  414. # zipimport specifically uses regular OS path syntax in its
  415. # pathnames, even though zip files specify that slashes are always
  416. # the separator, regardless of platform.
  417. segs = itsPath.segmentsFrom(myPath)
  418. zp = za
  419. for seg in segs:
  420. zp = zp.child(seg)
  421. return zp
  422. registerAdapter(_ZipMapImpl, zipimport.zipimporter, IPathImportMapper)
  423. def _defaultSysPathFactory():
  424. """
  425. Provide the default behavior of PythonPath's sys.path factory, which is to
  426. return the current value of sys.path.
  427. @return: L{sys.path}
  428. """
  429. return sys.path
  430. class PythonPath:
  431. """
  432. I represent the very top of the Python object-space, the module list in
  433. C{sys.path} and the modules list in C{sys.modules}.
  434. @ivar _sysPath: A sequence of strings like C{sys.path}. This attribute is
  435. read-only.
  436. @ivar sysPath: The current value of the module search path list.
  437. @type sysPath: C{list}
  438. @ivar moduleDict: A dictionary mapping string module names to module
  439. objects, like C{sys.modules}.
  440. @ivar sysPathHooks: A list of PEP-302 path hooks, like C{sys.path_hooks}.
  441. @ivar moduleLoader: A function that takes a fully-qualified python name and
  442. returns a module, like L{twisted.python.reflect.namedAny}.
  443. """
  444. def __init__(self,
  445. sysPath=None,
  446. moduleDict=sys.modules,
  447. sysPathHooks=sys.path_hooks,
  448. importerCache=sys.path_importer_cache,
  449. moduleLoader=namedAny,
  450. sysPathFactory=None):
  451. """
  452. Create a PythonPath. You almost certainly want to use
  453. modules.theSystemPath, or its aliased methods, rather than creating a
  454. new instance yourself, though.
  455. All parameters are optional, and if unspecified, will use 'system'
  456. equivalents that makes this PythonPath like the global L{theSystemPath}
  457. instance.
  458. @param sysPath: a sys.path-like list to use for this PythonPath, to
  459. specify where to load modules from.
  460. @param moduleDict: a sys.modules-like dictionary to use for keeping
  461. track of what modules this PythonPath has loaded.
  462. @param sysPathHooks: sys.path_hooks-like list of PEP-302 path hooks to
  463. be used for this PythonPath, to determie which importers should be
  464. used.
  465. @param importerCache: a sys.path_importer_cache-like list of PEP-302
  466. importers. This will be used in conjunction with the given
  467. sysPathHooks.
  468. @param moduleLoader: a module loader function which takes a string and
  469. returns a module. That is to say, it is like L{namedAny} - *not* like
  470. L{__import__}.
  471. @param sysPathFactory: a 0-argument callable which returns the current
  472. value of a sys.path-like list of strings. Specify either this, or
  473. sysPath, not both. This alternative interface is provided because the
  474. way the Python import mechanism works, you can re-bind the 'sys.path'
  475. name and that is what is used for current imports, so it must be a
  476. factory rather than a value to deal with modification by rebinding
  477. rather than modification by mutation. Note: it is not recommended to
  478. rebind sys.path. Although this mechanism can deal with that, it is a
  479. subtle point which some tools that it is easy for tools which interact
  480. with sys.path to miss.
  481. """
  482. if sysPath is not None:
  483. sysPathFactory = lambda : sysPath
  484. elif sysPathFactory is None:
  485. sysPathFactory = _defaultSysPathFactory
  486. self._sysPathFactory = sysPathFactory
  487. self._sysPath = sysPath
  488. self.moduleDict = moduleDict
  489. self.sysPathHooks = sysPathHooks
  490. self.importerCache = importerCache
  491. self.moduleLoader = moduleLoader
  492. def _getSysPath(self):
  493. """
  494. Retrieve the current value of the module search path list.
  495. """
  496. return self._sysPathFactory()
  497. sysPath = property(_getSysPath)
  498. def _findEntryPathString(self, modobj):
  499. """
  500. Determine where a given Python module object came from by looking at path
  501. entries.
  502. """
  503. topPackageObj = modobj
  504. while '.' in topPackageObj.__name__:
  505. topPackageObj = self.moduleDict['.'.join(
  506. topPackageObj.__name__.split('.')[:-1])]
  507. if _isPackagePath(FilePath(topPackageObj.__file__)):
  508. # if package 'foo' is on sys.path at /a/b/foo, package 'foo's
  509. # __file__ will be /a/b/foo/__init__.py, and we are looking for
  510. # /a/b here, the path-entry; so go up two steps.
  511. rval = dirname(dirname(topPackageObj.__file__))
  512. else:
  513. # the module is completely top-level, not within any packages. The
  514. # path entry it's on is just its dirname.
  515. rval = dirname(topPackageObj.__file__)
  516. # There are probably some awful tricks that an importer could pull
  517. # which would break this, so let's just make sure... it's a loaded
  518. # module after all, which means that its path MUST be in
  519. # path_importer_cache according to PEP 302 -glyph
  520. if rval not in self.importerCache:
  521. warnings.warn(
  522. "%s (for module %s) not in path importer cache "
  523. "(PEP 302 violation - check your local configuration)." % (
  524. rval, modobj.__name__),
  525. stacklevel=3)
  526. return rval
  527. def _smartPath(self, pathName):
  528. """
  529. Given a path entry from sys.path which may refer to an importer,
  530. return the appropriate FilePath-like instance.
  531. @param pathName: a str describing the path.
  532. @return: a FilePath-like object.
  533. """
  534. importr = self.importerCache.get(pathName, _nothing)
  535. if importr is _nothing:
  536. for hook in self.sysPathHooks:
  537. try:
  538. importr = hook(pathName)
  539. except ImportError:
  540. pass
  541. if importr is _nothing: # still
  542. importr = None
  543. return IPathImportMapper(importr, _theDefaultMapper).mapPath(pathName)
  544. def iterEntries(self):
  545. """
  546. Iterate the entries on my sysPath.
  547. @return: a generator yielding PathEntry objects
  548. """
  549. for pathName in self.sysPath:
  550. fp = self._smartPath(pathName)
  551. yield PathEntry(fp, self)
  552. def __getitem__(self, modname):
  553. """
  554. Get a python module by its given fully-qualified name.
  555. @param modname: The fully-qualified Python module name to load.
  556. @type modname: C{str}
  557. @return: an object representing the module identified by C{modname}
  558. @rtype: L{PythonModule}
  559. @raise KeyError: if the module name is not a valid module name, or no
  560. such module can be identified as loadable.
  561. """
  562. # See if the module is already somewhere in Python-land.
  563. moduleObject = self.moduleDict.get(modname)
  564. if moduleObject is not None:
  565. # we need 2 paths; one of the path entry and one for the module.
  566. pe = PathEntry(
  567. self._smartPath(
  568. self._findEntryPathString(moduleObject)),
  569. self)
  570. mp = self._smartPath(moduleObject.__file__)
  571. return PythonModule(modname, mp, pe)
  572. # Recurse if we're trying to get a submodule.
  573. if '.' in modname:
  574. pkg = self
  575. for name in modname.split('.'):
  576. pkg = pkg[name]
  577. return pkg
  578. # Finally do the slowest possible thing and iterate
  579. for module in self.iterModules():
  580. if module.name == modname:
  581. return module
  582. raise KeyError(modname)
  583. def __contains__(self, module):
  584. """
  585. Check to see whether or not a module exists on my import path.
  586. @param module: The name of the module to look for on my import path.
  587. @type module: C{str}
  588. """
  589. try:
  590. self.__getitem__(module)
  591. return True
  592. except KeyError:
  593. return False
  594. def __repr__(self):
  595. """
  596. Display my sysPath and moduleDict in a string representation.
  597. """
  598. return "PythonPath(%r,%r)" % (self.sysPath, self.moduleDict)
  599. def iterModules(self):
  600. """
  601. Yield all top-level modules on my sysPath.
  602. """
  603. for entry in self.iterEntries():
  604. for module in entry.iterModules():
  605. yield module
  606. def walkModules(self, importPackages=False):
  607. """
  608. Similar to L{iterModules}, this yields every module on the path, then every
  609. submodule in each package or entry.
  610. """
  611. for package in self.iterModules():
  612. for module in package.walkModules(importPackages=False):
  613. yield module
  614. theSystemPath = PythonPath()
  615. def walkModules(importPackages=False):
  616. """
  617. Deeply iterate all modules on the global python path.
  618. @param importPackages: Import packages as they are seen.
  619. """
  620. return theSystemPath.walkModules(importPackages=importPackages)
  621. def iterModules():
  622. """
  623. Iterate all modules and top-level packages on the global Python path, but
  624. do not descend into packages.
  625. @param importPackages: Import packages as they are seen.
  626. """
  627. return theSystemPath.iterModules()
  628. def getModule(moduleName):
  629. """
  630. Retrieve a module from the system path.
  631. """
  632. return theSystemPath[moduleName]