Skip to content

Instantly share code, notes, and snippets.

@aliles
Created August 12, 2014 12:27
Show Gist options
  • Save aliles/9bb375a9f889c2e584b5 to your computer and use it in GitHub Desktop.
Save aliles/9bb375a9f889c2e584b5 to your computer and use it in GitHub Desktop.
PEP 302 import hook to caching system path contents
"""PEP 302 import hook to caching system path contents.
Implements an import hook using a finder and loader class to load Python
modules from system paths while caching the path contents.
"""
from __future__ import print_function
import glob
import imp
import os
import sys
class CachingLoader(object):
"""Import hook loader.
Used by the CachingFinder class. Implemented using the imp module.
"""
def __init__(self, fobject, pathname, description):
self.fobject = fobject
self.pathname = pathname
self.description = description
def load_module(self, fullname):
"Import hook protocol."
try:
print('CachingLoader loading "{0}"'.format(fullname))
return imp.load_module(fullname, self.fobject, self,pathname, self.description)
finally:
if hasattr(self.fobject, 'close'):
self.fobject.close()
class CachingFinder(object):
"""Import hook loader with directory caching.
Finds modules to load using the CachingLoader. Directory listings from
systems paths are cached so they don't require repeated enumeration.
NOTE: Limited to Python modules only.
"""
SUFFIX = '.py'
MODE = 'U'
def __init__(self):
self.cache = {}
def find_module(self, fullname, paths=None):
source = fullname.split('.')[-1] + self.SUFFIX
paths = sys.path if paths is None else paths
for path in paths:
print("Find {0} on {1}".format(fullname, path))
if path not in self.cache:
print("List {0}".format(path))
self.cache[path] = set(glob.iglob(os.path.join(path, '*' + self.SUFFIX)))
if source not in self.cache[path]:
continue
print("Found at {0} in {1]".format(source, path))
pathname = os.path.join(path, source)
fobject = open(pathname, 'U')
description = (self.SUFFIX, self.MODE, imp.PY_SOURCE)
return CachingLoader(fobject, pathname, description)
def load_module(self, fullname):
print("Loading {0}".format(fullname))
return imp.load_module(fullname)
# create and register the import hook
finder = CachingFinder()
sys.meta_path.append(finder)
if __name__ == '__main__':
# import submodule from package
import xml.sax.saxutils
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment