Source code for diffpy.srfit.equation.visitors.swapper

#!/usr/bin/env python
##############################################################################
#
# diffpy.srfit      by DANSE Diffraction group
#                   Simon J. L. Billinge
#                   (c) 2008 The Trustees of Columbia University
#                   in the City of New York.  All rights reserved.
#
# File coded by:    Chris Farrow
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE_DANSE.txt for license information.
#
##############################################################################
"""Swapper for replacing a Literal in an equation with another Literals."""

__all__ = ["Swapper"]

from diffpy.srfit.equation.visitors.visitor import Visitor


[docs] class Swapper(Visitor): """Swapper for swapping out one literal for another in a literal tree. Note that this cannot swap out a root node of a literal tree. This case must be tested for explicitly. Attributes ---------- newlit The literal to be placed into the literal tree. oldlit The literal to be replaced. """ def __init__(self, oldlit, newlit): """Initialize. Attributes ---------- oldlit The literal to be replaced. newlit The literal to be placed into the literal tree. See the class for how the replacement takes place. """ self.newlit = newlit self.oldlit = oldlit self._swap = False return
[docs] def onArgument(self, arg): """Process an Argument node. Tell the parent to swap the old Argument with the replacement Literal. """ if arg is self.oldlit: self._swap = True return
[docs] def onOperator(self, op): """Process an Operator node. Tell the parent to swap the old Operator with the replacement Literal. """ # Check to see if we need to swap out this Operator. If so, then we # don't need to traverse into its arguments. if op is self.oldlit: self._swap = True return # Now traverse into the arguments. for literal in op.args: literal.identify(self) # If we've been told to swap out a literal, then we must do it in-place # because the order of op.args matters. if self._swap: oldlit = self.oldlit newlit = self.newlit while oldlit in op.args: # Record the index idx = op.args.index(oldlit) # Remove the literal del op.args[idx] # Remove op as an observer. A KeyError will be raised if we # attempt to remove the same observer more than once, which # might happen if the oldlit appears multiple times in op.args. try: oldlit.removeObserver(op._flush) except KeyError: pass # Validate the new literal. If it fails, we need to restore the # old one try: op._loopCheck(newlit) except ValueError: # Restore the old literal op.args.insert(idx, oldlit) oldlit.addObserver(op._flush) raise # If we got here, then go on with replacing the literal op.args.insert(idx, newlit) newlit.addObserver(op._flush) op._flush(other=()) self._swap = False return
[docs] def onEquation(self, eq): """Process an Equation node. This looks at the equation itself as well as the root. """ if eq is self.oldlit: self._swap = True return # If the newlit is the root, then swap that out and move on. if eq.root is self.oldlit: eq.setRoot(self.newlit) return # Now move into the equation. We have to do a _loopCheck to make sure # that we won't have any loops in the equation. eq._loopCheck(self.newlit) eq.root.identify(self) # Reset the root in case anything changed underneath. eq.setRoot(eq.root) return
# End of file