capellambse.loader package

The MelodyLoader loads and provides access to a Capella model.

It is using LXML internally to efficiently parse and navigate through the Capella-generated XML files. For more information about LXML, see the LXML Documentation.

Submodules

capellambse.loader.core module

Helps loading Capella models (including fragmented variants).

exception capellambse.loader.core.CorruptModelError

Bases: Exception

Raised when the model is corrupted and cannot be processed safely.

In addition to the short description in the exception’s arguments, some validators may also produce additional information in the form of CRITICAL log messages just before this exception is raised.

class capellambse.loader.core.FragmentType

Bases: Enum

The type of an XML fragment.

OTHER = 3
SEMANTIC = 1
VISUAL = 2
class capellambse.loader.core.MelodyLoader

Bases: object

Facilitates extensive access to Polarsys / Capella projects.

__init__(path, entrypoint=None, *, resources=None, ignore_duplicate_uuids_and_void_all_warranties=False, **kwargs)

Construct a MelodyLoader.

Parameters:
  • path (str | PathLike | FileHandler) – The path argument to the primary file handler, or the primary file handler itself.

  • entrypoint (str | PurePosixPath | None) – The entry point into the model, i.e. the top-level .aird file. This must be located within the primary file handler.

  • resources (Mapping[str, FileHandler | str | PathLike | dict[str, Any]] | None) – Additional file handler instances that provide library resources that are referenced from the model.

  • ignore_duplicate_uuids_and_void_all_warranties (bool) – Ignore corruption due to duplicate UUIDs (see below).

  • kwargs (Any) – Additional arguments to the primary file handler, if necessary.

Raises:

CorruptModelError – If the model is corrupt. Currently the only kind of corruption that is detected is duplicated UUIDs (either within a fragment or across multiple fragments). It is possible to ignore this error and load the model anyways by setting the keyword-only argument ignore_duplicate_uuids_and_void_all_warranties to True. However, this will lead to strange behavior like random exceptions when searching or filtering, or accidentally working with the wrong object. If you try to make changes to the model, always make sure that you have an up to date backup ready. In order to prevent accidental overwrites with an even corrupter model, you must therefore also set the i_have_a_recent_backup keyword argument to True when calling save().

Return type:

None

activate_viewpoint(name, version)

Activate (reference) a viewpoint in the model.

Return type:

None

Parameters:
check_duplicate_uuids()
Return type:

None

Create a link to to_element from from_element.

Parameters:
  • from_element (_Element) – The source element of the link.

  • to_element (_Element) – The target element of the link.

  • include_target_type (bool | None) –

    Whether to include the target type in cross-fragment link definitions.

    If set to True, it will always be included, False will always exclude it. Setting it to None (the default) will use a simple heuristic: It will be added unless the from_element is in a visual-only fragment (aird / airdfragment).

    Regardless of this setting, the target type will never be included if the link does not cross fragment boundaries.

Returns:

A link in one of the formats described by follow_link(). Which format is used depends on whether from_element and to_element live in the the same fragment, and whether the include_target_type parameter is set.

Return type:

str

property filehandler: FileHandler

The file handler containing the original model.

This is a shorthand for self.resources["\0"].

find_fragment(element)

Find the name of the fragment that contains element.

Return type:

PurePosixPath

Parameters:

element (_Element)

Follow a single link and return the target element.

Valid links have one of the following two formats:

  • Within the same fragment, a reference is the target’s UUID prepended with a #, for example #7a5b8b30-f596-43d9-b810-45ab02f4a81c.

  • A reference to a different fragment contains the target’s xsi:type and the path of the fragment, relative to the current one. For example, to link from main.capella into frag/logical.capellafragment, the reference could be: org.polarsys.capella.core.data.capellacore:Constraint frag/logical.capellafragment#7a5b8b30-f596-43d9-b810-45ab02f4a81c. To link back to the project root from there, it could look like: org.polarsys.capella.core.data.pa:PhysicalArchitecture ../main.capella#26e187b6-72e7-4872-8d8d-70b96243c96c.

Parameters:
  • from_element (_Element | None) – The element at the start of the link. This is needed to verify cross-fragment links.

  • link (str) – A string containing a valid link to another model element.

Raises:
  • ValueError – If the link is malformed

  • FileNotFoundError – If the target fragment is not loaded (only applicable if from_element is not None and fragment is part of the link)

  • RuntimeError – If the expected xsi:type does not match the actual xsi:type of the found target

  • KeyError – If the target cannot be found

Return type:

_Element

Follow multiple links and return all results as list.

The format for an individual link is the same as accepted by follow_link(). Multiple links are separated by a single space.

If any target cannot be found, None will be inserted at that point in the returned list.

Parameters:
  • from_element (_Element | None) – The element at the start of the link. This is needed to verify cross-fragment links.

  • links (str) – A string containing space-separated links as described in follow_link().

  • ignore_broken (bool) – Ignore broken references instead of raising a KeyError.

Raises:
  • KeyError – If any link points to a non-existing target. Can be suppressed with ignore_broken.

  • ValueError – If any link is malformed.

  • RuntimeError – If any expected xsi:type does not match the actual xsi:type of the found target.

Return type:

list[_Element]

generate_uuid(parent, *, want=None)

Generate a unique UUID for a new child of parent.

The generated ID is guaranteed to be unique across all currently loaded fragments.

Parameters:
  • parent (_Element) – The parent element below which the new UUID will be used.

  • want (str | None) – Try this UUID first, and use it if it satisfies all other constraints. If it does not satisfy all constraints (e.g. it would be non-unique), a random UUID will be generated as normal.

Returns:

The new UUID.

Return type:

str

get_model_info()

Return information about the loaded model.

Return type:

ModelInfo

idcache_index(subtree)

Index the IDs of subtree.

This method must be called after adding subtree to the XML tree.

Parameters:

subtree (_Element) – The new element that was just inserted.

Return type:

None

idcache_rebuild()

Rebuild the ID caches of all loaded ModelFile instances.

Return type:

None

idcache_remove(subtree)

Remove the subtree from the ID cache.

This method must be called before actually removing subtree from the XML tree.

Parameters:

subtree (_Element) – The element that is about to be removed.

Return type:

None

iterall(*tags)

Iterate over all elements in all trees by tags.

Parameters:

tags (str) – Optionally restrict the iterator to the given tags.

Return type:

Iterator[_Element]

iterall_xt(*xtypes, trees=None)

Iterate over all elements in all trees by xsi:types.

Parameters:
  • xtypes (str) – Optionally restrict the iterator to these xsi:types

  • trees (Container[PurePosixPath] | None) – Optionally restrict the iterator to elements that reside in any of the named trees.

Return type:

Iterator[_Element]

iterancestors(element, *tags)

Iterate over the ancestors of element.

This method will follow fragment links back to the origin point.

Parameters:
  • element (_Element) – The element to start at.

  • tags (str) – Only yield elements that have the given XML tag.

Return type:

Iterator[_Element]

iterchildren_xt(element, *xtypes)

Iterate over the children of element.

This method will follow links into different fragment files and yield those elements as if they were direct children.

Parameters:
  • element (_Element) – The parent element under which to search for children.

  • xtypes (str) – Only yield elements whose xsi:type matches one of those given here. If no types are given, all elements are yielded.

Return type:

Iterator[_Element]

iterdescendants(root_elm, *tags)

Iterate over all descendants of root_elm.

This method will follow links into different fragment files and yield those elements as if they were part of the origin subtree.

Parameters:
  • root_elm (_Element) – The root element of the tree

  • tags (str) – Only yield elements with a matching XML tag. If none are given, all elements are yielded.

Return type:

Iterator[_Element]

iterdescendants_xt(element, *xtypes)

Iterate over all descendants of element by xsi:type.

This method will follow links into different fragment files and yield those elements as if they were part of the origin subtree.

Parameters:
  • element (_Element) – The root element of the tree

  • xtypes (str) – Only yield elements whose xsi:type matches one of those given here. If no types are given, all elements are yielded.

Return type:

Iterator[_Element]

new_uuid(parent, *, want=None)

Context Manager around generate_uuid().

This context manager yields a newly generated model-wide unique UUID that can be inserted into a new element during the with block. It tries to keep the ID cache consistent in some harder to manage edge cases, like exceptions being thrown. Additionally it checks that the generated UUID was actually used in the tree; not using it before the with block ends is an error and provokes an Exception.

Note

You still need to call idcache_index() on the newly inserted element!

Example usage:

>>> with ldr.new_uuid(parent_elm) as obj_id:
...     child_elm = parent_elm.makeelement("ownedObjects")
...     child_elm.set("id", obj_id)
...     parent_elm.append(child_elm)
...     ldr.idcache_index(child_elm)

If you intend to reserve a UUID that should be inserted later, use generate_uuid() directly.

Parameters:
  • parent (_Element) – The parent element below which the new UUID will be used.

  • want (str | None) – Request this UUID. The request may or may not be fulfilled; always use the actual UUID returned by the context manager.

Return type:

Generator[str, None, None]

referenced_viewpoints()
Return type:

Iterator[tuple[str, str]]

save(**kw)

Save all model files.

Parameters:

kw (Any) – Additional keyword arguments accepted by the file handler in use. Please see the respective documentation for more info.

Return type:

None

See also

capellambse.filehandler.local.LocalFileHandler.write_transaction

Accepted **kw when using local directories

capellambse.filehandler.git.GitFileHandler.write_transaction

Accepted **kw when using git:// and similar URLs

Notes

With a filehandler that contacts a remote location (such as the capellambse.filehandler.git.GitFileHandler with non-local repositories), saving might fail if the local state has gone out of sync with the remote state. To avoid this, always leave the update_cache parameter at its default value of True if you intend to save changes.

update_namespaces()

Update the namespace definitions on each fragment root.

This method is automatically called while saving to ensure that all namespaces necessary for the current model elements are registered on the fragment roots.

Return type:

None

write_tmp_project_dir()

Create a temporary directory with this model as Capella project.

This method writes the loaded project files (model and library files, if any) into a temporary directory. The main model is always placed in a subdirectory called “main_model”; any library models are placed in subdirectories named after the resource that the library was loaded from. Additionally, a .project file is generated in each subdirectory to allow direct import into Capella.

The directory yielded from this method can be directly used as the workspace of a Capella instance.

Return type:

Iterator[Path]

xpath(query, *, namespaces=None, roots=None)

Run an XPath query on all fragments.

Note that, unlike the iter_* methods, placeholder elements are not followed into their respective fragment.

Parameters:
  • query (str | XPath) – The XPath query

  • namespaces (Mapping[str, str] | None) – Namespaces used in the query. Defaults to all known namespaces.

  • roots (_Element | Iterable[_Element] | None) – A list of XML elements to use as roots for the query. Defaults to all tree roots.

Returns:

A list of all matching elements.

Return type:

list[lxml.etree._Element]

xpath2(query, *, namespaces=None, roots=None)

Run an XPath query and return the fragments and elements.

Note that, unlike the iter_* methods, placeholder elements are not followed into their respective fragment.

The tuples have the fragment where the match was found as first element, and the LXML element as second one.

Parameters:
  • query (str | XPath) – The XPath query

  • namespaces (Mapping[str, str] | None) – Namespaces used in the query. Defaults to all known namespaces.

  • roots (_Element | Iterable[_Element] | None) – A list of XML elements to use as roots for the query. Defaults to all tree roots.

Returns:

A list of 2-tuples, containing:

  1. The fragment name where the match was found.

  2. The matching element.

Return type:

list[tuple[pathlib.PurePosixPath, lxml.etree._Element]]

class capellambse.loader.core.ModelFile

Bases: object

Represents a single file in the model (i.e. a fragment).

__init__(filename, handler, *, ignore_uuid_dups)
Parameters:
Return type:

None

enumerate_uuids()

Enumerate all UUIDs used in this fragment.

Return type:

set[str]

property fragment_type: FragmentType
idcache_index(subtree)

Index the IDs of subtree.

Return type:

None

Parameters:

subtree (_Element)

idcache_rebuild()

Invalidate and rebuild this file’s ID cache.

Return type:

None

idcache_remove(source)

Remove the ID or all IDs below the source from the ID cache.

Return type:

None

Parameters:

source (str | _Element)

idcache_reserve(new_id)

