Splitter section¶
A splitter pipeline section lets you branch a pipeline into
2 or more sub-pipelines. The splitter section blueprint name
is
collective.transmogrifier.sections.splitter
.
A splitter section takes 2 or more pipeline definitions, and sends the items from the previous section through each of these sub-pipelines, each with it's own copy [*] of the items:
>>> emptysplitter = """
... [transmogrifier]
... pipeline =
... source
... splitter
... logger
...
... [source]
... blueprint = collective.transmogrifier.sections.tests.rangesource
... size = 3
...
... [splitter]
... blueprint = collective.transmogrifier.sections.splitter
... pipeline-1 =
... pipeline-2 =
...
... [logger]
... blueprint = collective.transmogrifier.sections.logger
... name = logger
... level = INFO
... """
>>> registerConfig(u'collective.transmogrifier.sections.tests.emptysplitter',
... emptysplitter)
>>> transmogrifier(u'collective.transmogrifier.sections.tests.emptysplitter')
>>> print handler
logger INFO
{'id': 'item-00'}
logger INFO
{'id': 'item-00'}
logger INFO
{'id': 'item-01'}
logger INFO
{'id': 'item-01'}
logger INFO
{'id': 'item-02'}
logger INFO
{'id': 'item-02'}
Although the pipeline definitions in the splitter are empty,
we end up with 2 copies of every item in the pipeline as
both splitter pipelines get to process a copy. Splitter
pipelines are defined by options starting with
pipeline-
.
Normally you'll use conditions to identify items for each
sub-pipe, making the splitter the pipeline equivalent of an
if/elif statement. Conditions are optional and use the
pipeline option name plus
-condition
:
>>> evenoddsplitter = """
... [transmogrifier]
... pipeline =
... source
... splitter
... logger
...
... [source]
... blueprint = collective.transmogrifier.sections.tests.rangesource
... size = 3
...
... [splitter]
... blueprint = collective.transmogrifier.sections.splitter
... pipeline-even-condition = python:int(item['id'][-2:]) % 2
... pipeline-even = even-section
... pipeline-odd-condition = not:${splitter:pipeline-even-condition}
... pipeline-odd = odd-section
...
... [odd-section]
... blueprint = collective.transmogrifier.sections.inserter
... key = string:even
... value = string:The even pipe
...
... [even-section]
... blueprint = collective.transmogrifier.sections.inserter
... key = string:odd
... value = string:The odd pipe
...
... [logger]
... blueprint = collective.transmogrifier.sections.logger
... name = logger
... level = INFO
... """
>>> registerConfig(u'collective.transmogrifier.sections.tests.evenodd',
... evenoddsplitter)
>>> handler.clear()
>>> transmogrifier(u'collective.transmogrifier.sections.tests.evenodd')
>>> print handler
logger INFO
{'even': 'The even pipe', 'id': 'item-00'}
logger INFO
{'id': 'item-01', 'odd': 'The odd pipe'}
logger INFO
{'even': 'The even pipe', 'id': 'item-02'}
Conditions are expressed as TALES statements, and have access to:
item
|
the current pipeline item |
transmogrifier
|
the transmogrifier |
name
|
the name of the splitter section |
pipeline
|
the name of the splitter pipeline this condition
belongs to (including the
pipeline-
prefix)
|
options
|
the splitter options |
modules
|
sys.modules |
Warning
Although the splitter section employs some techniques to avoid memory bloat, if any contained section swallows items (so taking them from the previous section without passing them on), runs the risk of pulling all remaining items into the splitter buffer as a next match for the contained pipeline is being sought.
You can avoid this by not using sections that discard items within a splitter; place these before or after a splitter section. Better still, use a correct condition in the splitter configuration that won't include the items to discard in the first place.
[*] | Note that copy.deepcopy is used on all items. This will fail on items containing file handles, modules or other non-copyable values. See the copy module documentation. |