Skip to content

Instantly share code, notes, and snippets.

@markshannon
Created November 30, 2014 22:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markshannon/1868e7e6115d70ce6e76 to your computer and use it in GitHub Desktop.
Save markshannon/1868e7e6115d70ce6e76 to your computer and use it in GitHub Desktop.
Dynamic attribute module
import sys
import warnings
from types import ModuleType
from importlib import import_module
try:
basestring
except NameError:
basestring = str
class FancyModule(object):
__class__ = ModuleType
def __init__(self, original):
self.__dict__ = original.__dict__
self.__auto_import__ = set()
self.__warn_on_access__ = {}
self.__name__ = original.__name__
def __getattr__(self, name):
if name in self.__auto_import__:
assert "." not in name
# FIXME: this next line requires 2.7+.
mod = import_module("." + name, package=self.__package__)
# import has probably done this implicitly, but let's be explicit:
setattr(self, name, mod)
return mod
if name in self.__warn_on_access__:
value, warning = self.__warn_on_access__[name]
warnings.warn(warning, stacklevel=2)
return value
raise AttributeError(name)
def __dir__(self):
result = set(self.__dict__)
result.update(self.__auto_import__)
result.update(self.__warn_on_access__)
return sorted(result)
def __repr__(self):
return "<module %s>" % self.__name__
def install(name, class_=FancyModule):
orig_module = sys.modules[name]
if isinstance(orig_module, class_):
return
new_module = FancyModule(orig_module)
sys.modules[name] = new_module
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment