diff options
author | Marko Kreen | 2009-06-05 10:29:05 +0000 |
---|---|---|
committer | Marko Kreen | 2009-06-07 15:18:48 +0000 |
commit | 49e87a1c2e41ab613f0c383c8749066be92e14d2 (patch) | |
tree | 6da1eb793b1763c617d53ba86fe41008cd26c250 /python/pkgloader.py | |
parent | e9f032912997443878fdd70634ec644d73fef1c8 (diff) |
pkgloader module to be able to coexist with 2.x
Use scheme that pygtk uses to support parallel installations:
import pkgloader
pkgloader.require('skytools', '3.0')
import skytools
This will allow keeping old module installed by default and new
version is used only by request.
Diffstat (limited to 'python/pkgloader.py')
-rw-r--r-- | python/pkgloader.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/python/pkgloader.py b/python/pkgloader.py new file mode 100644 index 00000000..cf7fac87 --- /dev/null +++ b/python/pkgloader.py @@ -0,0 +1,89 @@ +"""Loader for Skytools modules. + +Primary idea is to allow several major versions to co-exists. +Secondary idea - allow checking minimal minor version. + +""" + +import sys, os, os.path, re + +__all__ = ['require'] + +_top = os.path.dirname(os.path.abspath(os.path.normpath(__file__))) + +_pkg_cache = None +_import_cache = {} +_pat = re.compile('^([a-z]+)-([0-9]+).([0-9]+)$') + +def _load_pkg_cache(): + global _pkg_cache + if _pkg_cache is not None: + return _pkg_cache + _pkg_cache = {} + for dir in os.listdir(_top): + m = _pat.match(dir) + if not m: + continue + modname = m.group(1) + modver = (int(m.group(2)), int(m.group(3))) + _pkg_cache.setdefault(modname, []).append((modver, dir)) + for vlist in _pkg_cache.itervalues(): + vlist.sort(reverse = True) + return _pkg_cache + +def _install_path(pkg, newpath): + for p in sys.path: + pname = os.path.basename(p) + m = _pat.match(pname) + if m and m.group(1) == pkg: + sys.path.remove(p) + sys.path.insert(0, newpath) + +def require(pkg, reqver): + # parse arg + reqval = tuple([int(n) for n in reqver.split('.')]) + need = reqval[:2] # cut minor ver + + # check if we already have one installed + if pkg in _import_cache: + got = _import_cache[pkg] + if need[0] != got[0] or reqval > got: + raise ImportError("Request for package '%s' ver '%s', have '%s'" % ( + pkg, reqver, '.'.join(_skytools_required_version))) + return + + # pick best ver from available ones + _pkg_cache = _load_pkg_cache() + if pkg not in _pkg_cache: + return + + for pkgver, pkgdir in _pkg_cache[pkg]: + if pkgver[0] == need[0] and pkgver >= need: + # install the best on + _install_path(pkg, os.path.join(_top, pkgdir)) + break + + # now import whatever is available + inst_ver = reqval + try: + mod = __import__(pkg) + ver_str = mod.__version__ + # check if it is actually useful + full_ver = tuple([int(x) for x in full_str.split('.')]) + if full_ver[0] != reqval[0] or reqval > full_ver: + raise ImportError("Request for Skytools ver '%s', got '%s'" % ( + reqver, full_str)) + raise ImportError("Request for package '%s' ver '%s', have '%s'" % ( + pkg, reqver, full_str)) + inst_ver = full_ver + except ImportError: + pass + except AttributeError: + pass + + # remember full version + _import_cache[pkg] = inst_ver + + return mod + + |