Created
December 8, 2018 17:37
Revisions
-
pankajp created this gist
Dec 8, 2018 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,12 @@ from mod_prop import mod_property, cached_mod_property @mod_property def my_prop(): print('my_prop called') return 42 @cached_mod_property def my_cached_prop(): print('my_cached_property called') return '24' This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,13 @@ import caching_mod print(caching_mod) print('p', caching_mod.my_prop) print('q', caching_mod.my_prop) from caching_mod import my_prop print('r', caching_mod.my_prop) print('s', caching_mod.my_prop) from caching_mod import my_cached_prop print('t') print('u', my_cached_prop) print('v', caching_mod.my_cached_prop) This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,33 @@ """ Module level property and cached property decorator """ import sys import types import functools def update_module_class(mod): class CachingModule(types.ModuleType): pass mod.__class__ = CachingModule def mod_property(func, cached=False): func_name = func.__name__ if '.' in func_name: raise ValueError('mod_property only applicable to top-level module functions') func_mod = sys.modules[func.__module__] if func_mod.__class__ == types.ModuleType: update_module_class(func_mod) elif func_mod.__class__.__name__ != 'CachingModule': raise RuntimeError(f'mod_property incompatible with module type: {func_mod.__name__}({func_mod.__class__.__qualname__})') @functools.wraps(func) def wrapper(mod): value = func() if cached: setattr(func_mod.__class__, func_name, value) delattr(func_mod, func_name) return value wrapper.__name__ = func_name setattr(func_mod.__class__, func_name, property(wrapper)) return wrapper def cached_mod_property(func): return mod_property(func, cached=True)