This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/intern/python/modules/mcf/utils/hier_rx.py
Hans Lambermont 12315f4d0e Initial revision
2002-10-12 11:37:38 +00:00

202 lines
5.5 KiB
Python

'''
Simple Hierarchic Walking functions for use with hierobj-type objects.
Provide for recurse-safe processing. Currently only provide depth-first
processing, and don't provide means for ignoring branches of the tree
during processing. For an example of breadth-first processing, see
mcf.pars.int.index.indutils. For more complex hierarchic processing,
see the mcf.walker package.
Originally these functions were only methods of the hierobj class (they
still are methods of it). I've split them out to allow them to be
imported selectively by other classes (some classes will only want
the simple walking functions, and not want to be bothered with the
methods which hierobj uses to keep track of its particular internal
structures.
'''
def hier_rapply(self, function,arglist=None,argdict={},moreattr = '__childlist__'):
'''
Safely apply a function to self and all children for
the function's side effects. Discard the return values
that function returns.
function
function to apply
arglist
(self,)+arglist is the set of arguments passed to function
argdict
passed as namedargs to the function
moreattr
the attribute representing the children of a node
'''
alreadydone = {}
tobedone = [self]
if arglist or argdict:
if not arglist: arglist=[self]
else:
arglist.insert(0,self) # we could insert anything... self is convenient
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
arglist[0]=object
apply(function,tuple(arglist),argdict)
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
else: # no arglist or argdict
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
function(object)
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
def hier_rreturn(self, function,arglist=None,argdict={},moreattr = '__childlist__'):
'''
Safely apply a function to self and all children,
collect the results in a list and return.
function
function to apply
arglist
(self,)+arglist is the set of arguments passed to function
argdict
passed as namedargs to the function
moreattr
the attribute representing the children of a node
'''
alreadydone = {}
tobedone = [self]
results = []
if arglist or argdict:
if not arglist: arglist=[self]
else:
arglist.insert(0,self) # or anything you feel like
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
arglist[0]=object
results.append(apply(function,tuple(arglist),argdict))
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
else:
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
results.append(function(object))
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
return results
def hier_rgetattr(self, attrname, multiple=1, moreattr = '__childlist__'):
'''
Recursively collect the values for attrname and
return as a list.
attrname
attribute to collect
arglist
(self,)+arglist is the set of arguments passed to function
argdict
passed as namedargs to the function
moreattr
the attribute representing the children of a node
'''
alreadydone = {}
tobedone = [self]
results = []
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
try:
if multiple:
results.append(getattr(object, attrname))
else:
return getattr(object, attrname)
except AttributeError:
pass
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
return results
def hier_rmethod(self, methodname,arglist=(),argdict={},moreattr = '__childlist__'):
'''
return the result of calling every object's method methodname,
as for hier_rreturn otherwise.
methodname
method to call
arglist
(self,)+arglist is the set of arguments passed to function
argdict
passed as namedargs to the function
moreattr
the attribute representing the children of a node
'''
alreadydone = {}
tobedone = [self]
results = []
while tobedone:
object = tobedone[0]
try:
alreadydone[id(object)]
# We've already processed this object
except KeyError:
# We haven't processed this object
alreadydone[id(object)]=1
try:
results.append(apply(getattr(object,methodname),arglist,argdict))
except:
pass
try:
tobedone[1:1]=getattr(object,moreattr)
except AttributeError:
# if the object isn't a hierobj, we don't need to recurse into it.
pass
del(tobedone[0])
return results