Commit | Line | Data |
---|---|---|
920dae64 AT |
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 | ||
36 | _packs = {} # {pack: [pathname, ...], ...} | |
37 | ||
38 | def 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 | ||
60 | def _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 |