removed generator imports (style incompatibility with Py25)
[pli.git] / pli / pattern / store / misc.py
blobc39db3ef4069213f1d34a21f4f7c6a3eda7c175b
1 #=======================================================================
3 __version__ = '''0.1.47'''
4 __sub_version__ = '''20061124145351'''
5 __copyright__ = '''(c) Alex A. Naanou 2003'''
8 #-----------------------------------------------------------------------
10 ##from __future__ import generators
11 import types
13 import pli.functional as func
14 from pli.functional import curry
15 ##!!! this might change in the future...
16 import pli.objutils as objutils
18 import selector
19 import store
20 import stored
21 import storeclient
23 ##import acl
27 #-----------------------------------------------------------------------
28 #-----------------------------------------------------------isinstore---
29 def isinstore(store):
30 '''
31 this function will return a predicate that will check if an object
32 exists in a given store (to be used mainly for auto type checking).
33 '''
34 return lambda oid: oid in store
37 #---------------------------------------------------------r_isinstore---
38 def r_isinstore(store, excep=None, msg=None):
39 '''
40 this will cunstruct a test function that will test if an object exists
41 in a given store or raise an exception.
42 '''
43 name = hasattr(store, '__name__') and store.__name__ or store.__class__.__name__
44 return func.raise_on_false(isinstore(store), 'r_isin' + name,\
45 excep != None and NameError \
46 or excep, \
47 msg != None and ('object not found in store %s.' % store) \
48 or msg)
51 #----------------------------------------------isinstore_and_isoftype---
52 def isinstore_and_isoftype(store):
53 '''
54 this will generate a function (takes store as argument) that will in turn
55 construct a function (takes object type as argument) that will test if
56 obj (key) is in store and is (value) of a given type...
59 NOTE: sorry, but this might not be the most obvios of functions (atleast
60 at the first sight!) :)
61 '''
62 return lambda otype: \
63 lambda obj: isinstore(store)(obj) and type(store[obj]) == otype
67 #-----------------------------------------------------------------------
68 # TODO rework this into mixins....
69 #------------------------------------------StaticStoreClientWithOwner---
70 SHOW_ALL = 1
71 class OwnedStaticStoreClient(storeclient.StaticStoreClient):
72 '''
73 '''
75 __ignore_nonexistant_filter_attrs__ = True
77 def __init__(self, owner, flags=0):
78 '''
79 '''
80 self._store_flags = flags
81 self.__owner__ = owner
82 store.StaticStoreClient.__init__(self, filters={'__owner__':owner})
83 def __getattr__(self, name):
84 '''
85 '''
86 # deligate the call to the original store object
87 # constructors...
88 ##!! revise !!##
89 cls = store.StaticStoreClient.__getattr__(self, name)
90 if issubclass(cls, OwnedStoredObjectWithAttrs):
91 return curry(cls, owner=self.__owner__)
92 return cls
93 def isaccessible(self, key):
94 '''
95 '''
96 obj = self._store_data[key]
97 ## obj = self[key]
98 if self._store_flags & SHOW_ALL:
99 return True
100 ## if hasattr(obj, '__store_public__') and obj.__store_public__:
101 ## return True
102 ##!!! is this needed...
103 if not hasattr(self, '__owner__') or self.__owner__ in ('', None):
104 return True
105 # this might be a litle slower, but it is more flexible...
106 return super(OwnedStaticStoreClient, self).isaccessible(key)
107 ## res = []
108 ## for attr, val in self._store_filters.items():
109 ## try:
110 ## res += [getattr(obj, attr) == val]
111 ## except AttributeError:
112 ## pass
113 ## if False not in res:
114 ## return True
115 ## return False
119 #-----------------------------------------------------------------------
120 #-----------------------------------------------StoredObjectWithAttrs---
121 class StoredObjectWithAttrs(objutils.ObjectWithAttrs, stored.StoredObject):
123 a generic stored object class with attribute creation an update automation.
125 this class checks attribute format.
127 ## __acl__ = acl
128 # this will restrict the attribute that can be created for this
129 # object to the ones mentioned in the list (DO NOT SET HERE!).
130 ## __attr_format__ = ()
131 # this defines a list of attributes that must be defined on object
132 # init.
133 ## __essential_attrs__ = ()
134 # this defines the callbacks for attr update... (RPC only at the
135 # moment...)
136 ## __attr_update_callbacks__ = {}
137 # this will enable attribute type checking...
138 __check_attr_types__ = True
139 # this defines the values to be considered as no-vals...
140 __none_values__ = ('', 'None', None)
142 ##!! temporary...
143 __readonly_attrs__ = ()
145 ##!! temporary -- this is a fix to allow zodbs special attrs... !!##
146 def __setattr__(self, name, val):
149 return object.__setattr__(self, name, val)
152 #------------------------------------------OwnedStoredObjectWithAttrs---
153 class OwnedStoredObjectWithAttrs(StoredObjectWithAttrs):
156 __store_public__ = False
158 def __init__(self, name, attrs={}, owner=''):
161 super(OwnedStoredObjectWithAttrs, self).__init__(name, attrs)
162 if not hasattr(self, '__owner__'):
163 self.__owner__ = owner
167 #-----------------------------------------------------------------------
168 #-----------------------------------------------------------TreeStore---
169 class TreeStore(store.BaseStore):
172 def __delitem__(self, key):
175 obj = self[key]
176 if hasattr(obj, 'children') and len(obj.children) != 0:
177 raise TypeError, 'can\'t remove, not empty object "%s"' % key
178 if obj.parent != None:
179 self[obj.parent].children.remove(key)
180 super(TreeStore, self).__delitem__(key)
181 # TODO make this non-recursive...
182 def get_tree_dict(self, node_id=None):
184 this will return a nested dict of the form:
185 {<node_id>: <children>[, ...]}
186 where <children> is a dict of the same format.
188 if node_id != None:
189 if node_id not in self:
190 raise KeyError, 'object "%s" is not in store "%s".' % (node_id, self.__name__)
191 root = node_id
192 else:
193 root = 'root'
194 root_obj = self[root]
195 # recursive...
196 return dict([(n, self.get_tree_dict(n)) for n in (hasattr(root_obj, 'children') and root_obj.children or [])])
197 def get_tree(self, node_id=None):
199 this will return a nested tuple of the form:
200 ((<node_id>, <children>)[, ...])
201 where <children> is a dict of the same format.
203 if node_id != None:
204 if node_id not in self:
205 raise KeyError, 'object "%s" is not in store "%s".' % (node_id, self.__name__)
206 root = node_id
207 else:
208 root = 'root'
209 root_obj = self[root]
210 # recursive...
211 return [[n, self.get_tree(n)] for n in (hasattr(root_obj, 'children') and root_obj.children or ())]
214 #------------------------------------------------------------TreeNode---
215 # Q: is it posible to make this store.StoredObject subclass???
216 class TreeNode(StoredObjectWithAttrs):
219 __store__ = None
220 # this will automatcly register the class as a store type...
221 __auto_register_type__ = False
223 __essential_attrs__ = (
224 'parent', # str (parent folder id)
226 ## __attr_format__ = __essential_attrs__ + \
227 ## (
228 ## )
230 __readonly_attrs__ = StoredObjectWithAttrs.__readonly_attrs__ + \
232 'children',
235 def __init__(self, *p, **n):
238 super(TreeNode, self).__init__(*p, **n)
239 # check parent...
240 ## if self.parent not in ('None', None):
241 ## if self.parent not in self.__store__:
242 ## raise TypeError, 'can\'t attach to a non-existant object "%s".' % self.parent
243 self.children = []
244 self.__readonly_attrs__ = self.__readonly_attrs__ + ('parent',)
245 def update(self, data):
248 if 'parent' in data:
249 parent = data['parent']
250 del data['parent']
251 if parent not in ('None', None):
252 if parent not in self.__store__:
253 raise TypeError, 'can\'t attach to a non-existant object "%s".' % parent
254 if hasattr(self, 'parent'):
255 # detach from old parent... (on move)
256 self.__store__[self.parent].children.remove(self.__name__)
257 self.parent = parent
258 res = super(TreeNode, self).update(data)
259 # atach to new parent...
260 self.__store__[parent].children += [self.__name__]
261 return res
262 else:
263 self.parent = parent
264 return super(TreeNode, self).update(data)
268 ###-----------------------------------------------------------------------
269 ##class CallproxyWrapper(object):
270 ## '''
271 ## '''
272 ## __proxy__ = None
274 ## def __getattr__(self, name):
275 ## '''
276 ## '''
277 ## return self.__proxy__(super(Wrapper, self).__getattr__(name))
280 ##class CallproxyWrapperStore(store.BaseStore):
281 ## '''
282 ## '''
284 ## __wrapper__ = Wrapper
286 ## def __getitem__(self, name):
287 ## '''
288 ## '''
289 ## return super(CallproxyWrapperStore, self).__getitem__(name)
293 #=======================================================================
294 # vim:set ts=4 sw=4 nowrap :