Changeset 176

Show
Ignore:
Timestamp:
06/17/02 22:22:55 (6 years ago)
Author:
sholloway
Message:

Documentation updated

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/RBFoundation/RBFoundation/WeakBind.py

    r175 r176  
    113113        return self._DoCall(args, kw) 
    114114 
     115    def __getattribute__(self, name): 
     116        try:  
     117            return BoundCallableBase.__getattribute__(self, name) 
     118        except AttributeError: 
     119            if self.im_self and self.im_self(): 
     120                try:  
     121                    return getattr(self.im_self(), name) 
     122                except AttributeError: pass 
     123            if self.im_func and self.im_func(): 
     124                try:  
     125                    return getattr(self.im_func(), name) 
     126                except AttributeError: pass 
     127            raise 
     128 
    115129    def __eq__(self, other): 
    116130        if isinstance(other, WeakBoundCallable): 
     
    164178        return self._DoCall(args, kw) 
    165179 
     180    def __getattribute__(self, name): 
     181        try:  
     182            return BoundCallableBase.__getattribute__(self, name) 
     183        except AttributeError: 
     184            if self.im_self and self.im_self(): 
     185                try:  
     186                    return getattr(self.im_self(), name) 
     187                except AttributeError: pass 
     188            if self.im_func and self.im_func(): 
     189                try:  
     190                    return getattr(self.im_func(), name) 
     191                except AttributeError: pass 
     192            raise 
     193 
    166194    def __eq__(self, other): 
    167195        if isinstance(other, StrongBoundCallable): 
     
    194222        return callback 
    195223 
     224def StrongBindCallable(callback): 
     225    """Weakly binds a callable object only if needed."""  
     226    if isinstance(callback, BoundCallableBase): 
     227        # It's already bound in some form or another,  
     228        # but we have to guard it from being wrapped 
     229        # again, because it is itself an instance. 
     230        return callback 
     231    elif isinstance(callback, typesRequireBinding): 
     232        # Well if it requires binding, then we should 
     233        # do so! 
     234        return StrongBoundCallable(callback) 
     235    else: 
     236        # not quite sure what it is, but it does not require binding 
     237        return callback 
     238 
    196239#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    197240#~ Testing  
  • trunk/RBJabber/RBJabber/SubjectObserver/AssociativeObserver.py

    r90 r176  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Observer implementation that can delegate multiple input updates to multiple 
     34receivers based on what the delegate observer is interested in.  Note: This is less 
     35effecient than Subject-side category based filtering, but does not depend upon the  
     36subject implementing the category interface. 
     37""" 
     38 
    3339#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3440#~ Imports  
     
    3642 
    3743from Foundation.WeakBind import BindCallable 
     44from Foundation.SubjectObserver import ProxyBidableCategorySubjectMixin 
    3845 
    3946#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    4148#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4249 
    43 class AssociativeObserver
     50class AssociativeObserver(ProxyBidableCategorySubjectMixin)
    4451    def __init__(self): 
    4552        self._associations = {} 
    4653 
    47     def AddAssociation(self, association, observer): 
    48         self._associations.setdefault(association, []).append(BindCallable(observer)) 
     54    def AddAssociation(self, category, observer): 
     55        self._associations.setdefault(category, []).append(BindCallable(observer)) 
    4956        return self 
    5057 
    51     def Bid(self, subject, **UpdateDict): 
    52         for key, value in UpdateDict.iteritems(): 
    53             for observer in self._associations.get(key, []): 
    54                 subject._GetBid(observer, UpdateDict) 
     58    def _ObserverList(self, category): 
     59        return self._associations.get(category, []) 
    5560 
    56     def Update(self, subject, **UpdateDict): 
    57         pass # Weird condition... no bids on it, but we really dont care here 
     61#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     62#~ Testing  
     63#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     64 
     65if __name__=='__main__': 
     66    print "Testing..." 
     67    import BidableSubject 
     68    s = BidableSubject.BidableSubject() 
     69    from Observer import Observer 
     70 
     71    def AssertSubject(subject, value): 
     72        assert subject is s 
     73    def AssertFalse(subject, value): 
     74        assert 0 
     75 
     76    ao = AssociativeObserver() 
     77    s.AddObserver(ao) 
     78 
     79    ao.AddAssociation('test', Observer(AssertFalse, 100)) 
     80    ao.AddAssociation('test', Observer(AssertFalse, -1)) 
     81 
     82    ao.AddAssociation('value', Observer(AssertFalse, 9)) 
     83    ao.AddAssociation('value', Observer(AssertSubject, 10)) 
     84    ao.AddAssociation('value', Observer(AssertSubject)) 
     85    ao.AddAssociation('value', AssertSubject) 
     86 
     87    ao.AddAssociation('value2', Observer(AssertSubject)) 
     88    ao.AddAssociation('value2', AssertSubject) 
     89 
     90    s.UpdateObservers(value=42) 
     91 
     92    print "Test complete." 
     93 
  • trunk/RBJabber/RBJabber/SubjectObserver/AttributedSubject.py

    r167 r176  
    3030##~ 
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     32 
     33"""Subject-based Foundation.AttributedDict 
     34 
     35Similar to Foundation.AttributedDict, except that every modification causes an  
     36UpdateObservers call.""" 
    3237 
    3338#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    159164 
    160165class AttributedSubject(AttributedSubjectMixin, Subject):  
     166    """Couples AttributedSubjectMixin with a Subject propigation scheme.""" 
    161167    def AddObserver(self, observer, call=0, **kw): 
    162168        Subject.AddObserver(self, observer, **kw) 
  • trunk/RBJabber/RBJabber/SubjectObserver/BidableSubject.py

    r164 r176  
    3030##~ 
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     32 
     33"""Adds bidding to the Subject/Observer mechanism so that 
     34observers can "voluntarily" be out-bid to provide for  
     35state-dependant event handling.   
     36 
     37In order to bid, the observer must have a 'Bid' attribute 
     38(value or callable), and the highest bidder wins, as defined 
     39by the > operator.""" 
    3240 
    3341#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  • trunk/RBJabber/RBJabber/SubjectObserver/CategorySubject.py

    r170 r176  
    3030##~ 
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     32 
     33"""Adds 'categories' to subjects to allow for prefiltering of subject 
     34notifications.  Simply put, you have to add an observer for a specific 
     35category, and that observer will only be called when that category is  
     36updated.""" 
    3237 
    3338#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  • trunk/RBJabber/RBJabber/SubjectObserver/Observer.py

    r88 r176  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Observer implementation. 
     34 
     35Note: You only need an Observer instance if you need to place a bid value. 
     36otherwise the callable object can be passed straight to the subject. 
     37""" 
     38 
    3339#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3440#~ Imports  
     
    4248 
    4349class Observer(BoundCallable): 
     50    """Note: Only needed if you are adding a Bid value to the observer; 
     51    otherwise the callable object can be passed straight to the subject.""" 
     52 
    4453    def __init__(self, callback=None, Bid=None): 
    4554        super(Observer, self).__init__(callback or self.Update) 
     
    5665    def Update(self, subject, **UpdateDict): 
    5766        print "On Update:", subject.__class__.__name__, UpdateDict 
     67 
     68 
     69#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     70#~ Testing  
     71#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     72 
     73if __name__=='__main__': 
     74    print "Testing..." 
     75    import BidableSubject 
     76    s = BidableSubject.BidableSubject() 
     77 
     78    def AssertSubject(subject, value): 
     79        assert subject is s 
     80    def AssertFalse(subject, value): 
     81        assert 0 
     82     
     83    s.AddObserver(Observer(AssertSubject, 10)) 
     84    s.AddObserver(Observer(AssertFalse, 9)) 
     85    s.AddObserver(Observer(AssertFalse, 8)) 
     86    s.AddObserver(Observer(AssertFalse, -1)) 
     87    # The following two will get called because of no bid value 
     88    s.AddObserver(Observer(AssertSubject)) 
     89    s.AddObserver(AssertSubject) 
     90 
     91    s.UpdateObservers(value=42) 
     92    print "Test complete." 
     93 
  • trunk/RBJabber/RBJabber/SubjectObserver/SchedulerSubject.py

    r170 r176  
    3030##~ 
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     32 
     33"""Subject/Observer like implementation of sched""" 
    3234 
    3335#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  • trunk/RBJabber/RBJabber/SubjectObserver/StateMachine.py

    r164 r176  
    3030##~ 
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     32 
     33"""State machine implementation using the Subject/Observer design pattern. 
     34 
     35By defining each state as a subject, the state can "call you back" in order to 
     36compute complext firing semantics, or when the state is reached. 
     37""" 
    3238 
    3339#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    6874#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    6975 
    70 class State(CategorySubject): 
     76class StateSubject(CategorySubject): 
    7177    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    7278    #~ Constants / Variables / Etc.  
     
    9298    #~ Public Methods  
    9399    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    94  
    95     def AddObserver(self, callable, category='', **kw): 
    96         category = category or 'precondition' 
    97         return CategorySubject.AddObserver(self, category, callable, **kw) 
    98100 
    99101    def SetState(self, value =1): 
     
    125127    def AddOutflux(self, Outflux): 
    126128        Outflux.AddInflux(self) 
     129 
     130#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     131 
     132class State(StateSubject): 
     133    def AddObserver(self, callable, category='', **kw): 
     134        category = category or 'precondition' 
     135        return CategorySubject.AddObserver(self, category, callable, **kw) 
    127136 
    128137#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  • trunk/RBJabber/RBJabber/SubjectObserver/Subject.py

    r170 r176  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Maintains a list of montioring observers that get updated when  
     34UpdateObservers or UpdateObserversEx get called, unless the subject is Locked. 
     35A lock can be obtained by calling Lock, and it maintained until the lock object  
     36no longer exisits or is explicitly released. 
     37 
     38WeakBind module is used extensively to prevent reference chains keeping objects in 
     39memory unnecessarily.""" 
     40 
    3341#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3442#~ Imports  
     
    4351 
    4452class Subject(object): 
    45     """Maintains a list of montioring observers that get updated when  
    46     UpdateObservers or UpdateObserversEx get called, unless the subject is Locked. 
    47     A lock can be obtained by calling Lock, and it maintained until the lock object  
    48     no longer exisits or is explicitly released.""" 
    49      
    5053    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    5154    #~ Special  
     
    7679 
    7780    def ClearObservers(self): 
     81        """Removes all observers from the internal collection""" 
    7882        self._observers[:] = [] 
    7983        return self 
  • trunk/RBJabber/RBJabber/SubjectObserver/__init__.py

    r159 r176  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
    33 """TODO: Document""" 
     33"""Subject/Observer with bells on. 
     34 
     35The goal of this package is to make both observers and subjects very simple to create 
     36maintain, while retaining both flexable and powerful subjects / observers.  The simplest 
     37observers are just callable objects, and the simplest subjects keep a list of observers 
     38to notify.  More advanced classes include bidable, attributed, and categorized  
     39subject/observers. 
     40 
     41This main module collects and blends many of the subject and observer types to create 
     42extremely useful subjects and observers.   
     43""" 
    3444 
    3545#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    3848 
    3949import Observer as _Observer 
    40 import AssociativeObserver as _AssociativeObserver 
    41  
    4250import Subject as _Subject 
    4351import CategorySubject as _CategorySubject 
     
    6674 
    6775class ProxyBidableCategorySubjectMixin(object): 
     76    """Allows some subject to proxy for a different subject as an observer of that subject,  
     77    while maintaining bid-sequences and categories""" 
     78 
    6879    def __call__(self, subject, **UpdateDict): 
    6980        pass 
     
    8091 
    8192class ProxyBidableSubjectMixin(object): 
     93    """Allows some subject to proxy for a different subject as an observer of that subject,  
     94    while maintaining bid-sequences""" 
     95 
    8296    def __call__(self, subject, **UpdateDict): 
    8397        pass 
  • trunk/RBSkinning/RBSkinning/wxTools/wxEvtHandlerBidableCategorySubject.py

    r164 r176  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Subject/Observer wrapping of wxEvents, allowing 0 to n recipients for any given event.  
     34 
     35Avoids having to deal with evt.Skip, or PushEventHandler for every needed layer by building 
     36upon Bidable and Category subjects from Foundation.SubjectObserver. 
     37 
     38To use: 
     39    EvtSubject = wxEvtSubject() 
     40    EvtSubject.PushEventHandler(window_or_evthandler) 
     41    EvtSubject.AddObserver(wxEVT_SIZE, callback_one) 
     42    EvtSubject.AddObserver(wxEVT_SIZE, callback_n) 
     43""" 
     44 
    3345#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3446#~ Imports  
     
    4456 
    4557class wxEvtHandlerBidableCategorySubject(BidableCategorySubject): 
    46     def __init__(self): 
     58    EventCallbackName = 'event' 
     59 
     60    def __init__(self, wxEvtHandlerBidableCategorySubject=None): 
    4761        self.EvtHandler = wx.wxEvtHandler() 
    4862        BidableCategorySubject.__init__(self) 
     63        if EventHandler: self.PushEventHandler(EventHandler) 
    4964 
    5065    def _OnEvent(self, evt): 
    51         if not self.UpdateObserversEx({('event', evt.GetEventType()):evt}): 
     66        if not self.UpdateObserversEx({(self.EventCallbackName, evt.GetEventType()):evt}): 
    5267            evt.Skip() 
    5368     
     69    def PushEventHandler(self, EventHandler): 
     70        self.EvtHandler.SetNextHandler(EventHandler) 
     71        EventHandler.SetPreviousHandler(self.EvtHandler) 
     72 
    5473    def AddObserver(self, category, *args, **kw): 
    5574        self.EvtHandler.Connect(-1, -1, category, BindCallable(self._OnEvent)) 
    56         BidableCategorySubject.AddObserver(self, ('event', category), *args, **kw) 
     75        BidableCategorySubject.AddObserver(self, (self.EventCallbackName, category), *args, **kw) 
    5776 
     77wxEvtSubject = wxEvtHandlerBidableCategorySubject