Changeset 138

Show
Ignore:
Timestamp:
05/05/02 14:02:58 (6 years ago)
Author:
sholloway
Message:

Updates, bugfixes, and of course, NEW FEATURES ;)

Files:

Legend:

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

    r132 r138  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Simple select.select handle management. 
     34 
     35A set of classes wrapping select.select, making the management of N handles as  
     36simple as managing a single handle.  In order to implement SmartSelect for your  
     37socket or other handle(s), simply derive from SmartSelectBase, and implement the  
     38abstract methods from ClientBase. 
     39 
     40Well read pythoneers will note that is module is very similar to asyncore, and are 
     41probably wondering why.  Well, my reason is interface.  Asyncore was great inspiration, 
     42but I wanted to have less assumption that the objects were sockets; simply objects  
     43compatable with select.select.  Secondly, objects derived from SmartSelectBase should 
     44be as easily run as if they were collected into a larger group.  Finally, I wanted the 
     45collections to feel like just that: collections of selectable objects.  (dict, list, or single) 
     46""" 
     47 
    3348#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3449#~ Imports                                            
     
    6075 
    6176    def Process(self, timeout=None): 
    62         """Uses select.select to wait on several file (proxy) handles in an object-oriented way.""" 
     77        """Uses select.select to wait on several file (proxy) handles in an object-oriented way.   
     78        ProcessState contains the state and, if applicable, the handle being processed, 
     79        allowing for interogation in the case of an exception.""" 
    6380        if not self: 
    6481            self.ProcessState = "Idle", None 
  • trunk/RBJabber/RBJabber/Conference.py

    r137 r138  
    3838from Foundation.Jabber.JabberSubject import JabberSubjectBase 
    3939from Foundation.Jabber import JID 
    40 from Foundation import SubjectObserver 
     40from Foundation.SubjectObserver.Observer import Observer 
    4141 
    4242#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     
    4747    def __init__(self, JC, ConferenceJID): 
    4848        JabberSubjectBase.__init__(self) 
     49        # Save the conference JID 
     50        self.ConferenceJID = JID.JID(ConferenceJID).nominal() 
     51 
     52        # Save the Jabber Client 
     53        self.JC = weakref.ref(JC) 
     54 
     55        # Pretend like we are a Jabber.Client 
    4956        self.stream = weakref.proxy(self) 
    50         self.ConferenceJID = JID.JID(ConferenceJID).nominal() 
    51         self.JC = weakref.ref(JC
    52         JC.stream.AddObserver('message', self
    53         JC.stream.AddObserver('presence', self
    54         JC.stream.AddObserver('iq', self
     57        # Insert our greedy little meathooks... 
     58        obs = Observer(self._CallConference, self._BidConference
     59        JC.stream.AddObserver('message', obs
     60        JC.stream.AddObserver('presence', obs
     61        JC.stream.AddObserver('iq', obs
    5562 
    56     def Bid(self, subject, **UpdateDict): 
     63    def __del__(self): 
     64        if self.JC(): 
     65            self.Presence(type='unavailable') 
     66 
     67    def _CallConference(self, subject, **UpdateDict): 
     68        pass 
     69 
     70    def _BidConference(self, subject, **UpdateDict): 
    5771        for each in UpdateDict.itervalues(): 
    5872            if each.from_ not in self.ConferenceJID: 
     
    6478        self.JC().Query('jabber:iq:conference', toJID=self.ConferenceJID, type='get', callback=callback) 
    6579 
    66     def Join(self, NickName, Secret='', callback=None): 
     80    def JoinAs(self, NickName, Secret='', callback=None): 
    6781        if not isinstance(NickName, (list, tuple)): NickName = (NickName,) 
    6882        xmlNickName = ''.join(['<nick>%s</nick>' % x for x in NickName]) 
     
    88102    print "Testing..." 
    89103    import Client 
    90     import pprint 
    91104    def PrintStuff(stream, **kw): 
    92105        for each in kw.itervalues(): 
     
    94107    jc = Client.Client('www.runeblade.com') 
    95108    jc.Authenticate('shane.test1', 'testing', 'PyConferenceTest') 
    96     jc.ProcessPending(1.0) 
    97109    conf = Conference(jc, 'shane.conf@private.www.runeblade.com') 
    98110    conf.AddObserver('message', PrintStuff) 
    99111    conf.AddObserver('presence', PrintStuff) 
    100112    conf.AddObserver('iq', PrintStuff) 
    101     conf.Join('RuneBlade.Development') 
     113    conf.JoinAs('RuneBlade.Development') 
    102114    conf.Message('Hello from RB development!!!') 
    103115    jc.ProcessPending(1.0) 
     116    try: 
     117        while 1: jc.Process(1.0) 
     118    except KeyboardInterrupt: 
     119        pass 
     120    #del conf 
     121    #try: 
     122    #    while 1: jc.Process(1.0) 
     123    #except KeyboardInterrupt: 
     124    #    pass 
    104125    print "Test complete." 
    105126 
  • trunk/RBJabber/RBJabber/SubjectObserver/Subject.py

    r137 r138  
    4242 
    4343class Subject(object): 
     44    """Maintains a list of montioring observers that get updated when  
     45    UpdateObservers or UpdateObserversEx get called, unless the subject is Locked. 
     46    A lock can be obtained by calling Lock, and it maintained until the lock object  
     47    no longer exisits or is explicitly released.""" 
     48     
     49    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     50    #~ Special  
     51    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     52 
    4453    def __init__(self): 
    4554        self._observers = [] 
     
    5261     
    5362    def AddObserver(self, observer): 
     63        """Adds observer to the internal collection monitoring this subject 
     64        Observer is assumed to be a callable object.""" 
    5465        result = WeakBind.BindCallable(observer) 
    5566        self._observers.append(result) 
     
    5768 
    5869    def RemoveObserver(self, observer): 
     70        """Removes observer from the internal collection monitoring this subject.   
     71        Observer should be the same object that was passed to AddObserver.""" 
    5972        result = WeakBind.BindCallable(observer) 
    6073        try: 
     
    6881    
    6982    def _ObserverList(self): 
     83        """Returns the internal observer collection pruned of invalid weakref objects as a list""" 
    7084        self._observers = filter(None, self._observers) 
    7185        return self._observers 
     
    7387 
    7488    def UpdateObservers(self, **kw): 
     89        """Updates all observers of this subject with data in **kw.  See also UpdateObserversEx.""" 
    7590        return self.UpdateObserversEx(kw) 
    7691 
    7792    def UpdateObserversEx(self, kw): 
     93        """Updates all observers of this subject with data in kw.  (kw is assumed to be a dictonary.)  See also UpdateObservers.""" 
    7894        self._cachedUpdates.update(kw) 
    7995        if self._cachedUpdates and not self._locked: 
     
    87103 
    88104    def UpdateObserver(self, observer, UpdateDict): 
     105        """Updates observer with UpdateDict.  (UpdateDict is assumed to be a dictonary.)""" 
    89106        if observer: apply(observer, (self,), UpdateDict) 
    90107 
     108    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     109    #~ Subject Locking 
     110    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     111 
     112    class _SubjectLock: 
     113        """Maintains a lock on subject while instance exists""" 
     114        subject = None 
     115        def __init__(self, lockedsubject): 
     116            self.SetLock(lockedsubject) 
     117        def __del__(self): 
     118            try:  
     119                self.SetLock(None) 
     120            except: 
     121                # XXX: Is there a good way to pass the exception along, and not have it  
     122                # be absorbed by the python __del__ exception condition? 
     123                import traceback 
     124                traceback.print_exc() 
     125        def SetLock(self, lockedsubject): 
     126            """Obtains a  lock on lockedsubject.  If lockedsubject is different than the  
     127            current subject, then the current subject is unlocked as well.""" 
     128            if self.subject and id(self) in self.subject._locked: 
     129                self.subject._locked.remove(id(self)) 
     130                if self.subject._cachedUpdates: 
     131                    self.subject.UpdateObservers() 
     132            self.subject = lockedsubject 
     133            if self.subject: 
     134                self.subject._locked.append(id(self)) 
     135 
    91136    def Lock(self): 
    92         class lock: 
    93             subject = None 
    94             def __init__(self, lockedsubject): 
    95                 self.SetLock(lockedsubject) 
    96             def __del__(self): 
    97                 self.SetLock(None) 
    98             def SetLock(self, lockedsubject): 
    99                 if self.subject and id(self) in self.subject._locked: 
    100                     self.subject._locked.remove(id(self)) 
    101                     if self.subject._cachedUpdates: 
    102                         self.subject.UpdateObservers() 
    103                 self.subject = lockedsubject 
    104                 if self.subject: 
    105                     self.subject._locked.append(id(self)) 
    106         return lock(self) 
     137        """Prevents observers of subject from being updated while a lock is held on the subject.""" 
     138        return self._SubjectLock(self) 
    107139 
     140    def Locked(self): 
     141        """Returns 1 if the subject is locked, and 0 otherwise""" 
     142        return self._locked and 1 or 0 
  • trunk/RBJabber/RBJabber/SubjectObserver/__init__.py

    r137 r138  
    3737#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3838 
    39 import Observer 
    40 import AssociativeObserver 
     39import Observer as _Observer 
     40import AssociativeObserver as _AssociativeObserver 
    4141 
    42 import Subject 
    43 import CategorySubject 
    44 import AttributedSubject 
    45 import BidableSubject 
     42import Subject as _Subject 
     43import CategorySubject as _CategorySubject 
     44import AttributedSubject as _AttributedSubject 
     45import BidableSubject as _BidableSubject 
    4646 
    47 class AttributedCategorySubject(AttributedSubject.AttributedSubjectMixin, CategorySubject.CategorySubjectMixin, Subject.Subject):  
     47#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     48#~ Definitions  
     49#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     50 
     51class AttributedCategorySubject(_AttributedSubject.AttributedSubjectMixin, _CategorySubject.CategorySubjectMixin, _Subject.Subject):  
    4852    pass 
    49 class AttributedBidableSubject(AttributedSubject.AttributedSubjectMixin, BidableSubject.BidableSubjectMixin, Subject.Subject): 
     53class AttributedBidableSubject(_AttributedSubject.AttributedSubjectMixin, _BidableSubject.BidableSubjectMixin, _Subject.Subject): 
    5054    pass 
    51 class AttributedBidableCategorySubject(AttributedSubject.AttributedSubjectMixin, BidableSubject.BidableSubjectMixin, CategorySubject.CategorySubjectMixin, Subject.Subject): 
     55class AttributedBidableCategorySubject(_AttributedSubject.AttributedSubjectMixin, _BidableSubject.BidableSubjectMixin, _CategorySubject.CategorySubjectMixin, _Subject.Subject): 
    5256    pass 
    5357 
    54 class BidableCategorySubject(BidableSubject.BidableSubjectMixin, CategorySubject.CategorySubjectMixin, Subject.Subject): 
     58class BidableCategorySubject(_BidableSubject.BidableSubjectMixin, _CategorySubject.CategorySubjectMixin, _Subject.Subject): 
    5559    pass 
    56 class BidableAttributedSubject(AttributedSubject.AttributedSubjectMixin, BidableSubject.BidableSubjectMixin, Subject.Subject): 
     60class BidableAttributedSubject(_AttributedSubject.AttributedSubjectMixin, _BidableSubject.BidableSubjectMixin, _Subject.Subject): 
    5761    pass 
    58 class BidableAttributedCategorySubject(AttributedSubject.AttributedSubjectMixin, BidableSubject.BidableSubjectMixin, CategorySubject.CategorySubjectMixin, Subject.Subject): 
     62class BidableAttributedCategorySubject(_AttributedSubject.AttributedSubjectMixin, _BidableSubject.BidableSubjectMixin, _CategorySubject.CategorySubjectMixin, _Subject.Subject): 
    5963    pass 
    6064 
     
    97101    def printo3(subject, **UpdateDict): 
    98102        print "O3: ", UpdateDict 
    99     s1 = Subject.Subject() 
    100     s2 = AttributedSubject.AttributedSubject() 
     103    s1 = _Subject.Subject() 
     104    s2 = _AttributedSubject.AttributedSubject() 
    101105    s3 = AttributedCategorySubject() 
    102106 
     
    114118    s1.UpdateObservers(Locked='Update') 
    115119    print "Post-lock" 
    116     lock = None 
     120    del lock 
    117121    print "Unlocked" 
    118122 
    119     o3 = Observer.Observer(printo3) 
    120     s3.AddObserver('CategoryA', o1) 
    121     s3.AddObserver('CategoryB', o2) 
     123    o3 = _Observer.Observer(printo3) 
     124    s3.AddObserver('CategoryA', printo1) 
     125    s3.AddObserver('CategoryB', printo2) 
    122126    s3.AddObserver('CategoryC', o3) 
    123127