Skip to content

Instantly share code, notes, and snippets.



Last active Aug 29, 2015
What would you like to do?
A simple python hook system that doesn't mutate global variables and tries to be as side-effect free as possible
from __future__ import print_function
import sys
from collections import namedtuple
from imp import load_module, find_module
from pathlib import Path
Hooks = namedtuple('Hooks', 'preactivate postactivate get_env_details postrmvirtualenv')
_HOOKS = Hooks._fields
def hook(f):
fname = f.__name__
if fname not in _HOOKS:
msg = '{0} is not a valid hook. Possible hooks are: {1}'.format(fname, _HOOKS)
raise ImportError(msg)
return f
paths = ['.', 'inner']
def select_hooks(module):
for _hook in _HOOKS:
loaded_hook = getattr(module, _hook, None)
if loaded_hook:
yield _hook, loaded_hook
def load_hooks(paths):
for path in paths:
if Path(path).exists():
module = load_module('<TEMP>', *find_module('hooks', [path]))
for hooktuple in select_hooks(module):
yield hooktuple # this would be a 'yield from' in Python3 only
del module
except ImportError as err:
print(err, file=sys.stderr)
def discover_hooks(paths):
hooks = {h:[] for h in _HOOKS}
for hookname, hook in load_hooks(paths):
return Hooks(**hooks)
if __name__ == '__main__':
hooks = discover_hooks(paths)
for h in hooks.preactivate:
for h in hooks.get_env_details:
from _utils import hook
def preactivate(env): # This will fail due to the extra "e"
print('preactivating', env, '!')
# This would fail due to the extra "e"
# @hook
# def preeactivate(env):
# print('preactivating', env, '!')
# The hook decorator is completely optional
def get_env_details(env):
print("here I'd need to supply you some details about", env)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment