1.3. satchless.process — multi-step processes

The purpose of this module is to aid with creation of multi-step processes such as online store checkout. We solve this by providing a step class and a process class that are typically bound to data that is persisted between the steps. Each time a single step is completed you can ask the manager which step needs to be completed next until the whole process is considered complete.

We do not define what a step is. It could be a Django view or a call to an external API. It can be anything as long as it can determine its own state (usually passed to its constructor by the process manager) and decide whether it’s valid or not.

1.3.1. Available Types

exception satchless.process.InvalidData

An exception raised when a step is invalid.

class satchless.process.Step

A single step in a multi-step process.

class satchless.process.ProcessManager

A multi-step process manager.

1.3.2. Step Objects

class satchless.process.Step

A Step instance is a single step in a process. For example a single checkout step.

Instance methods:

satchless.process.__str__()

Returns the step ID. The same step must always return the same ID and the ID has to be unique within the process.

Default implementation will raise an NotImplementedError exception.

satchless.process.validate()

Validates the step and raises InvalidData if the step requires further attention.

Default implementation will raise an NotImplementedError exception.

Example use:

>>> from satchless.process import InvalidData, Step
>>> class LicenseAcceptance(Step):
...     def __init__(self, data): self.data = data
...     def __str__(self): return 'license'
...     def validate(self):
...         if not self.data.get('license_accepted'):
...             raise InvalidData('Nice try')
...
>>> data = {}
>>> step = LicenseAcceptance(data)
>>> str(step)
'license'
>>> step.validate()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in validate
satchless.process.InvalidData: Nice try
>>> data['license_accepted'] = True
>>> step.validate()

1.3.3. ProcessManager Objects

class satchless.process.ProcessManager

A ProcessManager instance represents a single process. For example the checkout process in a typical online store.

Instance methods:

ProcessManager.__iter__()

Returns an iterator that yields Step objects that define the process.

Default implementation will raise an NotImplementedError exception.

ProcessManager.__getitem__(step_id)

Returns the Step object whose Step.__str__() method returns step_id.

If no such step is found, KeyError will be raised.

ProcessManager.is_complete()

Returns True if all the steps of the process are valid. False otherwise.

ProcessManager.get_next_step()

Returns the first step that does not validate.

If all steps are valid, None is returned.

ProcessManager.get_errors()

Returns a dict whose keys are IDs of steps that did not validate and the values are the exceptions raised by the steps.

Example use:

>>> from satchless.process import InvalidData, ProcessManager, Step
>>> class LicenseAcceptance(Step):
...     def __init__(self, data): self.data = data
...     def __str__(self): return 'license'
...     def __repr__(self): return 'LicenseAcceptance(%r)' % (self.data, )
...     def validate(self):
...         if not self.data.get('license_accepted'):
...             raise InvalidData('Nice try')
...
>>> class SingleStepProcessManager(ProcessManager):
...     def __init__(self, data): self.data = data
...     def __iter__(self):
...         yield LicenseAcceptance(self.data)
...
>>> data = {}
>>> process = SingleStepProcessManager(data)
>>> list(process)
[LicenseAcceptance({})]
>>> process['license']
LicenseAcceptance({})
>>> process.is_complete()
False
>>> process.get_next_step()
LicenseAcceptance({})
>>> process.get_errors()
{'license': InvalidData('Nice try',)}
>>> data['license_accepted'] = True
>>> process.is_complete()
True
>>> process.get_next_step()
>>> process.get_errors()
{}