Reserve the given ID for an element to be inserted later.

Return type:

None

Parameters:

new_id (str)

iterall_xt(xtypes)

Iterate over all elements in this tree by xsi:type.

Return type:

Iterator[_Element]

Parameters:

xtypes (Container[str])

unfollow_href(element_id)

Unfollow a fragment link and return the placeholder element.

If the given UUID is not linked to from this file, None is returned.

Return type:

_Element

Parameters:

element_id (str)

update_namespaces(viewpoints)

Update the current namespace map.

Parameters:

viewpoints (Mapping[str, str]) –

A mapping from viewpoint names to the version activated in the model.

If an element from a versioned Plugin is encountered, but the Plugin’s viewpoint is not activated in the model, an error is raised and no update is performed.

Return type:

None

write_xml(file, encoding='utf-8')

Write this file’s XML into the file specified by path.

Return type:

None

Parameters:

capellambse.loader.exs module

An Eclipse-like XML serializer.

The libxml2 XML serializer produces very different output from the one used by Capella. This causes a file saved by libxml2 to look vastly different, even though semantically nothing might have changed at all. This module implements a serializer which produces output like Capella does.

class capellambse.loader.exs.HasWrite

Bases: Protocol

A simple protocol to check for a writable file-like object.

__init__(*args, **kwargs)
write(chunk)
Return type:

int

Parameters:

chunk (bytes)

capellambse.loader.exs.serialize(tree, /, *, encoding='utf-8', errors='strict', line_length=80, siblings=None)

Serialize an XML tree.

The iterator returned by this function yields the serialized XML piece by piece.

Parameters:
  • tree (_Element | _ElementTree) – The XML tree to serialize.

  • encoding (str) – The encoding to use when generating XML.

  • errors (str) – The encoding error handling behavior.

  • line_length (float | int) – The number of characters after which to force a line break.

  • siblings (bool | None) – Also include siblings of the given subtree. Defaults to yes if ‘tree’ is an element tree, no if it’s a single element.

Returns:

An iterator that yields the serialized XML piece by piece.

Return type:

Iterator[str]

capellambse.loader.exs.to_bytes(tree, /, *, encoding='utf-8', errors='strict', declare_encoding=True)

Serialize an XML tree as a str.

At the start of the document, an XML processing instruction will be inserted declaring the used encoding. Pass declare_encoding=False to inhibit this behavior.

Parameters:
  • tree (_Element) – The XML tree to serialize.

  • encoding (str) – The encoding to use. An XML processing instruction will be inserted which declares the used encoding.

  • errors (str) – How to handle errors during encoding.

  • declare_encoding (bool)

Returns:

The serialized XML, encoded using encoding.

Return type:

bytes

capellambse.loader.exs.to_string(tree, /)

Serialize an XML tree as a str.

No XML processing instruction will be inserted at the start of the document.

Parameters:

tree (_Element) – The XML tree to serialize.

Returns:

The serialized XML.

Return type:

str

capellambse.loader.exs.write(tree, /, file, *, encoding='utf-8', errors='strict', line_length=80, siblings=False)

Write the XML tree to file.

Parameters:
  • tree (_Element | _ElementTree) – The XML tree to serialize.

  • file (HasWrite | PathLike | str | bytes) – An open file or a PathLike to write the XML into.

  • encoding (str) – The file encoding to use when opening a file.

  • errors (str) – Set the encoding error handling behavior of newly opened files.

  • line_length (float | int) – The number of characters after which to force a line break.

  • siblings (bool) – Also include siblings of the given subtree.

Return type:

None

capellambse.loader.modelinfo module

class capellambse.loader.modelinfo.ModelInfo

Bases: object

ModelInfo(url: ‘str | None’, title: ‘str | None’, entrypoint: ‘pathlib.PurePosixPath’, resources: ‘dict[str, filehandler.abc.HandlerInfo]’, capella_version: ‘str’, viewpoints: ‘dict[str, str]’)

__init__(url, title, entrypoint, resources, capella_version, viewpoints)
Parameters:
Return type:

None

capella_version: str
entrypoint: PurePosixPath
resources: dict[str, HandlerInfo]
title: str | None
url: str | None
viewpoints: dict[str, str]