Initial revision
This commit is contained in:
133
intern/python/modules/mcf/utils/hierobj.py
Normal file
133
intern/python/modules/mcf/utils/hierobj.py
Normal file
@@ -0,0 +1,133 @@
|
||||
'''
|
||||
Generic Hierarchic Objects Module
|
||||
Hierobj's store their children (which can be anything) in their
|
||||
__childlist__ attribute, and provide methods for walking the
|
||||
hierarchy, either collecting results or not.
|
||||
|
||||
The index function returns an index of the objects (effectively a
|
||||
flattened copy of the hierarchy)
|
||||
|
||||
97-03-17 Added ability to pass arguments to hier_rapply and hier_rreturn.
|
||||
97-10-31 Removed dependencies on mcf.store
|
||||
'''
|
||||
import copy,types
|
||||
import singletonlist, hier_rx
|
||||
|
||||
class Hierobj:
|
||||
'''
|
||||
An abstract class which handles hierarchic functions and information
|
||||
# remade as a DAG 97-04-02, also reduced memory overhead for
|
||||
hier-r* functions by using while-del-IndexError construct versus
|
||||
for loop (probably makes it slower though)
|
||||
If you require a true hierarchy, use the TrueHierobj class below...
|
||||
'''
|
||||
def __init__(self, parent=None, childlist=None):
|
||||
if parent is None: # passed no parents
|
||||
self.__dict__['__parent__'] = []
|
||||
elif type(parent) == types.ListType: # passed a list of parents
|
||||
self.__dict__['__parent__'] = parent
|
||||
else: # passed a single parent
|
||||
self.__dict__['__parent__'] = [parent]
|
||||
self.__dict__['__childlist__'] = childlist or []
|
||||
for child in self.__childlist__:
|
||||
try:
|
||||
child.__parent__.append(self)
|
||||
except:
|
||||
pass
|
||||
# import simple hierarchic processing methods
|
||||
hier_rapply = hier_rx.hier_rapply
|
||||
hier_rreturn = hier_rx.hier_rreturn
|
||||
hier_rgetattr = hier_rx.hier_rgetattr
|
||||
hier_rmethod = hier_rx.hier_rmethod
|
||||
|
||||
|
||||
def hier_addchild(self, child):
|
||||
'''
|
||||
Add a single child to the childlist
|
||||
'''
|
||||
self.__childlist__.append(child)
|
||||
try:
|
||||
# Hierobj-aware child
|
||||
child.__parent__.append(self) # raises error if not hier_obj aware
|
||||
except (TypeError, AttributeError):
|
||||
# Non Hierobj-aware child
|
||||
pass
|
||||
append = hier_addchild
|
||||
def hier_remchild(self, child):
|
||||
'''
|
||||
Breaks the child relationship with child, including the
|
||||
reciprocal parent relationship
|
||||
'''
|
||||
try:
|
||||
self.__childlist__.remove(child)
|
||||
try:
|
||||
child.hier_remparent(self) # if this fails, no problem
|
||||
except AttributeError: pass
|
||||
except (AttributeError,ValueError):
|
||||
return 0 # didn't manage to remove the child
|
||||
return 1 # succeeded
|
||||
def hier_remparent(self, parent):
|
||||
'''
|
||||
Normally only called by hier_remchild of the parent,
|
||||
just removes the parent from the child's parent list,
|
||||
but leaves child in parent's childlist
|
||||
'''
|
||||
try:
|
||||
self.__parent__.remove(parent)
|
||||
except (AttributeError,ValueError):
|
||||
return 0
|
||||
return 1
|
||||
def hier_replacewith(self,newel):
|
||||
'''
|
||||
As far as the hierarchy is concerned, the new element
|
||||
is exactly the same as the old element, it has all
|
||||
the same children, all the same parents. The old
|
||||
element becomes completely disconnected from the hierarchy,
|
||||
but it still retains all of its references
|
||||
|
||||
For every parent, replace this as a child
|
||||
For every child, replace this as the parent
|
||||
'''
|
||||
for parent in self.__parent__:
|
||||
try:
|
||||
parent.hier_replacechild(self, newel)
|
||||
except AttributeError:
|
||||
pass
|
||||
for child in self.__childlist__:
|
||||
try:
|
||||
child.hier_replaceparent(self,parent)
|
||||
except AttributeError:
|
||||
pass
|
||||
def hier_replaceparent(self, oldparent, newparent):
|
||||
ind = self.__parent__.index(oldparent)
|
||||
self.__parent__[ind] = newparent
|
||||
def hier_replacechild(self, oldchild, newchild):
|
||||
ind = self.__childlist__.index(oldchild)
|
||||
self.__childlist__[ind] = newchild
|
||||
|
||||
class TrueHierobj(Hierobj):
|
||||
'''
|
||||
An inefficient implementation of an Hierobj which limits the
|
||||
__parent__ attribute to a single element. This will likely be
|
||||
_slower_ than an equivalent Hierobj. That will have to be fixed
|
||||
eventually.
|
||||
'''
|
||||
def __init__(self, parent=None, childlist=[]):
|
||||
if parent is None: # passed no parents
|
||||
self.__dict__['__parent__'] = singletonlist.SingletonList()
|
||||
else: # passed a single parent
|
||||
self.__dict__['__parent__'] = singletonlist.SingletonList(parent)
|
||||
self.__dict__['__childlist__'] = copy.copy(childlist)
|
||||
for child in self.__childlist__:
|
||||
try:
|
||||
child.__parent__.append(self)
|
||||
except:
|
||||
pass
|
||||
|
||||
def index(grove):
|
||||
'''
|
||||
Returns a flattened version of the grove
|
||||
'''
|
||||
return grove.hier_rreturn(lambda x: x)
|
||||
|
||||
|
Reference in New Issue
Block a user