Extract Documentation

This simple Python script uses SysIDE to extract information from all the doc elements present in the model and print it out in the console.

The example covers unordered iteration over elements of specific type.

Note

Before running this example, make sure you have activated the SysIDE license by running syside-license check according to the instructions in the License Activation section.

Concepts Used

  • syside.load_model is the main function for loading the model. In the example, the parameter paths is used to specify the path to the SysMLv2 file. This parameter accepts a list of paths. load_model also accepts parameters sysml_source and kerml_source that can be used to load SysMLv2 and KerML files from memory, respectively.

  • nodes method on model enables iterating over the elements of the given type. By default, it returns only the instances that match the type exactly. The behaviour can be changed to include subtypes by setting the parameter include_subtypes to True.

  • name on element enables accessing the name of SysML element.

  • body on element enables accessing the annotation text for the comment.

Interactive version

Save the example model below to your computer and run python3 -m syside interactive path/to/downloaded/example_model.sysml with the SysIDE venv activated. This drops you into an interactive Python shell that starts with a banner:

Welcome to isyside!

This is an interactive Python shell with the loaded model accessible as `model`.
Builtin modules:        syside
Convenience variables:  model, diagnostics

>>>

From here, you can access the model described in example_model.sysml as model. For example

model.nodes(syside.Documentation)

gives an iterator over all documentation elements in the model. We can use this to create a list of all documentation elements

>>> doc_elements = list(model.nodes(syside.Documentation))
>>>

These elements might have names of their own

>>> doc_elements[2].name
'Document1'
>>>

or may be anonymous

>>> doc_elements[1].name
>>>

and will typically have a body

>>> doc_elements[0].body
'This is documentation of the owning\npackage.'
>>> doc_elements[1].body
'This is documentation of Automobile alias.'
>>> doc_elements[2].body
'This is documentation of Automobile.'
>>>

The text in the body concerns the element that _owns_ the documentation element. This _owning_ element can be accessed through owner

>>> doc_elements[2].owner.name
'Automobile'
>>>

If a fully qualified name is needed, use qualified_name:

>>> qn = doc_elements[2].owner.qualified_name
>>> qn
syside.core.QualifiedName(['Documentation Example', 'Automobile'])
>>> str(qn)
"'Documentation Example'::Automobile"
>>>

Example Model

package 'Documentation Example' {
  doc
  /*
   * This is documentation of the owning
   * package.
   */

  part def Automobile {
    doc Document1
    /*
     * This is documentation of Automobile.
     */
  }

  alias Car for Automobile {
    doc
    /*
     * This is documentation of Automobile alias.
     */
  }
  alias Torque for ISQ::TorqueValue;
}

Example Script

import pathlib
import syside
import syside.helpers

EXAMPLE_DIR = pathlib.Path(__file__).parent
MODEL_FILE_PATH = EXAMPLE_DIR / "example_model.sysml"


def main() -> None:
    # Load the model. Model can also be loaded by giving its path as a string
    # like syside.load_model("example_model.sysml")
    # However, we recommend using this approach to ensure that the model is
    # found even when the script is run from a different directory.
    (model, diagnostics) = syside.load_model(paths=[MODEL_FILE_PATH])

    # Only errors cause an exception. SysIDE may also report warnings and
    # informational messages, but not for this example.
    assert not diagnostics.contains_errors(warnings_as_errors=True)

    for element in model.nodes(syside.Documentation):
        assert (
            element.owner is not None
            and element.owner.qualified_name is not None
        ), (
            "In this example, all documentation elements are owned by elements \
        with names."
        )

        # Obtain qualified name
        about = str(element.owner.qualified_name)

        # Print out to the output
        if element.name:
            print(
                f"There is a documentation element called {element.name}, "
                f"which is about {about}, and it says: {element.body}"
            )
        else:
            print(
                f"There is an unnamed documentation element about {about}, "
                f"and it says: {element.body}"
            )


if __name__ == "__main__":
    main()

Output

There is an unnamed documentation element about 'Documentation Example', and it says: This is documentation of the owning
package.
There is an unnamed documentation element about 'Documentation Example'::Car, and it says: This is documentation of Automobile alias.
There is a documentation element called Document1, which is about 'Documentation Example'::Automobile, and it says: This is documentation of Automobile.

Download

Download this example here.