Skip to content

Instantly share code, notes, and snippets.

@jdowner
Created April 28, 2016 10:58
Show Gist options
  • Save jdowner/fc685180434a3388708b57de89d10cad to your computer and use it in GitHub Desktop.
Save jdowner/fc685180434a3388708b57de89d10cad to your computer and use it in GitHub Desktop.
requests-provides mechanism
import functools
import weakref
class Property(object):
instances = weakref.WeakValueDictionary()
def __new__(cls, name):
if name in Property.instances:
return Property.instances[name]
obj = super().__new__(cls)
setattr(obj, 'name', name)
Property.instances[name] = obj
return obj
class requires(object):
def __init__(self, *args, dynamic=False):
self.requires = set(args)
self.dynamic = dynamic
def __call__(self, func, *args, **kwargs):
@functools.wraps(func)
def static_wrapper(*args, **kwargs):
return func(*args, **kwargs)
@functools.wraps(func)
def dynamic_wrapper(*args, **kwargs):
for req in self.requires:
assert req in Property.instances, 'missing requirement: {}'.format(req)
return func(*args, **kwargs)
if self.dynamic:
return dynamic_wrapper
for req in self.requires:
assert req in Property.instances
return static_wrapper
class provides(object):
def __init__(self, *args):
self.properties = list(args)
def __call__(self, func, *args, **kwargs):
@functools.wraps(func)
def impl(*args, **kwargs):
return func(*args, **kwargs)
setattr(impl, '__provides__', [Property(p) for p in self.properties])
return impl
@requires('bar', dynamic=True)
@provides('foo')
class Foo(object):
def stuff(self):
print('foo')
provides('baz')
@requires('baz', dynamic=True)
def other(self):
print('baz')
@provides('bar')
class Bar(object):
pass
f = Foo()
f.stuff()
f.other()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment