Skip to content

Commit

Permalink
docs: Improve docs (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
ewuerger authored Sep 23, 2024
1 parent 9c1c406 commit ba8a5b1
Show file tree
Hide file tree
Showing 31 changed files with 500 additions and 189 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ repos:
additional_dependencies:
- bidict
- cairosvg
- capellambse==0.5.69
- capellambse==0.6.6
- click
- jinja2
- polarion-rest-api-client==1.1.2
- polarion-rest-api-client==1.1.3
- pydantic
- types-requests
- types-PyYAML
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@
![image](https://github.com/DSD-DBS/capella-polarion/actions/workflows/lint.yml/badge.svg)
![image](https://github.com/DSD-DBS/capella-polarion/actions/workflows/docs.yml/badge.svg)

Synchronise Capella models with Polarion projects
Synchronise Capella models with Polarion projects.

![image](c2p-uc1.gif)

Use cases covered:

- *Make Capella Objects and attributes of interest available in a Polarion* project so that a Project User could referense those objects and attributes in LiveDocs and WorkItems such as requirements, to ensure consistency across the Project. Model has full authority over the work items that represent model elements. A change to a model element will result in a change to the corresponding WorkItem in Polarion.

- *Create and maintain LiveDocs* based on a Capella model and a set of templates so that the Project Users could do less paperwork. A change to the model or template shall result in a change to a LiveDoc or related WorkItems. All changes to generated LiveDocs made in Polarion will be over-written by Capella2Polarion as it has "Full Authority" over those documents.

- *Create and co-maintain LiveDocs* where model would have authority over some sections and people over other sections (mixed-authority) - this would enable Project User to create requirements or other objects in the context of model-derived structure or elements.

# Documentation

Expand Down
Binary file added c2p-uc1.GIF
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions c2p-uc1.GIF.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Copyright DB InfraGO AG and contributors
SPDX-License-Identifier: Apache-2.0
10 changes: 5 additions & 5 deletions capella2polarion/converters/converter_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from collections import abc as cabc

import yaml
from capellambse.model import common, diagram
from capellambse import model as m
from capellambse_context_diagrams import filters as context_filters

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -370,11 +370,11 @@ def _filter_context_diagram_config(
def _filter_links(
c_type: str, links: list[LinkConfig], is_global: bool = False
) -> list[LinkConfig]:
c_class: type[common.ModelObject | diagram.Diagram]
c_class: type[m.ModelObject]
if c_type == "diagram":
c_class = diagram.Diagram
c_class = m.Diagram
else:
if not (c_classes := common.find_wrapper(c_type)):
if not (c_classes := m.find_wrapper(c_type)):
logger.error("Did not find any matching Wrapper for %r", c_type)
return links
c_class = c_classes[0]
Expand All @@ -385,7 +385,7 @@ def _filter_links(
is_diagram_elements = capella_attr == DIAGRAM_ELEMENTS_SERIALIZER
if (
capella_attr == DESCRIPTION_REFERENCE_SERIALIZER
or (is_diagram_elements and c_class == diagram.Diagram)
or (is_diagram_elements and c_class == m.Diagram)
or hasattr(c_class, capella_attr)
):
available_links.append(link)
Expand Down
4 changes: 2 additions & 2 deletions capella2polarion/converters/data_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import dataclasses

from capellambse.model import common, diagram
from capellambse import model as m

from capella2polarion import data_models as dm
from capella2polarion.converters import converter_config
Expand All @@ -17,7 +17,7 @@ class ConverterData:

layer: str
type_config: converter_config.CapellaTypeConfig
capella_element: diagram.Diagram | common.GenericElement
capella_element: m.ModelElement | m.Diagram
work_item: dm.CapellaWorkItem | None = None
description_references: list[str] = dataclasses.field(default_factory=list)
errors: set[str] = dataclasses.field(default_factory=set)
Expand Down
24 changes: 10 additions & 14 deletions capella2polarion/converters/element_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
import markupsafe
import polarion_rest_api_client as polarion_api
from capellambse import helpers as chelpers
from capellambse.model import common
from capellambse.model import diagram as diag
from capellambse import model as m
from lxml import etree

from capella2polarion import data_models
Expand Down Expand Up @@ -156,7 +155,7 @@ def _add_attachment(

def _draw_diagram_svg(
self,
diagram: capellambse.model.diagram.AbstractDiagram,
diagram: m.AbstractDiagram,
file_name: str,
title: str,
max_width: int,
Expand Down Expand Up @@ -225,7 +224,7 @@ def __make_href_filter(self, obj: object) -> str | None:
def __insert_diagram(
self,
work_item: data_models.CapellaWorkItem,
diagram: capellambse.model.diagram.AbstractDiagram,
diagram: m.AbstractDiagram,
file_name: str,
render_params: dict[str, t.Any] | None = None,
max_width: int = 800,
Expand Down Expand Up @@ -262,7 +261,7 @@ def __insert_diagram(
def _draw_additional_attributes_diagram(
self,
work_item: data_models.CapellaWorkItem,
diagram: capellambse.model.diagram.AbstractDiagram,
diagram: m.AbstractDiagram,
attribute: str,
title: str,
render_params: dict[str, t.Any] | None = None,
Expand All @@ -284,7 +283,7 @@ def _draw_additional_attributes_diagram(
}

def _sanitize_linked_text(
self, obj: common.GenericElement | diag.Diagram
self, obj: m.ModelElement | m.Diagram
) -> tuple[
list[str], markupsafe.Markup, list[polarion_api.WorkItemAttachment]
]:
Expand All @@ -301,9 +300,7 @@ def _sanitize_linked_text(
return self._sanitize_text(obj, linked_text)

def _sanitize_text(
self,
obj: common.GenericElement | diag.Diagram,
text: markupsafe.Markup | str,
self, obj: m.ModelElement | m.Diagram, text: markupsafe.Markup | str
) -> tuple[
list[str], markupsafe.Markup, list[polarion_api.WorkItemAttachment]
]:
Expand Down Expand Up @@ -393,8 +390,7 @@ def _replace_markup(
return match.group(default_group)

def _get_requirement_types_text(
self,
obj: common.GenericElement | diag.Diagram,
self, obj: m.ModelElement | m.Diagram
) -> dict[str, dict[str, str]]:
type_texts = collections.defaultdict(list)
for req in getattr(obj, "requirements", []):
Expand Down Expand Up @@ -455,7 +451,7 @@ def _diagram(
"""Serialize a diagram for Polarion."""
diagram = converter_data.capella_element
assert converter_data.work_item is not None
assert isinstance(diagram, diag.Diagram)
assert isinstance(diagram, m.Diagram)
work_item_id = converter_data.work_item.id

diagram_html, attachment = self._draw_diagram_svg(
Expand Down Expand Up @@ -483,9 +479,9 @@ def _include_pre_and_post_condition(
obj = converter_data.capella_element
assert hasattr(obj, "precondition"), "Missing PreCondition Attribute"
assert hasattr(obj, "postcondition"), "Missing PostCondition Attribute"
assert not isinstance(obj, diag.Diagram)
assert not isinstance(obj, m.Diagram)

def get_condition(cap: common.GenericElement, name: str) -> str:
def get_condition(cap: m.ModelElement, name: str) -> str:
if not (condition := getattr(cap, name)):
return ""
_, value, _ = self._sanitize_linked_text(condition)
Expand Down
28 changes: 13 additions & 15 deletions capella2polarion/converters/link_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

import capellambse
import polarion_rest_api_client as polarion_api
from capellambse.model import common
from capellambse.model import diagram as diag
from capellambse import model as m

from capella2polarion import data_models
from capella2polarion.connectors import polarion_repo
Expand All @@ -25,7 +24,7 @@

TYPE_RESOLVERS = {"Part": lambda obj: obj.type.uuid}
_Serializer: t.TypeAlias = cabc.Callable[
[diag.Diagram | common.GenericElement, str, str, dict[str, t.Any]],
[m.ModelElement | m.Diagram, str, str, dict[str, t.Any]],
list[polarion_api.WorkItemLink],
]

Expand Down Expand Up @@ -73,10 +72,10 @@ def create_links_for_work_item(
else:
refs = _resolve_attribute(obj, link_config.capella_attr)
new: cabc.Iterable[str]
if isinstance(refs, common.ElementList):
if isinstance(refs, m.ElementList):
new = refs.by_uuid # type: ignore[assignment]
elif refs is None:
logger.info(
logger.info( # type: ignore[unreachable]
'For model element %r attribute "%s" is not set',
obj._short_repr_(),
link_config.capella_attr,
Expand Down Expand Up @@ -140,7 +139,7 @@ def _get_work_item_ids(

def _handle_description_reference_links(
self,
obj: common.GenericElement | diag.Diagram,
obj: m.ModelElement | m.Diagram,
work_item_id: str,
role_id: str,
links: dict[str, polarion_api.WorkItemLink],
Expand All @@ -151,12 +150,12 @@ def _handle_description_reference_links(

def _handle_diagram_reference_links(
self,
diagram: common.GenericElement | diag.Diagram,
diagram: m.ModelElement | m.Diagram,
work_item_id: str,
role_id: str,
links: dict[str, polarion_api.WorkItemLink],
) -> list[polarion_api.WorkItemLink]:
assert isinstance(diagram, diag.Diagram)
assert isinstance(diagram, m.Diagram)
try:
refs = set(self._collect_uuids(diagram.nodes))
refs = set(self._get_work_item_ids(work_item_id, refs, role_id))
Expand All @@ -173,7 +172,7 @@ def _handle_diagram_reference_links(

def _collect_uuids(
self,
nodes: cabc.Iterable[common.GenericElement],
nodes: cabc.Iterable[m.ModelElement],
) -> cabc.Iterator[str]:
type_resolvers = TYPE_RESOLVERS
for node in nodes:
Expand Down Expand Up @@ -288,9 +287,8 @@ def _create_link_fields(
obj._short_repr_(),
)

uuids: cabc.Iterable[str]
if isinstance(attr, common.ElementList):
uuids = attr.by_uuid # type: ignore[assignment]
if isinstance(attr, m.ElementList):
uuids: list[str] = list(attr.by_uuid)
else:
assert hasattr(attr, "uuid")
uuids = [attr.uuid]
Expand Down Expand Up @@ -385,12 +383,12 @@ def _sorted_unordered_html_list(


def _resolve_attribute(
obj: common.GenericElement | diag.Diagram, attr_id: str
) -> common.ElementList[common.GenericElement] | common.GenericElement | None:
obj: m.ModelElement | m.Diagram, attr_id: str
) -> m.ElementList[m.ModelElement] | m.ModelElement:
attr_name, _, map_id = attr_id.partition(".")
objs = getattr(obj, attr_name)
if map_id and objs is not None:
if isinstance(objs, common.GenericElement):
if isinstance(objs, m.ModelElement):
return _resolve_attribute(objs, map_id)
objs = objs.map(map_id)
return objs
Expand Down
18 changes: 4 additions & 14 deletions capella2polarion/converters/polarion_html_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import pathlib
import re

import capellambse
import jinja2
import polarion_rest_api_client as polarion_api
from capellambse import helpers as chelpers
from capellambse import model as m
from lxml import html

wi_id_prefix = "polarion_wiki macro name=module-workitem;params=id="
Expand Down Expand Up @@ -93,11 +93,7 @@ def _get_jinja_env(self, template_folder: str | pathlib.Path):

def check_model_element(
self, obj: object
) -> (
capellambse.model.GenericElement
| capellambse.model.diagram.AbstractDiagram
| None
):
) -> m.ModelElement | m.AbstractDiagram | None:
"""Check if a model element was passed.
Return None if no element and raise a TypeError if a wrong typed
Expand All @@ -107,15 +103,9 @@ def check_model_element(
if jinja2.is_undefined(obj) or obj is None:
return None

if isinstance(obj, capellambse.model.ElementList):
if isinstance(obj, m.ElementList):
raise TypeError("Cannot make an href to a list of elements")
if not isinstance(
obj,
(
capellambse.model.GenericElement,
capellambse.model.diagram.AbstractDiagram,
),
):
if not isinstance(obj, (m.ModelElement, m.AbstractDiagram)):
raise TypeError(f"Expected a model object, got {obj!r}")
return obj

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/source/_static/grouped_linked_work_items.png.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse contributors
SPDX-License-Identifier: Apache-2.0
Binary file added docs/source/_static/linked_work_items.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/source/_static/linked_work_items.jpeg.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse contributors
SPDX-License-Identifier: Apache-2.0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse contributors
SPDX-License-Identifier: Apache-2.0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse contributors
SPDX-License-Identifier: Apache-2.0
10 changes: 9 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,15 @@

# -- Options for auto-doc ----------------------------------------------------
autoclass_content = "class"

autodoc_default_options = {
"members": True,
"undoc-members": True,
# "private-members": True,
# "special-members": True,
# "inherited-members": True,
# "show-inheritance": True,
"noindex": True,
}

# -- Options for napoleon ----------------------------------------------------
napoleon_google_docstring = False
Expand Down
Loading

0 comments on commit ba8a5b1

Please sign in to comment.