1 #=======================================================================
3 __version__
= '''0.0.49'''
4 __sub_version__
= '''20041019031531'''
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()
129 def gettypenames(self
):
131 this will return a list of type names supported by the store.
133 return self
._store
_types
.keys()
136 this will return the types supported by the store.
138 return self
._store
_types
.values()
139 def itertypenames(self
):
141 this will iterate through the type names supported by the store.
143 for n
in self
._store
_types
.iterkeys():
147 this will iterate through the types supported by the store.
149 for n
in self
._store
_types
.itervalues():
154 #-----------------------------------------------------------------------
156 #--------------------------------------------------------WeakrefStore---
157 class WeakrefStore(BaseStore
):
160 def __init__(self
, name
, *p
, **n
):
163 super(WeakrefStore
, self
).__init
__(name
, *p
, **n
)
164 self
._store
_data
= weakref
.WeakValueDictionary()
167 #---------------------------------------------------AttrTypeBaseStore---
168 class AttrTypeBaseStore(BaseStore
):
170 mix-in/class. this provides access to stored object types through atributes.
172 # this if set will check the attr name compliance with the python
173 # variable name syntax...
174 __check_type_name_format__
= True
175 ## __check_type_name_format__ = False
176 # this will define a pattern against which the attribute name is to
178 __type_name_format__
= re
.compile('[_a-zA-Z][_a-zA-Z\d]*$')
180 # NOTE: if this is both an AttributeBaseStore and na
181 # AttrTypeBaseStore the name will get checked twice, and I
182 # see no beautifull way out of this....
183 ## def __setitem__(self, key, value):
186 ## if hasattr(self, '__check_type_name_format__') and self.__check_type_name_format__ and \
187 ## re.match(self.__type_name_format__, key) is None:
188 ## raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % key
189 ## super(AttrTypeBaseStore, self).__setitem__(key, value)
190 def __getattr__(self
, name
):
193 if name
in ('_store_types',):
194 return object.__getattribute
__(self
, '_store_types')
195 if name
in self
._store
_types
:
196 return self
._store
_types
[name
]
198 return super(AttrTypeBaseStore
, self
).__getattr
__(name
)
199 except AttributeError:
200 # XXX is this correct....
201 raise AttributeError, 'object "%s" has no attribute "%s"' % (self
, name
)
202 def add_object_type(self
, otype
):
205 name
= self
.__typenameformat
___ % otype
.__name
__
206 if hasattr(self
, '__check_type_name_format__') and self
.__check
_type
_name
_format
__ and \
207 re
.match(self
.__type
_name
_format
__, name
) is None:
208 raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % name
209 super(AttrTypeBaseStore
, self
).add_object_type(otype
)
212 #--------------------------------------------------------RPCBaseStore---
213 # this is here for the RPC interface...
214 class RPCBaseStore(BaseStore
):
216 mix-in/class. this provides rpc methods for stored object data access.
218 def get_object_data(self
, key
, *attrs
):
225 ##!!! do type checking....
226 res
[attr
] = getattr(obj
, attr
)
228 # this might not be good for a generic version...
231 def add_object(self
, key
, obj
):
233 this will add an object to store...
235 self
.__setitem
__(key
, obj
)
236 def update_object(self
, key
, data
):
238 this will update a set of attributes of an object.
240 if hasattr(self
[key
], 'update'):
242 return self
[key
].update(data
)
246 return setattr(obj
, attr
, data
[attr
])
247 def remove_object(self
, key
):
250 self
.__delitem
__(key
)
253 #---------------------------------------------------GroupingBaseStore---
254 class GroupingBaseStore(BaseStore
):
256 mix-in/class. this provides grouping behavior for stored objects...
261 raise NotImplementedError, 'not yet done...'
264 #--------------------------------------------------AttributeBaseStore---
265 class AttributeBaseStore(BaseStore
):
267 mix-in/class. this provides access to stored objects through store attributes.
269 # this if set will check the attr name compliance with the python
270 # variable name syntax...
271 __check_key_format__
= True
272 # this will define a pattern against which the attribute name is to
274 __key_format__
= re
.compile('[_a-zA-Z][_a-zA-Z\d]*$')
276 # NOTE: if this is both an AttributeBaseStore and na
277 # AttrTypeBaseStore the name will get checked twice, and I
278 # see no beautifull way out of this....
279 def __setitem__(self
, key
, value
):
282 if hasattr(self
, '__check_key_format__') and self
.__check
_key
_format
__ and \
283 re
.match(self
.__key
_format
__, key
) is None:
284 raise NameError, 'stored objects name must comply with python variable naming rules (got: "%s").' % key
285 super(AttributeBaseStore
, self
).__setitem
__(key
, value
)
286 def __getattr__(self
, name
):
290 return super(AttributeBaseStore
, self
).__getattr
__(name
)
295 #--------------------------------------------------------WrapperStore---
296 class WrapperBaseStore(BaseStore
):
298 mix-in/class. this provides access to wrapped/proxied stored objects.
300 # this will define a wrapper object (
302 # <wrapper>(<obj>) -> <wrapped>
305 def __getitem__(self
, key
):
308 return self
.__wrapper
__(super(WrapperStore
, self
).__getitem
__(key
))
309 def itervalues(self
):
312 for val
in super(WrapperStore
, self
).itervalues():
313 yield self
.__wrapper
__(val
)
317 for key
, val
in super(WrapperStore
, self
).iteritems():
318 yield key
, self
.__wrapper
__(val
)
322 return [ self
.__wrapper
__(val
) for val
in super(WrapperStore
, self
).values() ]
325 #-----------------------------------------------AttributeWrapperStore---
326 class AttributeWrapperStore(AttributeBaseStore
, WrapperBaseStore
):
328 mix-in/class. this provides access to wrapped/proxied stored objects through store attributes.
333 #=======================================================================
334 # vim:set ts=4 sw=4 nowrap :