Skip to content

Instantly share code, notes, and snippets.

@tomerfiliba
Created June 14, 2011 10:12
Show Gist options
  • Save tomerfiliba/1024625 to your computer and use it in GitHub Desktop.
Save tomerfiliba/1024625 to your computer and use it in GitHub Desktop.
Nimp
"""
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