Skip to content

Instantly share code, notes, and snippets.

@samuraisam
Created June 13, 2012 00:24
Show Gist options
  • Select an option

  • Save samuraisam/2920980 to your computer and use it in GitHub Desktop.

Select an option

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
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
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))
from streamitem import StreamItem
@StreamItem.register()
class StupidStreamItem(StreamItem):
pass
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