1 #=======================================================================
3 __version__
= '''0.0.19'''
4 __sub_version__
= '''20061124145335'''
5 __copyright__
= '''(c) Alex A. Naanou 2003'''
8 #-----------------------------------------------------------------------
10 ##from __future__ import generators
17 #-----------------------------------------------------------------------
19 PY_SUFFIXES
= imp
.get_suffixes()
22 #-----------------------------------------------------------------------
23 #-----------------------------------------------ImportDependencyError---
24 class ImportDependencyError(Exception):
30 #-----------------------------------------------------------------------
31 #--------------------------------------------------------_load_module---
32 # NOTE: this is a potential log/aspect point...
33 def _load_module(package_dir
, mod_name
, name_prefix
=None):
37 mod_legal_name
= name_prefix
in (None, '') \
38 and mod_name
or name_prefix
+ '.' + mod_name
41 # restrict the import path to avoid uncontrolled imports...
42 mod_dat
= imp
.find_module(mod_name
, [package_dir
])
43 # check if the module is loaded...
44 if mod_legal_name
in sys
.modules
:
45 return mod_name
, sys
.modules
[mod_name
]
47 ## module = imp.load_module(mod_name, *mod_dat)
48 module
= imp
.load_module(mod_legal_name
, *mod_dat
)
50 if len(mod_dat
) > 1 and mod_dat
[0] != None:
52 return mod_name
, module
54 # cleanup... (is this needed???)
55 if len(mod_dat
) > 1 and mod_dat
[0] != None:
60 #--------------------------------------------------ispythonimportable---
61 def ispythonimportable(package_dir
, name
):
63 this will test if the module name is importable from package_dir.
65 mod_path
= os
.path
.join(package_dir
, name
)
66 # is directory and contains __init__.py?
67 if os
.path
.isdir(mod_path
) and \
68 True in [ os
.path
.exists(os
.path
.join(mod_path
, '__init__' + ext
[0])) \
69 for ext
in PY_SUFFIXES
]:
72 # is file -> is .py[cod]...
73 return True in [ os
.path
.exists(os
.path
.join(mod_path
, ext
[0])) \
74 for ext
in PY_SUFFIXES
]
78 #---------------------------------------------------------packageiter---
79 def packageiter(package_dir
, disable_file
='disabled.txt', \
80 disabled_packages
=None, notimportable
=None, ignore_modules
=()):
83 This will return importable (and enabled) package names (without importing).
84 this will return the names of all packages/modules under a given path (package_dir),
85 not containing the "disabled.txt" file (disable_file), one per iteration.
87 optional side-effects:
88 disabled_packages : if given, will contain the names of disabled modules
89 (e.g. modules that contained the "disabled.txt" file
91 NOTE: the above two parameters MUST either be of list type or None.
93 # some sanity checks...
94 if disabled_packages
!= None and type(disabled_packages
) != list:
95 raise TypeError, 'disabled_packages must either be of list type or None (got type "%s").' % type(disabled_packages
)
96 if notimportable
!= None and type(notimportable
) != list:
97 raise TypeError, 'notimportable must either be of list type or None (got type "%s").' % type(notimportable
)
100 for mod
in os
.listdir(package_dir
):
102 ## if mod.startswith('__init__.'):
105 mod_name
= mod
.split('.', 1)[0]
107 if mod_name
in ignore_modules
:
109 # include each name only once...
110 if mod_name
not in loaded_packages
.keys() + ['']:
111 # skip disabled plugins...
112 if os
.path
.exists(os
.path
.join(package_dir
, mod_name
, disable_file
)):
113 if disabled_packages
!= None:
114 disabled_packages
+= [mod_name
]
116 if ispythonimportable(package_dir
, mod_name
):
118 elif notimportable
!= None:
119 notimportable
+= [mod_name
]
123 #---------------------------------------------------getpackagedepends---
124 def getpackagedepends(package_dir
, mod_name
, dependency_file
='depends.txt', forbidden_chars
=' -+=&*()^%$#@!~`,.'):
127 # see if the dependency file exists...
128 if not os
.path
.exists(os
.path
.join(package_dir
, mod_name
, dependency_file
)):
130 dep_file
= open(os
.path
.join(package_dir
, mod_name
, dependency_file
))
131 # parse dependency file...
132 deps
= [ s
.lstrip().split('#')[0].rstrip() \
134 if s
.split('#')[0].lstrip() != '' ]
136 # check for correctness...
137 if [ s
for s
in deps
if True in [ c
in s
for c
in forbidden_chars
] ]:
138 raise ImportDependencyError
, 'dependency file format error.'
143 #-----------------------------------------------------------------------
144 #---------------------------------------------------importpackageiter---
145 # TODO make this return more specific error data (e.g. name, exception,
147 def importpackageiter(package_dir
,\
148 disable_file
='disabled.txt',\
150 disabled_packages
=None,\
156 This is an import iterator.
157 this will import all packages/modules under a given path (package_dir),
158 not containing the "disabled.txt" file (disable_file), one per iteration, and
159 will return a tuple containing the module name and its object.
161 optional side-effects:
162 err_names : if given, will contain the names of modules that
163 generated ImportError.
164 disabled_packages : if given, will contain the names of disabled modules
165 (e.g. modules that contained the "disabled.txt" file
167 NOTE: the above two parameters MUST either be of list type or None.
169 # some sanity checks...
170 if err_names
!= None and type(err_names
) != list:
171 raise TypeError, 'err_names must either be of list type or None (got type "%s").' % type(err_names
)
173 for mod_name
in packageiter(package_dir
, disable_file
, disabled_packages
, notimportable
, ignore_modules
):
174 mod_name
, module
= _load_module(package_dir
, mod_name
, name_prefix
)
176 yield mod_name
, module
177 elif err_names
!= None:
178 err_names
+= [mod_name
]
181 #-------------------------------------------importdependspackagesiter---
182 # TODO make this a generic dependency checker (objutils ???)
183 def importdependspackagesiter(package_dir
,\
184 disable_file
='disabled.txt',\
185 dependency_file
='depends.txt',\
187 disabled_packages
=None,\
188 notimportable
=None, \
193 This will import the modules in order of dependency.
196 def _loaddependsiter(path
, name
, wait_lst
, loaded_packages
, err_names
=None):
199 if name
not in loaded_packages
:
200 name
, mod
= _load_module(path
, name
, name_prefix
)
201 if mod
== None and err_names
!= None:
204 loaded_packages
[name
] = mod
206 dependees
= wait_lst
.pop(name
, [])
207 for name
in dependees
:
208 # if module does not need anything else load
209 if [ m
for m
in wait_lst
.values() if name
in m
]:
212 for n
, m
in _loaddependsiter(path
, name
, wait_lst
, loaded_packages
, err_names
):
217 for mod_name
in packageiter(package_dir
, disable_file
, disabled_packages
, notimportable
, ignore_modules
):
219 deps
= getpackagedepends(package_dir
, mod_name
, dependency_file
)
220 # if all dependencies are loaded load package...
221 needs
= [ i
for i
in deps
if i
not in loaded_packages
]
222 # check if we depend on a faulty package...
223 err_needs
= [ i
for i
in needs
if i
in err_names
]
224 if err_names
!= None and err_names
:
225 raise ImportDependencyError
, 'failure in dependencies (failed: %s).' % err_names
230 wait_lst
[mod
] += [mod_name
]
232 wait_lst
[mod
] = [mod_name
]
234 for n
, m
in _loaddependsiter(package_dir
, mod_name
, wait_lst
, loaded_packages
, err_names
):
236 # check if the remainig data in wait list is looping deps...
238 # TODO do a more thorough check...
239 raise ImportDependencyError
, 'cyclic or unresolved demendencies in: %s.' % wait_lst
243 #=======================================================================
244 # vim:set ts=4 sw=4 nowrap :