diff options
Diffstat (limited to 'intern/python/modules/mcf/utils/hier_rx.py')
-rw-r--r-- | intern/python/modules/mcf/utils/hier_rx.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/intern/python/modules/mcf/utils/hier_rx.py b/intern/python/modules/mcf/utils/hier_rx.py new file mode 100644 index 00000000000..3770f0bab22 --- /dev/null +++ b/intern/python/modules/mcf/utils/hier_rx.py @@ -0,0 +1,201 @@ +''' +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 + |