Skip to content

Instantly share code, notes, and snippets.

@DRMacIver
Created March 13, 2023 11:16
Show Gist options
  • Save DRMacIver/70af058fec9cb0024097dbcec61e5fbe to your computer and use it in GitHub Desktop.
Save DRMacIver/70af058fec9cb0024097dbcec61e5fbe to your computer and use it in GitHub Desktop.
from types import ModuleType
import sys
class LazyModule(ModuleType):
def __init__(self, name, doc, source):
super().__init__(name, doc)
self.__source = source
self.__loaded = None
def __initialize_load(self):
if self.__loaded is None:
module = ModuleType(self.__name__, self.__doc__)
exec(self.__source, module.__dict__, module.__dict__)
sys.modules[self.__name__] = module
self.__loaded = module
def __getattr__(self, name):
if name.startswith('_LazyModule__'):
return super().__getattr__(name)
self.__initialize_load()
return getattr(self.__loaded, name)
def __setattr__(self, name, value):
if name.startswith('_LazyModule__'):
return super().__setattr__(name, value)
self.__initialize_load()
return setattr(self.__loaded, name, value)
def __delattr__(self, name):
if name.startswith('_LazyModule__'):
return super().__delattr__(name)
self.__initialize_load()
return delattr(self.__loaded, name)
def __dir__(self):
self.__initialize_load()
return self.__loaded.__dir__()
def submodule(fn):
from inspect import getsource
name = fn.__name__
doc = fn.__doc__
root = fn.__module__
module_name = root + "." + name
source = getsource(fn)
lines = source.splitlines()
for start, line in enumerate(lines):
if line.lstrip().startswith('def '):
break
lines[start] = 'if True:'
for i in range(start):
lines[i] = ''
source = '\n'.join(lines)
module = LazyModule(module_name, doc, source)
sys.modules[module_name] = module
return module
@submodule
def foo():
hello = "WORLD"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment