Create and read your first bundle

In this tutorial, we create a configuration bundle, export it to XML, and read it back. We then create a result bundle with a status property.

Install the package

In a Python 3.11 through 3.14 virtual environment, install the package:

python -m pip install momotor-bundles

Start Python in that environment. We use a temporary directory for the files:

>>> from contextlib import closing
>>> from pathlib import Path
>>> from tempfile import TemporaryDirectory
>>> workspace = TemporaryDirectory()
>>> output = Path(workspace.name)

Create a configuration

First, allocate a configuration bundle and an option that belongs to it:

>>> from momotor.bundles import ConfigBundle
>>> from momotor.bundles.elements.options import Option
>>> config = ConfigBundle()
>>> timeout = Option(config).create(name='timeout', domain='example', value=10)
>>> config = config.create(id='example-config', options=[timeout])
>>> config.get_option_value('timeout', domain='example')
10

create() initializes the bundle once. Each element receives its owning bundle as its constructor argument.

Export the configuration

Now, write the configuration to XML:

>>> from momotor.bundles.const import BundleFormat
>>> config.to_file(output / 'config.xml', pretty_xml=True) == BundleFormat.XML
True
>>> (output / 'config.xml').is_file()
True

The export closes config. We load a new instance to read the saved data.

Read the saved configuration

Use closing() to release the loaded bundle when the block ends:

>>> with closing(ConfigBundle.from_file_factory(output / 'config.xml')) as loaded:
...     print(loaded.id)
...     print(loaded.get_option_value('timeout', domain='example'))
example-config
10

To inspect an unknown bundle type, use Bundle.from_file_factory(). It selects the concrete bundle class from the XML root element.

Create a result bundle

Next, create a result for a step named first:

>>> from momotor.bundles import ResultsBundle
>>> from momotor.bundles.elements.result import Result
>>> from momotor.bundles.elements.properties import Property
>>> results = ResultsBundle()
>>> status = Property(results).create(name='status', value='OK')
>>> first = Result(results).create(step_id='first', outcome='pass', properties=[status])
>>> results = results.create(results=[first])
>>> results.to_file(output / 'result.xml', pretty_xml=True) == BundleFormat.XML
True

Read the result by its step ID:

>>> with closing(ResultsBundle.from_file_factory(output / 'result.xml')) as loaded:
...     print(loaded.results['first'].outcome)
...     print(loaded.results['first'].get_property_value('status'))
pass
OK

Finally, remove the temporary files:

>>> workspace.cleanup()

See Content and attachments for file attachments and Elements for element creation and recreation.