root/trunk/RBJabber/RBJabber/SubjectObserver/ProxySubject.py

Revision 400, 4.5 kB (checked in by sholloway, 6 years ago)

Integrated SubjectObserver? from old foundation into tree for meantime

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 """ProxySubejcts draw out some commonalities of subjects observing
23 other subjects.  Based upon what they observer, the proxy subjects
24 may filter/modify/extrapolate further results, or simple pass on a
25 subset of those results.
26
27 TODO: Look at doing this with metaclasses ala Aspect Oriented Programming?
28 """
29
30 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 #~ Imports
32 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33
34 from RBFoundation import Acquisition
35 import Subject
36 import CategorySubject
37
38 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 #~ Definitions
40 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41
42 class ProxySubjectTriggerMixin(object):
43     """This class makes it so that any setattr/delattr
44     calls UpdateObservers on the associated subject."""
45
46     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47     #~ Constants / Variables / Etc.
48     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49
50     _subject = None
51
52     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53     #~ Special
54     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
55
56     def __init__(self, subject=None):
57         self.SetSubject(subject)
58
59     def __setattr__(self, name, value):
60         result = self.__super.__setattr__(name, value)
61         if name != '_subject' and self._subject:
62             self._subject.UpdateObserversEx({name: value})
63         return result
64
65     def __delattr__(self, name):
66         result = self.__super.__delattr__(name)
67         if name != '_subject' and self._subject:
68             self._subject.UpdateObserversEx({name: None})
69         return result
70
71     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72     #~ Public Methods
73     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74
75     def SetSubject(self, subject):
76         self._subject = subject
77
78 ProxySubjectTriggerMixin._ProxySubjectTriggerMixin__super = super(ProxySubjectTriggerMixin)
79
80 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81
82 class ProxySubjectAcquisitionMixin(ProxySubjectTriggerMixin, Acquisition.AcquisitionMixin):
83     """This class couples the methods of Acquisition with UpdateObserver calls on attribute sets or deletes."""
84     def __init__(self, subject=None):
85         ProxySubjectTriggerMixin.__init__(self, subject)
86         Acquisition.AcquisitionMixin.__init__(self)
87
88     def SetSubject(self, subject):
89         if self._subject: self.RemoveAcquirable(self._subject)
90         super(ProxySubjectAcquisitionMixin, self).SetSubject(subject)
91         if self._subject: self.AddAcquirable(self._subject)
92
93 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94
95 class ProxySubject(ProxySubjectAcquisitionMixin):
96     """Binds ProxySubjectAcquisitionMixin to the Subject class by default"""
97     def __init__(self, subject=None):
98         ProxySubjectAcquisitionMixin.__init__(self, subject or Subject.Subject())
99
100 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101
102 class ProxyCategorySubject(ProxySubjectAcquisitionMixin):
103     """Binds ProxySubjectAcquisitionMixin to the CategorySubject class by default"""
104     def __init__(self, subject=None):
105         ProxySubjectAcquisitionMixin.__init__(self, subject or CategorySubject.CategorySubject())
106
107 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108 #~ Testing
109 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110
111 if __name__=='__main__':
112     print "Testing..."
113     from RBFoundation.AttributedDict import AttributedDict
114     ad = AttributedDict({'a':1,'b':2})
115
116     test = ProxySubject()
117     test.AddAcquirable(ad)
118
119     def TestObserver(subject, **kw):
120         print subject, kw
121
122     test.AddObserver(TestObserver)
123
124     test.UpdateObservers(testing='yep')
125
126     print test.a
127     assert test.a is ad.a
128
129     print test.b
130     assert test.b is ad.b
131
132     test.a = test.a * 3
133     print test.a
134     assert test.a is ad.a
135
136     print "Test complete."
137
Note: See TracBrowser for help on using the browser.