1 |
commit: cbc3333406f8ed796d98f8f5a6fe0ccab60ac7b5 |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Thu Aug 29 13:13:12 2013 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Thu Aug 29 13:13:12 2013 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=cbc33334 |
7 |
|
8 |
roverlay/util/objects: comments |
9 |
|
10 |
--- |
11 |
roverlay/util/objects.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++-- |
12 |
1 file changed, 62 insertions(+), 2 deletions(-) |
13 |
|
14 |
diff --git a/roverlay/util/objects.py b/roverlay/util/objects.py |
15 |
index ce4eccb..323bc88 100644 |
16 |
--- a/roverlay/util/objects.py |
17 |
+++ b/roverlay/util/objects.py |
18 |
@@ -11,12 +11,24 @@ class ObjectDisappeared ( Exception ): |
19 |
# --- end of ObjectDisappeared --- |
20 |
|
21 |
class SafeWeakRef ( weakref.ref ): |
22 |
+ """A weak reference that supports 'safe' dereferencing, i.e. raising an |
23 |
+ exception if the referenced object does no longer exist.""" |
24 |
|
25 |
def deref_unsafe ( self ): |
26 |
+ """Dereferences without checking whether the object exists. |
27 |
+ |
28 |
+ Returns: the object / None |
29 |
+ """ |
30 |
return super ( SafeWeakRef, self ).__call__() |
31 |
# --- end of deref_unsafe (...) --- |
32 |
|
33 |
def deref_safe ( self ): |
34 |
+ """Safely dereferences the object. |
35 |
+ |
36 |
+ Returns: the object |
37 |
+ |
38 |
+ Raises: ObjectDisappeared if the object does no longer exist. |
39 |
+ """ |
40 |
obj = super ( SafeWeakRef, self ).__call__() |
41 |
if obj is not None: |
42 |
return obj |
43 |
@@ -28,6 +40,7 @@ class SafeWeakRef ( weakref.ref ): |
44 |
deref = deref_safe |
45 |
|
46 |
def __bool__ ( self ): |
47 |
+ """Returns True if the referenced object exists, else False.""" |
48 |
return self.deref_unsafe() is not None |
49 |
# --- end of __bool__ (...) --- |
50 |
|
51 |
@@ -48,6 +61,7 @@ class SafeWeakRef ( weakref.ref ): |
52 |
|
53 |
|
54 |
class NoneRef ( object ): |
55 |
+ """A 'reference' to None (compat object).""" |
56 |
|
57 |
def __init__ ( self, obj=None ): |
58 |
super ( NoneRef, self ).__init__() |
59 |
@@ -76,8 +90,17 @@ class NoneRef ( object ): |
60 |
# --- end of NoneRef --- |
61 |
|
62 |
def get_object_ref ( obj ): |
63 |
+ """Returns a reference to the given object, either by using the object's |
64 |
+ get_ref() function (if defined) or by creating a SafeWeakRef/NoneRef |
65 |
+ instance. |
66 |
+ |
67 |
+ arguments: |
68 |
+ * obj -- |
69 |
+ """ |
70 |
if obj is None: |
71 |
return NoneRef() |
72 |
+ elif isinstance ( obj, ( SafeWeakRef, NoneRef, weakref.ref ) ): |
73 |
+ return obj |
74 |
elif hasattr ( obj, 'get_ref' ): |
75 |
return obj.get_ref() |
76 |
else: |
77 |
@@ -129,6 +152,15 @@ class AbstractMethodError ( MethodNotImplementedError ): |
78 |
# --- end of AbstractMethodError --- |
79 |
|
80 |
def _get_exception_wrapper ( err_cls, func ): |
81 |
+ """Returns a method that raises the given exception when called. |
82 |
+ |
83 |
+ arguments: |
84 |
+ * err_cls -- class/constructor of the exception that should be raised. |
85 |
+ Has to accept 2 args: |
86 |
+ - object to which the method is bound |
87 |
+ - the actual function |
88 |
+ * func -- function to be wrapped |
89 |
+ """ |
90 |
def wrapped ( obj, *args, **kwargs ): |
91 |
raise err_cls ( obj, func ) |
92 |
# --- end of wrapped (...) --- |
93 |
@@ -138,7 +170,6 @@ def _get_exception_wrapper ( err_cls, func ): |
94 |
wrapped.__doc__ = func.__doc__ |
95 |
wrapped.__dict__.update ( func.__dict__ ) |
96 |
return wrapped |
97 |
- |
98 |
# --- end of _get_exception_wrapper (...) --- |
99 |
|
100 |
def abstractmethod ( func=None ): |
101 |
@@ -155,6 +186,7 @@ class Referenceable ( object ): |
102 |
CACHE_REF = False |
103 |
|
104 |
def __init__ ( self, *args, **kwargs ): |
105 |
+ """Initializes a referenceable object. Ignores all args/kwargs.""" |
106 |
super ( Referenceable, self ).__init__() |
107 |
self._cached_selfref = None |
108 |
if self.CACHE_REF: |
109 |
@@ -162,62 +194,90 @@ class Referenceable ( object ): |
110 |
# --- end of __init__ (...) --- |
111 |
|
112 |
def cache_ref ( self ): |
113 |
+ """Creates a cached reference and sets get_ref() so that the cached ref |
114 |
+ is returned (when called).""" |
115 |
self._cached_selfref = self.get_new_ref() |
116 |
self.get_ref = self._get_cached_ref |
117 |
# --- end of cache_ref (...) --- |
118 |
|
119 |
def _get_cached_ref ( self ): |
120 |
+ """Returns the cached reference.""" |
121 |
return self._cached_selfref |
122 |
# --- end of _get_cached_ref (...) --- |
123 |
|
124 |
def get_new_ref ( self ): |
125 |
+ """Returns a new reference.""" |
126 |
return SafeWeakRef ( self ) |
127 |
# --- end of get_new_ref (...) --- |
128 |
|
129 |
+ # initially, get_ref() is get_new_ref() |
130 |
get_ref = get_new_ref |
131 |
|
132 |
# --- end of Referenceable --- |
133 |
|
134 |
|
135 |
class ReferenceTree ( Referenceable ): |
136 |
+ """A Referenceable that is part of a tree-like data structure with weak |
137 |
+ backreferences (each object has one ancestor or None).""" |
138 |
|
139 |
def __init__ ( self, parent ): |
140 |
+ """Intializes this referencable object. |
141 |
+ |
142 |
+ arguments: |
143 |
+ * parent -- the parent object (typically not a reference) |
144 |
+ """ |
145 |
super ( ReferenceTree, self ).__init__() |
146 |
self.parent_ref = None |
147 |
self.set_parent ( parent ) |
148 |
# --- end of __init__ (...) --- |
149 |
|
150 |
def set_parent ( self, parent ): |
151 |
+ """(Re-)sets the parent object. |
152 |
+ |
153 |
+ arguments: |
154 |
+ * parent -- the parent object (typically not a reference) |
155 |
+ """ |
156 |
self.parent_ref = get_object_ref ( parent ) |
157 |
# --- end of set_parent (...) --- |
158 |
|
159 |
def get_parent ( self ): |
160 |
+ """Returns the parent object (dereferenced parent object reference).""" |
161 |
return self.parent_ref.deref_safe() |
162 |
# --- end of get_parent (...) --- |
163 |
|
164 |
+ #get_upper() is an alias to get_parent() |
165 |
get_upper = get_parent |
166 |
|
167 |
# --- end of ReferenceTree --- |
168 |
|
169 |
|
170 |
class ObjectView ( object ): |
171 |
+ """A view object (=expose a (sub-)set of another object's data) that |
172 |
+ uses weak references.""" |
173 |
|
174 |
ObjectDisappeared = ObjectDisappeared |
175 |
|
176 |
def __init__ ( self, obj ): |
177 |
+ """Initializes an object view. |
178 |
+ |
179 |
+ arguments: |
180 |
+ * obj -- object to be "viewed" |
181 |
+ """ |
182 |
super ( ObjectView, self ).__init__() |
183 |
- self.obj_ref = get_object_ref ( obj ) |
184 |
+ self.obj_ref = get_object_ref ( obj ) |
185 |
self.deref_unsafe = self.obj_ref.deref_unsafe |
186 |
self.deref_safe = self.obj_ref.deref_safe |
187 |
self.deref = self.obj_ref.deref_safe |
188 |
# --- end of __init__ (...) --- |
189 |
|
190 |
def __bool__ ( self ): |
191 |
+ """Returns True if the actual object exists, else False.""" |
192 |
return bool ( self.obj_ref ) |
193 |
# --- end of __bool__ (...) --- |
194 |
|
195 |
@abstractmethod |
196 |
def update ( self ): |
197 |
+ """Updates this view (collect data from the actual object etc.).""" |
198 |
pass |
199 |
# --- end of update (...) --- |