diff options
author | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2012-08-27 20:48:15 -0400 |
---|---|---|
committer | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2012-08-27 21:00:37 -0400 |
commit | 9d4f01972775eb6c601f5a7f55715002df2fecb1 (patch) | |
tree | 76d50c71915e19767495301abb34fed42ac3a1a4 /src/lib/Bcfg2/Compat.py | |
parent | c07cc475cbafec24e747d6907f3bf7257e441934 (diff) | |
download | bcfg2-9d4f01972775eb6c601f5a7f55715002df2fecb1.tar.gz bcfg2-9d4f01972775eb6c601f5a7f55715002df2fecb1.tar.bz2 bcfg2-9d4f01972775eb6c601f5a7f55715002df2fecb1.zip |
added better common walk_packages implementation for python 2.4 and 2.5
Conflicts:
src/lib/Bcfg2/Client/Tools/__init__.py
Diffstat (limited to 'src/lib/Bcfg2/Compat.py')
-rw-r--r-- | src/lib/Bcfg2/Compat.py | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Compat.py b/src/lib/Bcfg2/Compat.py index be3954f3b..6551ffc40 100644 --- a/src/lib/Bcfg2/Compat.py +++ b/src/lib/Bcfg2/Compat.py @@ -132,3 +132,84 @@ class CmpMixin(object): def __le__(self, other): return self.__lt__(other) or self.__eq__(other) + +try: + from pkgutil import walk_packages +except ImportError: + try: + from pkgutil import iter_modules + # iter_modules was added in python 2.5; use it to get an exact + # re-implementation of walk_packages if possible + def walk_packages(path=None, prefix='', onerror=None): + def seen(p, m={}): + if p in m: + return True + m[p] = True + + for importer, name, ispkg in iter_modules(path, prefix): + yield importer, name, ispkg + + if ispkg: + try: + __import__(name) + except ImportError: + if onerror is not None: + onerror(name) + except Exception: + if onerror is not None: + onerror(name) + else: + raise + else: + path = getattr(sys.modules[name], '__path__', []) + + # don't traverse path items we've seen before + path = [p for p in path if not seen(p)] + + for item in walk_packages(path, name + '.', onerror): + yield item + except ImportError: + def walk_packages(path=None, prefix='', onerror=None): + """ imperfect, incomplete implementation of + walk_packages() for python 2.4. Differences: + + * requires a full path, not a path relative to something + in sys.path. anywhere we care about that shouldn't be + an issue + + * the first element of each tuple is None instead of an + importer object + """ + def seen(p, m={}): + if p in m: + return True + m[p] = True + + if path is None: + path = sys.path + rv = [] + for mpath in path: + for fname in os.listdir(mpath): + fpath = os.path.join(mpath, fname) + if (os.path.isfile(fpath) and fname.endswith(".py") and + fname != '__init__.py'): + yield None, prefix + fname[:-3], False + elif os.path.isdir(fpath): + mname = prefix + fname + if os.path.exists(os.path.join(fpath, "__init__.py")): + yield None, mname, True + try: + __import__(mname) + except ImportError: + if onerror is not None: + onerror(mname) + except Exception: + if onerror is not None: + onerror(mname) + else: + raise + else: + for item in walk_packages([fpath], + prefix=mname + '.', + onerror=onerror): + yield item |