Created
June 14, 2011 10:12
-
-
Save tomerfiliba/1024625 to your computer and use it in GitHub Desktop.
Nimp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Nested Imports Mechanism, a la Java | |
=================================== | |
Usage:: | |
import nimp | |
nimp.install() | |
# also, nimp.uninstall() | |
Suppose the following directory structure (under ``site-packages`` or so):: | |
com/ | |
__init__.py | |
com.ibm.xiv.xsf/ | |
host/ | |
__init__.py | |
__init__.py | |
com.ibm.xiv.xsf.common/ | |
__init__.py | |
com.ibm.xiv.scsy/ | |
__init__.py | |
device.py | |
[class Device] | |
the following imports will work as expected:: | |
import com # real module | |
import com.ibm # namespace module | |
import com.ibm.xiv # namespace module | |
import com.ibm.xiv.xsf # real module | |
import com.ibm.xiv.xsf.host # real module | |
import com.ibm.xiv.xsf.common # real module | |
from com.ibm.xiv.scsy.device import Device | |
""" | |
import os | |
import sys | |
import imp | |
class Nimp(object): | |
def __init__(self): | |
self.cache = {} | |
@staticmethod | |
def _get_name_parts(dotted_name): | |
i = -1 | |
while i is not None: | |
i = dotted_name.find(".", i+1) | |
if i < 0: | |
i = None | |
part = dotted_name[0:i] | |
yield part | |
def _find(self, fullname): | |
if fullname in self.cache: | |
return | |
for path in sys.path: | |
if not os.path.isdir(path): | |
continue | |
for fn in os.listdir(path): | |
fullpath = os.path.join(path, fn) | |
if not os.path.isdir(fullpath) or "." not in fn or not fn.startswith(fullname): | |
continue | |
for part in self._get_name_parts(fn): | |
fullpath = os.path.join(path, part) | |
if part in self.cache: | |
if os.path.exists(fullpath): | |
self.cache[part] = fullpath # namespace + real | |
else: | |
self.cache[part] = None # namespace | |
else: | |
self.cache[part] = fullpath # real | |
def find_module(self, fullname, path=None): | |
self._find(fullname) | |
if fullname in self.cache: | |
return self | |
else: | |
return None | |
def load_module(self, fullname): | |
if fullname in sys.modules: | |
return sys.modules[fullname] | |
path = self.cache[fullname] | |
if path is None: | |
mod = sys.modules[fullname] = imp.new_module(fullname) | |
mod.__file__ = "<namespace module>" | |
mod.__path__ = [] | |
else: | |
info = imp.find_module(fullname, [os.path.dirname(path)]) | |
mod = imp.load_module(fullname, *info) | |
sys.modules[fullname] = mod | |
return mod | |
# create Nimp singleton | |
Nimp = Nimp() | |
_installed = False | |
def install(): | |
global _installed | |
if _installed: | |
return | |
sys.meta_path.append(Nimp) | |
_installed = True | |
def uninstall(): | |
global _installed | |
if not _installed: | |
return | |
sys.meta_path.remove(Nimp) | |
_installed = False | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment