1 #=======================================================================
3 __version__
= '''0.0.49'''
4 __sub_version__
= '''20041031230609'''
5 __copyright__
= '''(c) Alex A. Naanou 2003'''
8 #-----------------------------------------------------------------------
14 import pli
.pattern
.mixin
.mapping
as mapping
17 #-----------------------------------------------------------------------
18 #---------------------------------------------------isstorecompatible---
19 def isstorecompatible(obj
):
21 this will test general store interface compatibility...
23 return issubclass(type(obj
), BaseStore
) or type(obj
) == type({})
26 #--------------------------------------------------------isstoredtype---
27 def isstoredtype(store
, name
):
29 this will return True if the name is a stored type is store.
31 return name
in store
._store
_types
35 #-----------------------------------------------------------------------
36 #-----------------------------------------------------------BaseStore---
37 # TODO add onStoreLoad, onStoreSave and onStoreReload events!!
38 # the handlers of these will accept the store instance as an
40 # TODO rename to MappingBaseStore...
42 class BaseStore(mapping
.Mapping
, mapping
.BasicMappingProxy
):
43 ##class BaseStore(mapping.MappingWithMethods, mapping.BasicMappingProxy):
46 # if this is true strict object type checking will be enabled...
47 __stricttypes__
= False
48 # if this is true there will be no abbility to "recreate" an object
49 # using the add_object method.
50 __strictnames__
= True
51 # this will define the format used to generate a type attribute
52 # name... (attrname = __typenameformat___ % <type>.__name__)
53 __typenameformat___
= '%s'
55 __source_attr__
= '_store_data'
57 def __init__(self
, name
, *p
, **n
):
61 self
._store
_types
= {}
63 ## super(BaseStore, self).__init__(name)
64 # dict minimal methods:
65 ## def __getitem__(self, key):
68 ## return self._store_data[key]
69 def __setitem__(self
, key
, obj
):
72 if type(obj
).__name
__ not in self
._store
_types
:
73 if not self
.__stricttypes
__:
74 # add objects' type...
75 self
.add_object_type(type(obj
))
77 raise TypeError, 'can\'t add object "' + str(obj
) + '" to store "' + str(self
) + '": unregistred type.'
79 if self
.__strictnames
__ and key
in self
._store
_data
:
80 raise TypeError, 'an object with the id "%s" already exists.' % key
81 ## self._store_data[key] = obj
82 super(BaseStore
, self
).__setitem
__(key
, obj
)
83 ## def __delitem__(self, key):
86 ## del self._store_data[key]
87 ## def __iter__(self):
90 ## return self._store_data.__iter__()
91 # dict secondary methods:
92 # NOTE: might be good to un comment these...
93 ## def __contains__(self, key):
96 ## return key in self._store_data
97 ## def iterkeys(self):
100 ## return self._store_data.iterkeys()
101 ## def itervalues(self):
104 ## return self._store_data.itervalues()
105 ## def iteritems(self):
108 ## return self._store_data.iteritems()
112 ## return self._store_data.keys()
116 ## return self._store_data.values()
117 # BaseStore specific methods...
118 def add_object_type(self
, otype
):
121 self
._store
_types
[self
.__typenameformat
___ % otype
.__name
__] = otype
122 ##!!! REMOVE THIS !!!##
126 print '''WARNING: the pli.pattern.store.BaseStore.get_types method will be shortly removed!
127 use the itertypenames, itertypes methods instead!'''
128 return self
._store
_types
.keys()
130 def gettypenames(self
):
132 this will return a list of type names supported by the store.
134 return self
._store
_types
.keys()
137 this will return the types supported by the store.
139 return self
._store
_types
.values()
140 def itertypenames(self
):
142 this will iterate through the type names supported by the store.
144 for n
in self
._store
_types
.iterkeys():
148 this will iterate through the types supported by the store.
150 for n
in self
._store
_types
.itervalues():
155 #-----------------------------------------------------------------------
157 #--------------------------------------------------------WeakrefStore---
158 class WeakrefStore(BaseStore
):
161 def __init__(self
, name
, *p
, **n
):
164 super(WeakrefStore
, self
).__init
__(name
, *p
, **n
)
165 self
._store
_data
= weakref
.WeakValueDictionary()
168 #---------------------------------------------------AttrTypeBaseStore---
169 class AttrTypeBaseStore(BaseStore
):
171 mix-in/class. this provides access to stored object types through atributes.
173 # this if set will check the attr name compliance with the python
174 # variable name syntax...
175 __check_type_name_format__
= True
176 ## __check_type_name_format__ = False
177 # this will define a pattern against which the attribute name is to
179 __type_name_format__
= re
.compile('[_a-zA-Z][_a-zA-Z\d]*$')
181 # NOTE: if this is both an AttributeBaseStore and na
182 # AttrTypeBaseStore the name will get checked twice, and I
183 # see no beautifull way out of this....
184 ## def __setitem__(self, key, value):
187 ## if hasattr(self, '__check_type_name_format__') and self.__check_type_name_format__ and \
188 ## re.match(self.__type_name_format__, key) is None:
189 ## raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % key
190 ## super(AttrTypeBaseStore, self).__setitem__(key, value)
191 def __getattr__(self
, name
):
194 if name
in ('_store_types',):
195 return object.__getattribute
__(self
, '_store_types')
196 if name
in self
._store
_types
:
197 return self
._store
_types
[name
]
199 return super(AttrTypeBaseStore
, self
).__getattr
__(name
)
200 except AttributeError:
201 # XXX is this correct....
202 raise AttributeError, 'object "%s" has no attribute "%s"' % (self
, name
)
203 def add_object_type(self
, otype
):
206 name
= self
.__typenameformat
___ % otype
.__name
__
207 if hasattr(self
, '__check_type_name_format__') and self
.__check
_type
_name
_format
__ and \
208 re
.match(self
.__type
_name
_format
__, name
) is None:
209 raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % name
210 super(AttrTypeBaseStore
, self
).add_object_type(otype
)
213 #--------------------------------------------------------RPCBaseStore---
214 # this is here for the RPC interface...
215 class RPCBaseStore(BaseStore
):
217 mix-in/class. this provides rpc methods for stored object data access.
219 def get_object_data(self
, key
, *attrs
):
226 ##!!! do type checking....
227 res
[attr
] = getattr(obj
, attr
)
229 # this might not be good for a generic version...
232 def add_object(self
, key
, obj
):
234 this will add an object to store...
236 self
.__setitem
__(key
, obj
)
237 def update_object(self
, key
, data
):
239 this will update a set of attributes of an object.
241 if hasattr(self
[key
], 'update'):
243 return self
[key
].update(data
)
247 return setattr(obj
, attr
, data
[attr
])
248 def remove_object(self
, key
):
251 self
.__delitem
__(key
)
254 #---------------------------------------------------GroupingBaseStore---
255 class GroupingBaseStore(BaseStore
):
257 mix-in/class. this provides grouping behavior for stored objects...
262 raise NotImplementedError, 'not yet done...'
265 #--------------------------------------------------AttributeBaseStore---
266 class AttributeBaseStore(BaseStore
):
268 mix-in/class. this provides access to stored objects through store attributes.
270 # this if set will check the attr name compliance with the python
271 # variable name syntax...
272 __check_key_format__
= True
273 # this will define a pattern against which the attribute name is to
275 __key_format__
= re
.compile('[_a-zA-Z][_a-zA-Z\d]*$')
277 # NOTE: if this is both an AttributeBaseStore and na
278 # AttrTypeBaseStore the name will get checked twice, and I
279 # see no beautifull way out of this....
280 def __setitem__(self
, key
, value
):
283 if hasattr(self
, '__check_key_format__') and self
.__check
_key
_format
__ and \
284 re
.match(self
.__key
_format
__, key
) is None:
285 raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % key
286 super(AttributeBaseStore
, self
).__setitem
__(key
, value
)
287 def __getattr__(self
, name
):
291 return super(AttributeBaseStore
, self
).__getattr
__(name
)
296 #--------------------------------------------------------WrapperStore---
297 class WrapperBaseStore(BaseStore
):
299 mix-in/class. this provides access to wrapped/proxied stored objects.
301 # this will define a wrapper object (
303 # <wrapper>(<obj>) -> <wrapped>
306 def __getitem__(self
, key
):
309 return self
.__wrapper
__(super(WrapperStore
, self
).__getitem
__(key
))
310 def itervalues(self
):
313 for val
in super(WrapperStore
, self
).itervalues():
314 yield self
.__wrapper
__(val
)
318 for key
, val
in super(WrapperStore
, self
).iteritems():
319 yield key
, self
.__wrapper
__(val
)
323 return [ self
.__wrapper
__(val
) for val
in super(WrapperStore
, self
).values() ]
326 #-----------------------------------------------AttributeWrapperStore---
327 class AttributeWrapperStore(AttributeBaseStore
, WrapperBaseStore
):
329 mix-in/class. this provides access to wrapped/proxied stored objects through store attributes.
334 #=======================================================================
335 # vim:set ts=4 sw=4 nowrap :