*** empty log message ***
[pli.git] / pli / pattern / tree / acquisitional.py
bloba39f5e41a95ef4eeaefa7ce81dacffb2c5be0c13
1 #=======================================================================
3 __version__ = '''0.0.01'''
4 __sub_version__ = '''20080126193432'''
5 __copyright__ = '''(c) Alex A. Naanou 2003'''
8 #-----------------------------------------------------------------------
10 import pli.pattern.mixin.mapping as mapping
11 import pli.pattern.proxy.generic as proxy
12 import pli.logictypes as logictypes
15 #-----------------------------------------------------------------------
16 # TODO parant resolution protocol (if not present use attr).
17 # TODO acquisition cut (mignt be done by the above...)
18 # TODO might be good to do a recursive depth iterator...
19 # TODO path modification and resolution priority...
20 # TODO wrap the return of __getitem__
21 # - add context data (for both the origin (?) and current
22 # contexts)
23 # TODO revise the module structure...
26 # AbstractAcquisitionalNode - create, resolve up, basic proto, mixin
27 # AbstractAcquisitionalNodeMapping - mapping, mixin
28 # BasicNodeMapping - specific, config, mixin
29 # Directory (fs mixin)
30 # ...
31 # BasicNode - specific, config, mixin
32 # File (fs mixin)
33 # ...
34 # BasicNodeReference - mixin
35 # NodeContextProxy - mixin, basic proto
38 # TODO make this an instance of AbstractTreeNode...
39 class AbstractAcquisitionalNode(object):
40 '''
41 '''
42 pass
45 class AcquisitionalNodeMixin(AbstractAcquisitionalNode):
46 '''
47 '''
48 def __acquire__(self):
49 '''
50 '''
51 parent = getattr(self, 'parent', None)
52 if parent != None:
53 yield parent
54 for o in parent.__acquire__():
55 yield o
58 #-----------------------------------------------------------BasicNode---
59 class BasicNode(AcquisitionalNodeMixin):
60 '''
61 '''
62 ## parent = None
64 def __init__(self, parent, name, *p, **n):
65 '''
66 '''
67 self.__name__ = name
68 ## self.parent = None
69 if parent != None:
70 self.parent = parent
71 parent.children[name] = self
72 ## self.parent = None
73 self.children = {}
76 #--------------------------------------------------BasicNodeReference---
77 ##!!! REWRITE !!!##
78 class BasicNodeReference(BasicNode, proxy.InheritAndOverrideProxy):
79 '''
80 '''
81 ##!!!!! FIND A BETTER (MORE GENTLE) WAY TO DO THIS !!!!!##
82 # TODO avoid duble writes...
83 def __init__(self, target, parent, name, *p, **n):
84 '''
85 '''
86 # NOTE: the way the __init__ is called is a workaround pythons
87 # type check on first arg of method...
88 # NOTE: the class is passed up to avoid changing the targets
89 # state (NS).
90 BasicNode.__dict__['__init__'](self.__class__, parent, name, *p, **n)
91 # this is to correcting a little side-effect... (in the above
92 # code we passed the class, thus it is registred as a child,
93 # not the original rarget...)
94 # TODO avoid duble writes...
95 if hasattr(self, 'parent') and self.parent != None:
96 self.parent.children[name] = self
97 ## self.parent.children[name] = self
100 #------------------------------------------------------ProxyNameSpace---
101 class ProxyNameSpace(logictypes.WritableDictUnion, dict):
104 __modify_props__ = logictypes.GET_LOCAL_FIRST \
105 | logictypes.WRITE_LOCAL \
106 | logictypes.DELETE_FIRST
109 #----------------------------------------------------NodeContextProxy---
110 class NodeContextProxy(BasicNode, proxy.InheritAndOverrideProxy):
111 ##class NodeContextProxy(BasicNode, proxy.TransparentInheritAndOverrideProxy):
114 ## __proxy_public_attrs__ = proxy.TransparentInheritAndOverrideProxy.__proxy_public_attrs__ \
115 ## + (
116 ## 'parent',
117 ## )
119 ##!!!!! FIND A BETTER (MORE GENTLE) WAY TO DO THIS !!!!!##
120 # TODO avoid duble writes...
121 def __init__(self, target, context, *p, **n):
124 ## self.__dict__ = ProxyNameSpace(self.__dict__)
125 ## BasicNode.__dict__['__init__'](self.__class__, getattr(context, 'parent', None), self.__name__, *p, **n)
126 self.__class__.parent = context
129 #----------------------------------------------------BasicNodeMapping---
130 class BasicNodeMapping(BasicNode, mapping.Mapping):
133 __node_reference_class__ = BasicNodeReference
135 def __getitem__(self, name):
138 return self.children[name]
139 # WARNING: this will cause proxy nesting...
140 def __setitem__(self, name, value):
143 if isinstance(value, BasicNode):
144 BasicNodeReference(value, self, name)
145 else:
146 self.children[name] = value
147 def __delitem__(self, name):
150 del self.children[name]
151 def __iter__(self):
154 return self.children.__iter__()
157 #----------------------------------------------BasicAcquisitionalNode---
158 class BasicAcquisitionalNode(BasicNodeMapping):
161 # signature:
162 # __context_wrapper__(cur_context, res)
163 ## __context_wrapper__ = None
164 __context_wrapper__ = NodeContextProxy
165 # WARNING: be ware of acquisition loops!
166 # TODO resolve acquisition loops...
167 def __getitem__(self, name):
170 wrapper = getattr(self, '__context_wrapper__', None)
171 try:
172 if wrapper == None:
173 return super(BasicAcquisitionalNode, self).__getitem__(name)
174 else:
175 return wrapper(super(BasicAcquisitionalNode, self).__getitem__(name), self)
176 except KeyError:
177 if self.parent == None:
178 raise
179 if wrapper == None:
180 return self.parent[name]
181 else:
182 return wrapper(self.parent[name], self)
185 #-----------------------------------------------------------------------
186 if __name__ == '__main__':
187 import pickle
189 # test node creation...
190 root = BasicAcquisitionalNode(None, 'root')
192 BasicAcquisitionalNode(root, 'a')
194 BasicAcquisitionalNode(root, 'b')
195 BasicAcquisitionalNode(root, 'c')
197 # test node access...
198 BasicAcquisitionalNode(root['a'], 'x')
199 BasicAcquisitionalNode(root['a'], 'y')
200 BasicAcquisitionalNode(root['a'], 'z')
202 print '''root['a']'''
203 print root['a']
204 print '''root['a']['x']'''
205 print root['a']['x']
206 print '''root['a']['x']['b']'''
207 print root['a']['x']['b']
208 print '!!!!!!!'
209 print root['a']['x']['b']
210 print '''root['b']'''
211 print root['b']
212 print '''root['b']['a']['x']['b']'''
213 print root['b']['a']['x']['b']
215 print
217 ## for n in root['b']['a']['x']['b']['a'].__acquire__():
218 ## print n.__name__, '/',
221 # test direct node assignment...
222 root['c']['123'] = 123
223 root['c']['root'] = root
225 print
227 print root
228 print root['c']['root']
230 ## print root.parent
231 print root['c']['root'].parent
233 print
235 print root['c']['root']['b']['a']['x']['b']
237 root['b']['rrr'] = root['c']['root']
239 print root['b']['rrr']['b']['a']['x']['b']
241 print root['c']['root'].parent
243 ## for n in root['b']['rrr']['b']['a']['x'].__acquire__():
244 ## print n.__name__, '/',
246 root2 = pickle.loads(pickle.dumps(root))
248 # test node removal....
249 del root['b']['rrr']
251 # test for possible del side-effects...
252 print root['c']['root'].parent
253 print root['c']
255 print
256 print
258 # raw pickle test...
259 ## root2 = pickle.loads(pickle.dumps(root))
261 print root2['a']
262 print root2['a']['x']
263 print root2['a']['x']['b']
264 print root2['b']
265 print root2['b']['a']['x']['b']
266 print root2['c']['root']['b']['a']['x']['b']
267 print root2['b']['rrr']['b']['a']['x']['b']
268 print root2['c']['root'].parent
269 print root2['c']
278 #=======================================================================
279 # vim:set ts=4 sw=4 nowrap :