Skip to content

Instantly share code, notes, and snippets.

@mottosso
Created May 16, 2014 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mottosso/8877a2ae1608f2656e3a to your computer and use it in GitHub Desktop.
Save mottosso/8877a2ae1608f2656e3a to your computer and use it in GitHub Desktop.
Request Pattern - Weak
class Request(object):
"""
In contrast to Signal, this object emits a request for data.
The observer(s) then transmits requested data.
If there is more than one observer, each observer transmits
requested until no more data exists. That way, a minimal amount
of observers will ever have to process.
Example
Create two objects, a subject and observer, where
the observer provides data *requests* from the subject.
In this case, `Mom` will provide the `age` of `Marcus`
(as `Marcus` doesn't know it on his own :)
>>> subject = type('Marcus', (object,), {})()
>>> subject.get_age = Request(age=int)
>>> observer = type('Mom', (object,), {})()
>>> observer.give_age = lambda: 27
>>> subject.get_age.connect(observer.give_age)
>>> subject.get_age()
27
"""
log = logging.getLogger('pifou.lib.Request')
def __call__(self, *args, **kwargs):
return self.request_first(*args, **kwargs)
def __init__(self, **kwargs):
self.__methods = weakref.WeakKeyDictionary()
self.__functions = weakref.WeakSet()
def request(self, *args, **kwargs):
"""Return generator, yielding one return value per slot"""
for func in self.__functions:
return_value = func(*args, **kwargs)
yield return_value
for obj, funcs in self.__methods.iteritems():
for func in funcs:
return_value = func(obj, *args, **kwargs)
yield return_value
def request_first(self, *args, **kwargs):
"""Return first available result"""
try:
return next(self.request(*args, **kwargs))
except StopIteration:
return None
return None
def connect(self, slot):
if hasattr(slot, '__self__'):
if slot.__self__ not in self.__methods:
self.__methods[slot.__self__] = set()
self.__methods[slot.__self__].add(slot.__func__)
else:
self.__functions.add(slot)
def disconnect(self, slot):
if hasattr(slot, '__self__'):
if slot.__self__ in self.__methods:
return self.__methods[slot.__self__].remove(slot.__func__)
else:
if slot in self.__functions:
return self.__functions.remove(slot)
raise ValueError("Slot not connected: %s" % slot)
def clear(self):
self.__functions.clear()
self.__methods.clear()
@mottosso
Copy link
Author

Motivation and use here
http://rfc.abstractfactory.io/spec/45/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment