blob: 3d09236ba982bed967c109f59cbb9f1dee87743d [file] [log] [blame]
Guido van Rossumd1df83b1994-03-07 11:45:36 +00001# 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
36_packs = {} # {pack: [pathname, ...], ...}
37
38def addpack(pack, *locations):
39 import os
40 if os.path.isabs(pack):
41 base = os.path.basename(pack)
42 else:
43 base = pack
44 if _packs.has_key(base):
45 return
46 import sys
47 path = []
48 for loc in _flatten(locations) + sys.path:
49 fn = os.path.join(loc, base)
50 if fn not in path and os.path.isdir(fn):
51 path.append(fn)
52 if pack != base and pack not in path and os.path.isdir(pack):
53 path.append(pack)
54 if not path: raise ImportError, 'package ' + pack + ' not found'
55 _packs[base] = path
56 for fn in path:
57 if fn not in sys.path:
58 sys.path.append(fn)
59
60def _flatten(locations):
61 locs = []
62 for loc in locations:
63 if type(loc) == type(''):
64 locs.append(loc)
65 else:
66 locs = locs + _flatten(loc)
67 return locs