Created
June 13, 2012 00:24
-
-
Save samuraisam/2920980 to your computer and use it in GitHub Desktop.
A decorator that allows you to execute a function exactly once upon the first execution of the wrapped function
This file contains hidden or 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 characters
| import uuid | |
| import functools | |
| def do_once(once_f, *once_f_a, **once_f_kw): | |
| """ | |
| A decorator that executes `once_f(*once_f_a, **once_f_kw)` exactly once upon | |
| the first execution of the decorated function. `once_f` may be a string in | |
| which case it will be used to getattr() from the class. | |
| `once_f` may be any callable. If the wrapped function is a classmethod | |
| `once_f` may not be an instance method, but it may be if the wrapped | |
| function is an instance method itself (they must be peers). | |
| For example:: | |
| >>> class Item(object): | |
| ... @classmethod | |
| ... def load_stuff(cls, mod): | |
| ... print 'loading', mod | |
| ... __import__(mod) | |
| ... | |
| ... @do_once('load_stuff', 'faceplant') | |
| ... def start(self): | |
| ... print 'started!' | |
| >>> Item().start() | |
| loading faceplant | |
| started! | |
| >>> Item().start() | |
| started! | |
| Notice how 'loading faceplant' is only run once. Kabam. `once_f` could | |
| be any callable, including lambdas. It works with with instancemethods | |
| """ | |
| once = { # to get around namespacing | |
| 'once_f': once_f, | |
| 'once_f_a': once_f_a, | |
| 'once_f_kw': once_f_kw | |
| } | |
| def dec(f): | |
| key = 'did_{}'.format(uuid.uuid1().hex) | |
| @functools.wraps(f) | |
| def wrapped_f(*a, **kw): | |
| if not f.__dict__.get(key, False): | |
| # once_f may be a string pointing to another function in the | |
| # same instance as the do_once | |
| if isinstance(once['once_f'], basestring): | |
| once['once_f'] = getattr(a[0], once['once_f']) | |
| once['once_f'](*once['once_f_a'], **once['once_f_kw']) # do it! | |
| setattr(f, key, True) # remember we did | |
| return f(*a, **kw) | |
| return wrapped_f | |
| return dec |
This file contains hidden or 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 characters
| import importlib | |
| import pkglib | |
| from do_once_decorator import do_once | |
| class StreamItem(object): | |
| _item_types = {} | |
| @classmethod | |
| @do_once('load_all_classes', 'mypackage') | |
| def get_type(cls, type_name): | |
| if type_name not in cls._item_types[type_name]: | |
| raise TypeError('Unknown StreamItem type {}'.format(type_name)) | |
| return cls._item_types[type_name] | |
| @classmethod | |
| def register(cls, name=None): | |
| """ | |
| Register a subclass of `StreamItem` to be available for automatic | |
| instantiation when being pulled from the database. | |
| """ | |
| def dec(klass): | |
| cls._item_types[name or klass.__name__] = klass | |
| return klass | |
| return dec | |
| @classmethod | |
| def load_all_classes(cls, package): | |
| """ | |
| Imports all subclasses of helpers_package so they are loaded into | |
| all_helpers and available for lookup | |
| """ | |
| helpers_mod = importlib.import_module(package) | |
| mod_gen = pkgutil.iter_modules(helpers_mod.__path__) | |
| for importer, name, is_pkg in mod_gen: | |
| if name.startswith('_'): | |
| continue # ignore names that start with a _ | |
| __import__('{}.{}'.format(package, name)) |
This file contains hidden or 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 characters
| from streamitem import StreamItem | |
| @StreamItem.register() | |
| class StupidStreamItem(StreamItem): | |
| pass |
This file contains hidden or 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 characters
| from streamitem import StreamItem | |
| stupid_stream_item = StreamItem.get_type('StupidStreamItem') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment