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
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)
31 # BasicNode - specific, config, mixin
34 # BasicNodeReference - mixin
35 # NodeContextProxy - mixin, basic proto
38 # TODO make this an instance of AbstractTreeNode...
39 class AbstractAcquisitionalNode(object):
45 class AcquisitionalNodeMixin(AbstractAcquisitionalNode
):
48 def __acquire__(self
):
51 parent
= getattr(self
, 'parent', None)
54 for o
in parent
.__acquire
__():
58 #-----------------------------------------------------------BasicNode---
59 class BasicNode(AcquisitionalNodeMixin
):
64 def __init__(self
, parent
, name
, *p
, **n
):
71 parent
.children
[name
] = self
76 #--------------------------------------------------BasicNodeReference---
78 class BasicNodeReference(BasicNode
, proxy
.InheritAndOverrideProxy
):
81 ##!!!!! FIND A BETTER (MORE GENTLE) WAY TO DO THIS !!!!!##
82 # TODO avoid duble writes...
83 def __init__(self
, target
, parent
, name
, *p
, **n
):
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
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__ \
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
)
146 self
.children
[name
] = value
147 def __delitem__(self
, name
):
150 del self
.children
[name
]
154 return self
.children
.__iter
__()
157 #----------------------------------------------BasicAcquisitionalNode---
158 class BasicAcquisitionalNode(BasicNodeMapping
):
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)
173 return super(BasicAcquisitionalNode
, self
).__getitem
__(name
)
175 return wrapper(super(BasicAcquisitionalNode
, self
).__getitem
__(name
), self
)
177 if self
.parent
== None:
180 return self
.parent
[name
]
182 return wrapper(self
.parent
[name
], self
)
185 #-----------------------------------------------------------------------
186 if __name__
== '__main__':
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']'''
204 print '''root['a']['x']'''
206 print '''root['a']['x']['b']'''
207 print root
['a']['x']['b']
209 print root
['a']['x']['b']
210 print '''root['b']'''
212 print '''root['b']['a']['x']['b']'''
213 print root
['b']['a']['x']['b']
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
228 print root
['c']['root']
231 print root
['c']['root'].parent
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....
251 # test for possible del side-effects...
252 print root
['c']['root'].parent
259 ## root2 = pickle.loads(pickle.dumps(root))
262 print root2
['a']['x']
263 print root2
['a']['x']['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
278 #=======================================================================
279 # vim:set ts=4 sw=4 nowrap :