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.

Concepts used

  • load_model is the main function for loading the model. In the example, the parameter paths is used to specify the path to the SysML v2 file. This parameter accepts a list of paths. The list may also hold (url, source) tuples to load SysML v2 or KerML text from memory, the language following the extension of url.

  • .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 behavior 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 documentation 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

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.
    #
    # Raises if Syside reports errors, or with this flag warnings too.
    # Syside may also report informational messages, but not for this
    # example.
    model = syside.load_model(paths=[MODEL_FILE_PATH], 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 as extract_docs.zip.