Skip to content

Instantly share code, notes, and snippets.

@bobuk
Last active June 24, 2022 10:31
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bobuk/508f22bb949cd0724d95cd67487b1c62 to your computer and use it in GitHub Desktop.
Save bobuk/508f22bb949cd0724d95cd67487b1c62 to your computer and use it in GitHub Desktop.
import os
import sys
import importlib.abc
import importlib.util
import json
import yaml
ex_registry = []
class ExDataLoader(importlib.abc.Loader):
def repack(self, mod, data):
if type(data) == dict:
for k, v in data.items():
if k.startswith("__") and k.endswith("__") or hasattr(mod, k):
continue
setattr(mod, k, v)
mod.raw_data = data
def exec_module(self, mod):
data = self.load_data(open(mod.__spec__.origin, 'r').read())
self.repack(mod, data)
def load_data(self, data):
return {}
def __init_subclass__(self):
ex_registry.append(self)
if not hasattr(self, 'ext'):
setattr(self, 'ext', '.' + self.__name__.lower())
class JSON(ExDataLoader):
def load_data(self, data):
return json.loads(data)
class YAML(ExDataLoader):
ext = ".yaml"
def load_data(self, data):
return yaml.load(data, Loader=yaml.SafeLoader)
class ExPathFinder(importlib.abc.MetaPathFinder):
def find_spec(self, fullname, path, target=None):
if not path:
path = [os.getcwd()]
if "." in fullname:
fullname = fullname.split(".")[-1]
for cat in path:
for mod in ex_registry:
in_path = os.path.join(cat, fullname) + mod.ext
if os.path.exists(in_path):
return importlib.util.spec_from_file_location(
name=fullname + mod.ext, location=in_path, loader=mod()
)
return None
sys.meta_path.append(ExPathFinder())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment