from aquarium.util.ContainerClass import ContainerClass
class ShouldSkipMe(ValueError):
"""A step may raise this if it wishes to not be run."""
pass
class InvalidConfigurationError(ValueError):
"""A step may raise this if it detects that the current configuration is
so broken it cannot run at all."""
pass
class Wizard:
name = "Generic Wizard"
steps = []
reviewScreen = "wizard_review"
debugMessages = []
def __call__(self, callingStep=None, action=None):
self.sanityCheck(callingStep, action)
self.callingStep = callingStep
if callingStep is None:
startStep = 0
else:
try:
startStep = self.findStepByName(self.steps, callingStep.getName()) -1
except ValueError:
raise ValueError(
"The calling step (%s) could not be found in the list "
"of steps (%r)" %(callingStep.getName(), self.steps))
lastStep = len(self.steps)
# BVZ: This is filthy filthy code. Wash your hands after looking at
# this and delete it if no one else is looking.
try:
direction = int(self._ctx.form["d"])
except (KeyError, IndexError):
direction = 1
if action == "Next":
startStep += 1
elif action == "Prev" or direction == -1:
# This is a weird way of handling previous across SkipMe
if direction != -1:
startStep -= 1
lastStep = -1
direction = -1
elif action == "Cancel":
self.cancel()
for stepNum in range(startStep, lastStep, direction):
try:
step = self.steps[stepNum]['screenName']
except IndexError:
raise IndexError("Step number%s is invalid" %(stepNum))
try:
if self.callingStep and self.callingStep.getName() == step:
self.callingStep.run()
else:
if direction != 1:
redirect_qs = {"d": direction}
else:
redirect_qs = {}
self._ctx.iLib.redirectSeeOther(step, redirect_qs)
except ShouldSkipMe:
self.debug("Step (%s) asked to be skipped" %(step))
except InvalidConfigurationError:
raise NotImplementedError
else:
raise NotImplementedError("Passed the last step of the Wizard.\
Did you properly format your list of steps?")
def findStepByName(self, steps, callerName):
position = 0
for iItem in steps:
position += 1
if callerName == iItem['screenName']:
return position
return 0
def getReviewStrings(self):
"""Returns list of strings that are result of calling review() on all
steps."""
reviewStrings = []
for stepNum in range(0, len(self.steps)):
try:
step = self._ctx.iLib.aquariumFactory(
"screen." + self.steps[stepNum]['screenName'])
except ShouldSkipMe:
continue
except InvalidConfigurationError:
raise
if step.review():
reviewStrings.append(step.review())
return reviewStrings
def sanityCheck(self, callingStep, action):
"""Ensures to the best of its ability that the subclass has defined
the necessary methods and properties to create a true wizard."""
if not hasattr(self, "commit"):
raise NotImplementedError("You have not defined a commit method")
if not hasattr(self, "cancel"):
raise NotImplementedError("You have not defined a cancel method")
if len(self.steps) < 1:
raise ValueError("Your list of steps is empty")
if bool(callingStep) ^ bool(action):
raise ValueError("Wizard called with only one of callingStep " \
"and action. You must specify both or neither")
self.debug("Sanity check passes")
def debug(self, msg):
self.debugMessages.append("Wizard: %s" %(msg))
|