addpack.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # This module provides standard support for "packages".
  2. #
  3. # The idea is that large groups of related modules can be placed in
  4. # their own subdirectory, which can be added to the Python search path
  5. # in a relatively easy way.
  6. #
  7. # The current version takes a package name and searches the Python
  8. # search path for a directory by that name, and if found adds it to
  9. # the module search path (sys.path). It maintains a list of packages
  10. # that have already been added so adding the same package many times
  11. # is OK.
  12. #
  13. # It is intended to be used in a fairly stylized manner: each module
  14. # that wants to use a particular package, say 'Foo', is supposed to
  15. # contain the following code:
  16. #
  17. # from addpack import addpack
  18. # addpack('Foo')
  19. # <import modules from package Foo>
  20. #
  21. # Additional arguments, when present, provide additional places where
  22. # to look for the package before trying sys.path (these may be either
  23. # strings or lists/tuples of strings). Also, if the package name is a
  24. # full pathname, first the last component is tried in the usual way,
  25. # then the full pathname is tried last. If the package name is a
  26. # *relative* pathname (UNIX: contains a slash but doesn't start with
  27. # one), then nothing special is done. The packages "/foo/bar/bletch"
  28. # and "bletch" are considered the same, but unrelated to "bar/bletch".
  29. #
  30. # If the algorithm finds more than one suitable subdirectory, all are
  31. # added to the search path -- this makes it possible to override part
  32. # of a package. The same path will not be added more than once.
  33. #
  34. # If no directory is found, ImportError is raised.
  35. _packs = {} # {pack: [pathname, ...], ...}
  36. def addpack(pack, *locations):
  37. import os
  38. if os.path.isabs(pack):
  39. base = os.path.basename(pack)
  40. else:
  41. base = pack
  42. if _packs.has_key(base):
  43. return
  44. import sys
  45. path = []
  46. for loc in _flatten(locations) + sys.path:
  47. fn = os.path.join(loc, base)
  48. if fn not in path and os.path.isdir(fn):
  49. path.append(fn)
  50. if pack != base and pack not in path and os.path.isdir(pack):
  51. path.append(pack)
  52. if not path: raise ImportError, 'package ' + pack + ' not found'
  53. _packs[base] = path
  54. for fn in path:
  55. if fn not in sys.path:
  56. sys.path.append(fn)
  57. def _flatten(locations):
  58. locs = []
  59. for loc in locations:
  60. if type(loc) == type(''):
  61. locs.append(loc)
  62. else:
  63. locs = locs + _flatten(loc)
  64. return locs