Created
May 16, 2014 13:18
-
-
Save mottosso/8877a2ae1608f2656e3a to your computer and use it in GitHub Desktop.
Request Pattern - Weak
This file contains 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
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Motivation and use here
http://rfc.abstractfactory.io/spec/45/