Skip to content

Instantly share code, notes, and snippets.

@jdowner
Created April 28, 2016 10:58
Show Gist options
  • Select an option

  • Save jdowner/fc685180434a3388708b57de89d10cad to your computer and use it in GitHub Desktop.

Select an option

Save jdowner/fc685180434a3388708b57de89d10cad to your computer and use it in GitHub Desktop.

Revisions

  1. jdowner created this gist Apr 28, 2016.
    78 changes: 78 additions & 0 deletions reqpro.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    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()