From 180b0eefbe011c665ac407160b72108e0e6aac63 Mon Sep 17 00:00:00 2001 From: alex_nanou Date: Mon, 11 Apr 2005 02:29:09 +0000 Subject: [PATCH] *** empty log message *** --- CHANGES | 5 +- PKG-INFO | 2 +- pli/logictypes.py | 140 ++++++++++++++++++- pli/pattern/proxy/generic.py | 4 +- pli/pattern/tree/__init__.py | 11 ++ pli/pattern/tree/acquisitional.py | 280 ++++++++++++++++++++++++++++++++++++++ pli/pattern/tree/fs.py | 11 ++ setup.py | 4 +- 8 files changed, 450 insertions(+), 7 deletions(-) create mode 100755 pli/pattern/tree/__init__.py create mode 100755 pli/pattern/tree/acquisitional.py create mode 100755 pli/pattern/tree/fs.py diff --git a/CHANGES b/CHANGES index 889ab89..8faad10 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -# this file was generated on [200504010132] +# this file was generated on [200504110626] pli changes: +version 0.0.140 (200504060442): ++ added pli.logictypes.WritableDictUnion class... + version 0.0.138 (200503310620): - added support for proxy objects (module pli.pattern.proxy.generic) to be safely pickled and unpickled (needs more testing). - added two functions to pli.pattern.proxy.generic, the _reduceproxyobject and _reconstructproxyobject which enable to breakup a proxy object and safely restore it respectively... these are used for the pickle protocol (see above) (needs nor testing). diff --git a/PKG-INFO b/PKG-INFO index 1241075..38f8ae2 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: pli -Version: 0.0.140 +Version: 0.0.141 Summary: PLI: a utility library for the Python language. Home-page: http://pli.sourceforge.net/ Author: Alex A. Naanou diff --git a/pli/logictypes.py b/pli/logictypes.py index 9c140e5..3b09233 100755 --- a/pli/logictypes.py +++ b/pli/logictypes.py @@ -1,7 +1,7 @@ #======================================================================= -__version__ = '''0.1.07''' -__sub_version__ = '''20050302201424''' +__version__ = '''0.1.12''' +__sub_version__ = '''20050406044155''' __copyright__ = '''(c) Alex A. Naanou 2003''' __doc__ = '''\ @@ -325,6 +325,126 @@ class DictUnion(mapping.Mapping): return dict(self.items()) +#---------------------------------------------------WritableDictUnion--- +# modes: +# get the last occurance... +GET_LOCAL_LAST = 0 +# get the first occurance... +GET_LOCAL_FIRST = 1 + +# if key is not contained in union, add it to the last member... +WRITE_NEW_TO_LAST = 0 +# if key is not contained in union, add it to the first member... +WRITE_NEW_TO_FIRST = 2 +# if the key is present in the union more than once, override the last +# occurance... +WRITE_TO_LAST_OWNER = 0 +# if the key is present in the union more than once, override the first +# occurance... +WRITE_TO_FIRST_OWNER = 4 +# write to local (temporary) dict... +# NOTE: if this is set, other write opts will be ignored... +WRITE_LOCAL = 8 +# disable write... +WRITE_DISABLED = 16 + +# delete the last occurance of key... +DELETE_LAST = 0 +# delete the first occurance of key... +DELETE_FIRST = 32 +# enable ocal key delete... +DELETE_LOCAL = 64 +# disable deletion of anything but local keys... +DELETE_LOCAL_ONLY = 128 +# disable delete... +DELETE_DISABLED = 256 + +class WritableDictUnion(DictUnion): + ''' + ''' + __modify_props__ = GET_LOCAL_FIRST \ + | WRITE_NEW_TO_FIRST \ + | WRITE_TO_FIRST_OWNER \ + | DELETE_FIRST \ + | DELETE_LOCAL + + def __init__(self, *members): + ''' + ''' + super(WritableDictUnion, self).__init__(*members) + self._locals = {} + def __getitem__(self, name): + ''' + ''' + props = getattr(self, '__modify_props__', 0) + if props & GET_LOCAL_FIRST: + return self._locals.get(name, super(WritableDictUnion, self).__getitem__(name)) + try: + return super(WritableDictUnion, self).__getitem__(name) + except KeyError: + if name in self._locals: + return self._locals[name] + raise KeyError, name + def __setitem__(self, name, value): + ''' + ''' + props = getattr(self, '__modify_props__', 0) + if props & WRITE_DISABLED: + raise TypeError, 'can\'t add values to a dict union object (writing is disabled).' + elif props & WRITE_LOCAL: + self._locals[name] = value + else: + try: + if props & WRITE_TO_FIRST_OWNER: + self.getallcontainersof(name)[0][name] = value + else: + self.getallcontainersof(name)[-1][name] = value + except KeyError: + if props & WRITE_NEW_TO_FIRST: + self.members()[0][name] = value + else: + self.members()[-1][name] = value + def __contains__(self, name): + ''' + ''' + if name in self._locals or super(WritableDictUnion, self).__contains__(name): + return True + return False + def __delitem__(self, name): + ''' + ''' + props = getattr(self, '__modify_props__', 0) + if props & DELETE_DISABLED: + raise TypeError, 'can\'t delete items (deletion is disabled).' + if props & DELETE_LOCAL and name in self._locals: + del self._locals[name] + elif not props & DELETE_LOCAL_ONLY: + if props & DELETE_FIRST: + del self.getallcontainersof(name)[0][name] + else: + del self.getallcontainersof(name)[-1][name] + else: + raise TypeError, 'can\'t delete from contained dicts.' + def __iter__(self): + ''' + ''' + seen = [] + props = getattr(self, '__modify_props__', 0) + if props & GET_LOCAL_FIRST: + for k in self._locals: + yield k + seen += [k] + for k in super(WritableDictUnion, self).__iter__(): + if k not in seen: + yield k + seen += [k] + if not props & GET_LOCAL_FIRST: + for k in self._locals: + if k not in seen: + yield k + + + #-------------------------------------------------------DictTypeUnion--- # WARNING: this is not done! class DictTypeUnion(DictUnion, dict): @@ -390,5 +510,21 @@ class ObjectUnion(object): +if __name__ == '__main__': + d0 = {'a':1, 'b':2} + d1 = {'c':'!!!!!', 'b':'x'} + + D = WritableDictUnion(d0, d1) + + D['b'] = '*****' + + print D.todict() + print d0, d1 + + print 'a' in D + + + + #======================================================================= # vim:set ts=4 sw=4 nowrap : diff --git a/pli/pattern/proxy/generic.py b/pli/pattern/proxy/generic.py index 6166bca..de1af28 100644 --- a/pli/pattern/proxy/generic.py +++ b/pli/pattern/proxy/generic.py @@ -1,7 +1,7 @@ #======================================================================= __version__ = '''0.1.19''' -__sub_version__ = '''20050401013137''' +__sub_version__ = '''20050405190239''' __copyright__ = '''(c) Alex A. Naanou 2003''' @@ -486,6 +486,8 @@ class InheritAndOverrideProxy(CachedProxyMixin, ProxyWithReprMixin): those will require the rewrite of these methods in the metaclass; this can be defined in the __proxy_metaclass__ class variable. + NOTE: this will only override methods. instance attribute + substitution can not be done... Attributes: __proxy__ - the class used to create the proxy. diff --git a/pli/pattern/tree/__init__.py b/pli/pattern/tree/__init__.py new file mode 100755 index 0000000..db28e21 --- /dev/null +++ b/pli/pattern/tree/__init__.py @@ -0,0 +1,11 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20040115052440''' +__copyright__ = '''(c) Alex A. Naanou 2003''' + + +#----------------------------------------------------------------------- + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/pli/pattern/tree/acquisitional.py b/pli/pattern/tree/acquisitional.py new file mode 100755 index 0000000..6696066 --- /dev/null +++ b/pli/pattern/tree/acquisitional.py @@ -0,0 +1,280 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20050411062343''' +__copyright__ = '''(c) Alex A. Naanou 2003''' + + +#----------------------------------------------------------------------- + +import pli.pattern.mixin.mapping as mapping +import pli.pattern.proxy.generic as proxy +import pli.logictypes as logictypes + + +#----------------------------------------------------------------------- +# TODO rename this module to something like acquisitional.py +# TODO parant resolution protocol (if not present use attr). +# TODO acquisition cut (mignt be done by the above...) +# TODO might be good to do a recursive depth iterator... +# TODO path modification and resolution priority... +# TODO wrap the return of __getitem__ +# - add context data (for both the origin (?) and current +# contexts) +# TODO revise the module structure... +# +# +# AbstractAcquisitionalNode - create, resolve up, basic proto, mixin +# AbstractAcquisitionalNodeMapping - mapping, mixin +# BasicNodeMapping - specific, config, mixin +# Directory (fs mixin) +# ... +# BasicNode - specific, config, mixin +# File (fs mixin) +# ... +# BasicNodeReference - mixin +# NodeContextProxy - mixin, basic proto +# +# +# TODO make this an instance of AbstractTreeNode... +class AbstractAcquisitionalNode(object): + ''' + ''' + pass + + +class AcquisitionalNodeMixin(AbstractAcquisitionalNode): + ''' + ''' + def __acquire__(self): + ''' + ''' + parent = getattr(self, 'parent', None) + if parent != None: + yield parent + for o in parent.__acquire__(): + yield o + + +#-----------------------------------------------------------BasicNode--- +class BasicNode(AcquisitionalNodeMixin): + ''' + ''' +## parent = None + + def __init__(self, parent, name, *p, **n): + ''' + ''' + self.__name__ = name +## self.parent = None + if parent != None: + self.parent = parent + parent.children[name] = self +## self.parent = None + self.children = {} + + +#--------------------------------------------------BasicNodeReference--- +##!!! REWRITE !!!## +class BasicNodeReference(BasicNode, proxy.InheritAndOverrideProxy): + ''' + ''' + ##!!!!! FIND A BETTER (MORE GENTLE) WAY TO DO THIS !!!!!## + # TODO avoid duble writes... + def __init__(self, target, parent, name, *p, **n): + ''' + ''' + # NOTE: the way the __init__ is called is a workaround pythons + # type check on first arg of method... + # NOTE: the class is passed up to avoid changing the targets + # state (NS). + BasicNode.__dict__['__init__'](self.__class__, parent, name, *p, **n) + # this is to correcting a little side-effect... (in the above + # code we passed the class, thus it is registred as a child, + # not the original rarget...) + # TODO avoid duble writes... + if hasattr(self, 'parent') and self.parent != None: + self.parent.children[name] = self +## self.parent.children[name] = self + + +#------------------------------------------------------ProxyNameSpace--- +class ProxyNameSpace(logictypes.WritableDictUnion, dict): + ''' + ''' + __modify_props__ = logictypes.GET_LOCAL_FIRST \ + | logictypes.WRITE_LOCAL \ + | logictypes.DELETE_FIRST + + +#----------------------------------------------------NodeContextProxy--- +class NodeContextProxy(BasicNode, proxy.InheritAndOverrideProxy): +##class NodeContextProxy(BasicNode, proxy.TransparentInheritAndOverrideProxy): + ''' + ''' +## __proxy_public_attrs__ = proxy.TransparentInheritAndOverrideProxy.__proxy_public_attrs__ \ +## + ( +## 'parent', +## ) + + ##!!!!! FIND A BETTER (MORE GENTLE) WAY TO DO THIS !!!!!## + # TODO avoid duble writes... + def __init__(self, target, context, *p, **n): + ''' + ''' +## self.__dict__ = ProxyNameSpace(self.__dict__) +## BasicNode.__dict__['__init__'](self.__class__, getattr(context, 'parent', None), self.__name__, *p, **n) + self.__class__.parent = context + + +#----------------------------------------------------BasicNodeMapping--- +class BasicNodeMapping(BasicNode, mapping.Mapping): + ''' + ''' + __node_reference_class__ = BasicNodeReference + + def __getitem__(self, name): + ''' + ''' + return self.children[name] + # WARNING: this will cause proxy nesting... + def __setitem__(self, name, value): + ''' + ''' + if isinstance(value, BasicNode): + BasicNodeReference(value, self, name) + else: + self.children[name] = value + def __delitem__(self, name): + ''' + ''' + del self.children[name] + def __iter__(self): + ''' + ''' + return self.children.__iter__() + + +#----------------------------------------------BasicAcquisitionalNode--- +class BasicAcquisitionalNode(BasicNodeMapping): + ''' + ''' + # signature: + # __context_wrapper__(cur_context, res) +## __context_wrapper__ = None + __context_wrapper__ = NodeContextProxy + # WARNING: be ware of acquisition loops! + # TODO resolve acquisition loops... + def __getitem__(self, name): + ''' + ''' + wrapper = getattr(self, '__context_wrapper__', None) + try: + if wrapper == None: + return super(BasicAcquisitionalNode, self).__getitem__(name) + else: + return wrapper(super(BasicAcquisitionalNode, self).__getitem__(name), self) + except KeyError: + if self.parent == None: + raise + if wrapper == None: + return self.parent[name] + else: + return wrapper(self.parent[name], self) + + +#----------------------------------------------------------------------- +if __name__ == '__main__': + import pickle + + # test node creation... + root = BasicAcquisitionalNode(None, 'root') + + BasicAcquisitionalNode(root, 'a') + + BasicAcquisitionalNode(root, 'b') + BasicAcquisitionalNode(root, 'c') + + # test node access... + BasicAcquisitionalNode(root['a'], 'x') + BasicAcquisitionalNode(root['a'], 'y') + BasicAcquisitionalNode(root['a'], 'z') + + print '''root['a']''' + print root['a'] + print '''root['a']['x']''' + print root['a']['x'] + print '''root['a']['x']['b']''' + print root['a']['x']['b'] + print '!!!!!!!' + print root['a']['x']['b'] + print '''root['b']''' + print root['b'] + print '''root['b']['a']['x']['b']''' + print root['b']['a']['x']['b'] + + print + +## for n in root['b']['a']['x']['b']['a'].__acquire__(): +## print n.__name__, '/', + + + # test direct node assignment... + root['c']['123'] = 123 + root['c']['root'] = root + + print + + print root + print root['c']['root'] + +## print root.parent + print root['c']['root'].parent + + print + + print root['c']['root']['b']['a']['x']['b'] + + root['b']['rrr'] = root['c']['root'] + + print root['b']['rrr']['b']['a']['x']['b'] + + print root['c']['root'].parent + +## for n in root['b']['rrr']['b']['a']['x'].__acquire__(): +## print n.__name__, '/', + + root2 = pickle.loads(pickle.dumps(root)) + + # test node removal.... + del root['b']['rrr'] + + # test for possible del side-effects... + print root['c']['root'].parent + print root['c'] + + print + print + + # raw pickle test... +## root2 = pickle.loads(pickle.dumps(root)) + + print root2['a'] + print root2['a']['x'] + print root2['a']['x']['b'] + print root2['b'] + print root2['b']['a']['x']['b'] + print root2['c']['root']['b']['a']['x']['b'] + print root2['b']['rrr']['b']['a']['x']['b'] + print root2['c']['root'].parent + print root2['c'] + + + + + + + + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/pli/pattern/tree/fs.py b/pli/pattern/tree/fs.py new file mode 100755 index 0000000..db28e21 --- /dev/null +++ b/pli/pattern/tree/fs.py @@ -0,0 +1,11 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20040115052440''' +__copyright__ = '''(c) Alex A. Naanou 2003''' + + +#----------------------------------------------------------------------- + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/setup.py b/setup.py index 39da121..ffabc23 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #======================================================================= __version__ = '''0.1.12''' -__sub_version__ = '''20041009203657''' +__sub_version__ = '''20050411062518''' __copyright__ = '''(c) Alex A. Naanou 2003''' @@ -80,7 +80,7 @@ setup( 'pli.pattern.state', 'pli.pattern.store', 'pli.pattern.mixin', -## 'pli.pattern.tree', + 'pli.pattern.tree', 'pli.serialize', ], ## py_modules = [], -- 2.11.4.GIT