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 toTrue
when callingsave()
.- Return type:
None
- activate_viewpoint(name, version)¶
Activate (reference) a viewpoint in the model.
- check_duplicate_uuids()¶
- Return type:
None
- create_link(from_element, to_element, *, include_target_type=None)¶
Create a link to
to_element
fromfrom_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 whetherfrom_element
andto_element
live in the the same fragment, and whether theinclude_target_type
parameter is set.- Return type:
- property filehandler: FileHandler¶
The file handler containing the original model.
This is a shorthand for
self.resources["\0"]
.
- find_by_xsi_type(*xsi_types, roots=None)¶
Find all elements matching any of the given
xsi:type
s.
- find_fragment(element)¶
Find the name of the fragment that contains
element
.- Parameters:
element (_Element)
- Return type:
- follow_link(from_element, link)¶
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 frommain.capella
intofrag/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:
- Raises:
ValueError – If the link is malformed
FileNotFoundError – If the target fragment is not loaded (only applicable if
from_element
is not None andfragment
is part of the link)RuntimeError – If the expected
xsi:type
does not match the actualxsi:type
of the found targetKeyError – If the target cannot be found
- Return type:
- follow_links(from_element, links, *, ignore_broken=False)¶
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 actualxsi:type
of the found target.
- Return type:
- 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:
- Returns:
The new UUID.
- Return type:
- 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_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.
- iterall_xt(*xtypes, trees=None)¶
Iterate over all elements in all trees by
xsi:type
s.- Parameters:
xtypes (str) – Optionally restrict the iterator to these
xsi:type
strees (Container[PurePosixPath] | None) – Optionally restrict the iterator to elements that reside in any of the named trees.
- Return type:
- iterancestors(element, *tags)¶
Iterate over the ancestors of
element
.This method will follow fragment links back to the origin point.
- 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.
- 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.
- iterdescendants_xt(element, *xtypes)¶
Iterate over all descendants of
element
byxsi:type
.This method will follow links into different fragment files and yield those elements as if they were part of the origin subtree.
- 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 thewith
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.
- 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 directoriescapellambse.filehandler.git.GitFileHandler.write_transaction
Accepted
**kw
when usinggit://
and similar URLs
Notes
With a
filehandler
that contacts a remote location (such as thecapellambse.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 theupdate_cache
parameter at its default value ofTrue
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.
- 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:
- Returns:
A list of all matching elements.
- Return type:
- 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:
- Returns:
A list of 2-tuples, containing:
The fragment name where the match was found.
The matching element.
- Return type:
- 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:
filename (PurePosixPath)
handler (FileHandler)
ignore_uuid_dups (bool)
- Return type:
None
- property fragment_type: FragmentType¶
- 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.
- idcache_reserve(new_id)¶
Reserve the given ID for an element to be inserted later.
- Parameters:
new_id (str)
- Return type:
None
- iterall_xt(xtypes)¶
Iterate over all elements in this tree by
xsi:type
.
- property tree: _ElementTree¶
- 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.
- update_namespaces(viewpoints)¶
Update the current namespace map.
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.
- 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:
- Returns:
The serialized XML, encoded using
encoding
.- Return type:
- 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.
- 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.filehandler module¶
- class capellambse.loader.filehandler.FileHandler¶
Bases:
object
Abstract super class for file handler implementations.
- Parameters:
path (str | os.PathLike) – The location of the remote. The exact accepted forms are determined by the specific file handler implementation, for example the
LocalFileHandler
accepts only local paths, and theGitFileHandler
accepts everything that Git accepts.subdir – Consider all paths relative to this subdirectory, instead of the root of the file handler’s hierarchy.
- __init__(path, *, subdir='/', **kw)¶
- Parameters:
subdir (str | PurePosixPath)
kw (Any)
- Return type:
None
- abstract get_model_info()¶
- Return type:
- is_dir(path, /)¶
- Parameters:
path (str | PurePosixPath)
- is_file(path, /)¶
- Parameters:
path (str | PurePosixPath)
- iterdir(path='.', /)¶
Iterate over the contents of a directory.
This method is equivalent to calling
fh.rootdir.joinpath(path).iterdir()
.- Parameters:
path (str | PurePosixPath) – The directory to list. If not given, lists the contents of the root directory (i.e. the one specified by
path
andsubdir
).- Return type:
- abstract open(filename, mode='rb')¶
Open the model file for reading or writing.
A “file” in this context does not necessarily refer to a physical file on disk; it may just as well be streamed in via network or other means. Due to this, the file-like returned by this method is not required to support random access.
- Parameters:
filename (str | PurePosixPath) – The name of the file, relative to the
path
that was given to the constructor.mode (Literal['r', 'rb', 'w', 'wb']) – The mode to open the file in. Either
"r"
or"rb"
for reading, or"w"
or"wb"
for writing a new file. Be aware that this method may refuse to open a file for writing unless a transaction was started withwrite_transaction()
first.
- Return type:
- read_file(path, /)¶
Read a file.
This method is a convenience wrapper around
open()
.- Parameters:
path (str | PurePosixPath)
- Return type:
- write_file(path, content, /)¶
Write a file.
This method is a convenience wrapper around
open()
.- Parameters:
path (str | PurePosixPath)
content (bytes)
- Return type:
None
- write_transaction(**kw)¶
Start a transaction for writing new model files.
During a transaction, writable objects returned by
open()
buffer their contents in a temporary location, and once the transaction ends, all updated files are committed to their destinations at once. If the transaction is aborted, for example because an exception was raised, then all changes must be rolled back to the state immediately before the transaction. If, during a transaction, any relevant file is touched without the file handler knowing about it, the behavior is undefined.Note that
open()
may refuse to open a file as writable if no transaction is currently open. This depends on the needs of the underlying abstract file system.Transaction arguments
A concrete file handler implementation may accept arbitrary additional arguments to this method. The implementation should however always support the case of no arguments given, in which case it should start a transaction with sensible defaults, and it should also accept and ignore any arguments it does not understand. All additional arguments must be passed in via keywords. Positional arguments are not supported.
The return value of the context manager’s
__enter__()
method is expected to be a mapping of all the keyword arguments that were not understood. Client code may use this to react properly (e.g. by aborting the transaction early) if a required keyword argument is found to be not supported by the underlying file handler. If a subclass wishes to call its super class’write_transaction()
method, it should remove all the keyword arguments that it handles itself and pass on the others unchanged.Well-known arguments
The following arguments are considered well-known, and their meaning is expected to be the same for all file handlers that support them.
dry_run
(bool
): If set toTrue
, changes made during the transaction should be rolled back instead of being committed, just as if an exception had been raised.author_name
(str
): The name of the author of the changes.author_email
(str
): The e-mail address to record alongside theauthor_name
.commit_msg
(str
): A message describing the changes, which will be recorded in the version control system.remote_branch
(str
): If the model came from a remote version control system, changes are normally pushed back to the same branch on that remote. This argument specifies an alternative branch name to push to (which may not yet exist on the remote).
- Parameters:
kw (Any)
- Return type:
- exception capellambse.loader.filehandler.TransactionClosedError¶
Bases:
RuntimeError
Raised when a transaction must be opened first to write files.
- capellambse.loader.filehandler.get_filehandler(path, **kwargs)¶
- Parameters:
- Return type:
capellambse.loader.modelinfo module¶
- class capellambse.loader.modelinfo.ModelInfo¶
Bases:
object
ModelInfo(branch: ‘str | None’ = None, title: ‘str | None’ = None, url: ‘str | None’ = None, revision: ‘str | None’ = None, rev_hash: ‘str | None’ = None, capella_version: ‘str | None’ = None, viewpoints: ‘dict[str, str]’ = <factory>)
- __init__(branch=None, title=None, url=None, revision=None, rev_hash=None, capella_version=None, viewpoints=<factory>)¶
capellambse.loader.xmltools module¶
Useful helpers for making object-oriented XML proxy classes.
- class capellambse.loader.xmltools.AttributeProperty¶
Bases:
object
A property that forwards access to the underlying XML element.
- NOT_OPTIONAL = <object object>¶
- __init__(xmlattr, attribute, *, returntype=<class 'str'>, optional=False, default=None, writable=True, __doc__=None)¶
Create an AttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
returntype (Callable[[str], Any]) – The type to return the result as. Must accept a single
str
as argument.optional (bool) – If False (default) and the XML attribute does not exist, an AttributeError is raised. Otherwise a default value is returned.
default (Any) – A new-style format string to use as fallback value. You can access the object instance as
self
and the XML element asxml
.writable (bool) – Whether to allow modifying the XML attribute.
__doc__ (str | None)
- Return type:
None
- attribute¶
- default¶
- returntype¶
- writable¶
- xmlattr¶
- class capellambse.loader.xmltools.BooleanAttributeProperty¶
Bases:
AttributeProperty
An AttributeProperty that works with booleans.
- __init__(xmlattr, attribute, *, writable=True, __doc__=None)¶
Create an AttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
returntype – The type to return the result as. Must accept a single
str
as argument.optional – If False (default) and the XML attribute does not exist, an AttributeError is raised. Otherwise a default value is returned.
default – A new-style format string to use as fallback value. You can access the object instance as
self
and the XML element asxml
.writable (bool) – Whether to allow modifying the XML attribute.
__doc__ (str | None)
- Return type:
None
- attribute¶
- default¶
- returntype¶
- writable¶
- xmlattr¶
- class capellambse.loader.xmltools.DatetimeAttributeProperty¶
Bases:
AttributeProperty
An AttributeProperty that stores a datetime.
The value stored in the XML will be formatted as required by Capella. This format is the ISO8601 format with millisecond precision, but no
:
in the time zone specification.- __init__(xmlattr, attribute, *, optional=True, writable=True, __doc__=None)¶
Create an AttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
returntype – The type to return the result as. Must accept a single
str
as argument.optional (bool) – If False (default) and the XML attribute does not exist, an AttributeError is raised. Otherwise a default value is returned.
default – A new-style format string to use as fallback value. You can access the object instance as
self
and the XML element asxml
.writable (bool) – Whether to allow modifying the XML attribute.
__doc__ (str | None)
- Return type:
None
- format¶
- re_get = re.compile('(?<=[+-]\\d\\d)(?=\\d\\d$)')¶
- re_set = re.compile('(?<=[+-]\\d\\d):(?=\\d\\d$)')¶
- class capellambse.loader.xmltools.EnumAttributeProperty¶
Bases:
AttributeProperty
An AttributeProperty whose values are determined by an Enum.
This works in much the same way as the standard AttributeProperty, except that the returned and consumed values are not simple strings, but members of the Enum that was passed into the constructor.
Usually it is expected that the enum members will be directly assigned to this property. However it is also possible to assign a
str
instead. In this case, the string will be taken to be an enum member’s name. In both cases, the enum member’s value will be placed in the underlying XML attribute.If the XML attribute contains a value that does not correspond to any of the Enum’s members, a KeyError will be raised. If the attribute is completely missing from the XML and there was no
default=
value set during construction, this property will returnNone
.- __init__(xmlattr, attribute, enumcls, *args, default=None, **kw)¶
Create an EnumAttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
enumcls (type[Enum]) – The
enum.Enum
subclass to use. The class’ members’ values are used as the possible values for the XML attribute.default (str | Enum | None) – The default value to return if the attribute is not present in the XML. If None, an AttributeError will be raised instead.
args (Any)
kw (Any)
- Return type:
None
- enumcls¶
- class capellambse.loader.xmltools.HTMLAttributeProperty¶
Bases:
AttributeProperty
An AttributeProperty that gracefully handles HTML-in-XML.
- __init__(xmlattr, attribute, *, optional=False, writable=True, __doc__=None)¶
Create an AttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
returntype – The type to return the result as. Must accept a single
str
as argument.optional (bool) – If False (default) and the XML attribute does not exist, an AttributeError is raised. Otherwise a default value is returned.
default – A new-style format string to use as fallback value. You can access the object instance as
self
and the XML element asxml
.writable (bool) – Whether to allow modifying the XML attribute.
__doc__ (str | None)
- Return type:
None
- attribute¶
- default¶
- returntype¶
- writable¶
- xmlattr¶
- class capellambse.loader.xmltools.NumericAttributeProperty¶
Bases:
AttributeProperty
Attribute property that handles (possibly infinite) numeric values.
Positive infinity is stored in Capella XML as *. This class takes care of converting to and from that value when setting or retrieving the value.
Note that there is currently no representation of negative infinity, which is why
-inf
is rejected with aValueError
.NaN
values are rejected with a ValueError as well.- __init__(xmlattr, attribute, *, optional=False, default=None, allow_float=True, writable=True, __doc__=None)¶
Create an AttributeProperty.
- Parameters:
xmlattr (str) – The owning type’s instance attribute pointing to the XML element.
attribute (str) – The attribute on the XML element to handle.
returntype – The type to return the result as. Must accept a single
str
as argument.optional (bool) – If False (default) and the XML attribute does not exist, an AttributeError is raised. Otherwise a default value is returned.
default (int | float | None) – A new-style format string to use as fallback value. You can access the object instance as
self
and the XML element asxml
.writable (bool) – Whether to allow modifying the XML attribute.
allow_float (bool)
__doc__ (str | None)
- Return type:
None
- attribute¶
- default¶
- returntype¶
- writable¶
- xmlattr¶
- class capellambse.loader.xmltools.XMLDictProxy¶
Bases:
MutableMapping
Provides dict-like access to underlying XML structures.
Subclasses of this class behave like regular Python dictionary, except that all key/value accesses are transparently forwarded to the underlying XML.
- __init__(xml_element, *args, childtag, keyattr, model=None, **kwargs)¶
Initialize the XMLDictProxy.
- Parameters:
xml_element (_Element) – The underlying XML element.
childtag (str) – The XML tag of handled child elements.
keyattr (str) – The element attribute to use as dictionary key.
model (MelodyLoader | None) – Reference to the original MelodyLoader. If not None, the loader will be informed about element creation and deletion.
args (Any)
kwargs (Any)
- Return type:
None