diff --git a/capella2polarion/connectors/polarion_repo.py b/capella2polarion/connectors/polarion_repo.py index 09a3cf65..f0eb176a 100644 --- a/capella2polarion/connectors/polarion_repo.py +++ b/capella2polarion/connectors/polarion_repo.py @@ -8,7 +8,7 @@ import bidict import polarion_rest_api_client as polarion_api -from capella2polarion import data_models +from capella2polarion import data_model class PolarionDataRepository: @@ -20,11 +20,11 @@ class PolarionDataRepository: """ _id_mapping: bidict.bidict[str, str] - _work_items: dict[str, data_models.CapellaWorkItem] + _work_items: dict[str, data_model.CapellaWorkItem] def __init__( self, - polarion_work_items: list[data_models.CapellaWorkItem] | None = None, + polarion_work_items: list[data_model.CapellaWorkItem] | None = None, ): if polarion_work_items is None: polarion_work_items = [] @@ -58,7 +58,7 @@ def __iter__(self) -> cabc.Iterator[str]: def items( self, - ) -> cabc.Iterator[tuple[str, str, data_models.CapellaWorkItem]]: + ) -> cabc.Iterator[tuple[str, str, data_model.CapellaWorkItem]]: """Yield all Capella UUIDs, Work Item IDs and Work Items.""" for uuid, polarion_id in self._id_mapping.items(): yield uuid, polarion_id, self._work_items[uuid] @@ -73,19 +73,19 @@ def get_capella_uuid(self, work_item_id: str) -> str | None: def get_work_item_by_capella_uuid( self, capella_uuid: str - ) -> data_models.CapellaWorkItem | None: + ) -> data_model.CapellaWorkItem | None: """Return a Work Item for a provided Capella UUID.""" return self._work_items.get(capella_uuid) def get_work_item_by_polarion_id( self, work_item_id: str - ) -> data_models.CapellaWorkItem | None: + ) -> data_model.CapellaWorkItem | None: """Return a Work Item for a provided Work Item ID.""" return self.get_work_item_by_capella_uuid( self.get_capella_uuid(work_item_id) # type: ignore ) - def update_work_items(self, work_items: list[data_models.CapellaWorkItem]): + def update_work_items(self, work_items: list[data_model.CapellaWorkItem]): """Update all mappings for the given Work Items.""" for work_item in work_items: assert work_item.id is not None @@ -123,7 +123,7 @@ def remove_work_items_by_capella_uuid(self, uuids: cabc.Iterable[str]): """ -def check_work_items(work_items: cabc.Iterable[data_models.CapellaWorkItem]): +def check_work_items(work_items: cabc.Iterable[data_model.CapellaWorkItem]): """Raise a ``ValueError`` if any work item has no ID.""" if work_item_without_id := next( (wi for wi in work_items if wi.id is None), None diff --git a/capella2polarion/connectors/polarion_worker.py b/capella2polarion/connectors/polarion_worker.py index 8aa0150f..1183b06c 100644 --- a/capella2polarion/connectors/polarion_worker.py +++ b/capella2polarion/connectors/polarion_worker.py @@ -4,7 +4,6 @@ from __future__ import annotations import collections.abc as cabc -import json import logging import typing as t from urllib import parse @@ -13,7 +12,7 @@ from capellambse import helpers as chelpers from lxml import etree -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo from capella2polarion.converters import data_session @@ -122,7 +121,7 @@ def load_polarion_work_item_map(self): work_items = self.project_client.work_items.get_all( "HAS_VALUE:uuid_capella", fields={"workitems": "id,uuid_capella,checksum,status,type"}, - work_item_cls=data_models.CapellaWorkItem, + work_item_cls=data_model.CapellaWorkItem, ) self.polarion_data_repo.update_work_items(work_items) @@ -140,7 +139,7 @@ def delete_orphaned_work_items( if work_item.status != "deleted" } uuids: set[str] = existing_work_items - set(converter_session) - work_items: list[data_models.CapellaWorkItem] = [] + work_items: list[data_model.CapellaWorkItem] = [] for uuid in uuids: if wi := self.polarion_data_repo.get_work_item_by_capella_uuid( uuid @@ -159,7 +158,7 @@ def create_missing_work_items( self, converter_session: data_session.ConverterSession ) -> None: """Post work items in a Polarion project.""" - missing_work_items: list[data_models.CapellaWorkItem] = [] + missing_work_items: list[data_model.CapellaWorkItem] = [] for uuid, converter_data in converter_session.items(): if not (work_item := converter_data.work_item): logger.warning( @@ -207,7 +206,7 @@ def compare_and_update_work_item( try: if work_item_changed or self.force_update: old = self.project_client.work_items.get( - old.id, work_item_cls=data_models.CapellaWorkItem + old.id, work_item_cls=data_model.CapellaWorkItem ) assert old is not None assert old.id is not None @@ -319,7 +318,7 @@ def compare_and_update_work_item( ) raise error - def _refactor_attached_images(self, new: data_models.CapellaWorkItem): + def _refactor_attached_images(self, new: data_model.CapellaWorkItem): def set_attachment_id(node: etree._Element) -> None: if node.tag != "img": return @@ -352,7 +351,7 @@ def set_attachment_id(node: etree._Element) -> None: def update_attachments( self, - new: data_models.CapellaWorkItem, + new: data_model.CapellaWorkItem, old_checksums: dict[str, str], new_checksums: dict[str, str], old_attachments: list[polarion_api.WorkItemAttachment], @@ -468,7 +467,7 @@ def compare_and_update_work_items( def create_documents( self, - document_datas: list[data_models.DocumentData], + document_datas: list[data_model.DocumentData], document_project: str | None = None, ): """Create new documents. @@ -485,7 +484,7 @@ def create_documents( def update_documents( self, - document_datas: list[data_models.DocumentData], + document_datas: list[data_model.DocumentData], document_project: str | None = None, ): """Update existing documents. @@ -506,7 +505,7 @@ def update_documents( def _process_document_datas( self, client: polarion_api.ProjectClient, - document_datas: list[data_models.DocumentData], + document_datas: list[data_model.DocumentData], ): documents: list[polarion_api.Document] = [] headings: list[polarion_api.WorkItem] = [] @@ -545,7 +544,7 @@ def get_document( def load_polarion_documents( self, - document_infos: t.Iterable[data_models.DocumentInfo], + document_infos: t.Iterable[data_model.DocumentInfo], ) -> polarion_repo.DocumentRepository: """Load the documents referenced and text work items from Polarion.""" return { diff --git a/capella2polarion/converters/data_session.py b/capella2polarion/converters/data_session.py index ef903bda..012eb936 100644 --- a/capella2polarion/converters/data_session.py +++ b/capella2polarion/converters/data_session.py @@ -7,7 +7,7 @@ from capellambse import model as m -from capella2polarion import data_models as dm +from capella2polarion import data_model as dm from capella2polarion.converters import converter_config diff --git a/capella2polarion/converters/document_config.py b/capella2polarion/converters/document_config.py index 39909e4c..7010579e 100644 --- a/capella2polarion/converters/document_config.py +++ b/capella2polarion/converters/document_config.py @@ -12,7 +12,7 @@ import pydantic import yaml -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.converters import polarion_html_helper logger = logging.getLogger(__name__) @@ -83,11 +83,11 @@ class DocumentConfigs(pydantic.BaseModel): pydantic.Field(default_factory=list) ) - def iterate_documents(self) -> t.Iterator[data_models.DocumentInfo]: + def iterate_documents(self) -> t.Iterator[data_model.DocumentInfo]: """Yield all document paths of the config as tuples.""" for conf in self.full_authority + self.mixed_authority: for inst in conf.instances: - yield data_models.DocumentInfo( + yield data_model.DocumentInfo( project_id=conf.project_id, module_folder=inst.polarion_space, module_name=inst.polarion_name, diff --git a/capella2polarion/converters/document_renderer.py b/capella2polarion/converters/document_renderer.py index 24390eae..e4620631 100644 --- a/capella2polarion/converters/document_renderer.py +++ b/capella2polarion/converters/document_renderer.py @@ -16,7 +16,7 @@ from capella2polarion.connectors import polarion_repo -from .. import data_models +from .. import data_model from . import document_config, polarion_html_helper from . import text_work_item_provider as twi @@ -54,10 +54,10 @@ class RenderingSession: class ProjectData: """A class holding data of a project which documents are rendered for.""" - new_docs: list[data_models.DocumentData] = dataclasses.field( + new_docs: list[data_model.DocumentData] = dataclasses.field( default_factory=list ) - updated_docs: list[data_models.DocumentData] = dataclasses.field( + updated_docs: list[data_model.DocumentData] = dataclasses.field( default_factory=list ) @@ -203,7 +203,7 @@ def render_document( text_work_item_provider: twi.TextWorkItemProvider | None = None, document_project_id: str | None = None, **kwargs: t.Any, - ) -> data_models.DocumentData: + ) -> data_model.DocumentData: """Render a new Polarion document.""" @t.overload @@ -216,7 +216,7 @@ def render_document( text_work_item_provider: twi.TextWorkItemProvider | None = None, document_project_id: str | None = None, **kwargs: t.Any, - ) -> data_models.DocumentData: + ) -> data_model.DocumentData: """Update an existing Polarion document.""" def render_document( @@ -232,7 +232,7 @@ def render_document( text_work_item_provider: twi.TextWorkItemProvider | None = None, document_project_id: str | None = None, **kwargs: t.Any, - ) -> data_models.DocumentData: + ) -> data_model.DocumentData: """Render a Polarion document.""" text_work_item_provider = ( text_work_item_provider or twi.TextWorkItemProvider() @@ -279,7 +279,7 @@ def render_document( ) document.rendering_layouts = session.rendering_layouts - return data_models.DocumentData( + return data_model.DocumentData( document, session.headings, text_work_item_provider ) @@ -292,7 +292,7 @@ def update_mixed_authority_document( section_parameters: dict[str, dict[str, t.Any]], text_work_item_provider: twi.TextWorkItemProvider | None = None, document_project_id: str | None = None, - ) -> data_models.DocumentData: + ) -> data_model.DocumentData: """Update a mixed authority document.""" text_work_item_provider = ( text_work_item_provider or twi.TextWorkItemProvider() @@ -360,7 +360,7 @@ def update_mixed_authority_document( ) document.rendering_layouts = session.rendering_layouts - return data_models.DocumentData( + return data_model.DocumentData( document, session.headings, text_work_item_provider ) diff --git a/capella2polarion/converters/element_converter.py b/capella2polarion/converters/element_converter.py index bc0dd680..35471981 100644 --- a/capella2polarion/converters/element_converter.py +++ b/capella2polarion/converters/element_converter.py @@ -21,7 +21,7 @@ from capellambse_context_diagrams import context from lxml import etree -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo from capella2polarion.converters import data_session, polarion_html_helper @@ -76,12 +76,12 @@ def __init__( self.generate_attachments = generate_attachments self.jinja_envs: dict[str, jinja2.Environment] = {} - def serialize_all(self) -> list[data_models.CapellaWorkItem]: + def serialize_all(self) -> list[data_model.CapellaWorkItem]: """Serialize all items of the converter_session.""" work_items = (self.serialize(uuid) for uuid in self.converter_session) return list(filter(None, work_items)) - def serialize(self, uuid: str) -> data_models.CapellaWorkItem | None: + def serialize(self, uuid: str) -> data_model.CapellaWorkItem | None: """Return a CapellaWorkItem for the given diagram or element.""" converter_data = self.converter_session[uuid] work_item_id = None @@ -98,7 +98,7 @@ def serialize(self, uuid: str) -> data_models.CapellaWorkItem | None: try: serializer: cabc.Callable[ ..., - data_models.CapellaWorkItem, + data_model.CapellaWorkItem, ] = getattr(self, f"_{converter}") serializer(converter_data, **params) except Exception as error: @@ -125,15 +125,15 @@ def serialize(self, uuid: str) -> data_models.CapellaWorkItem | None: def _add_attachment( self, - work_item: data_models.CapellaWorkItem, - attachment: data_models.Capella2PolarionAttachment, + work_item: data_model.CapellaWorkItem, + attachment: data_model.Capella2PolarionAttachment, ): assert attachment.file_name is not None attachment.work_item_id = work_item.id or "" work_item.attachments.append(attachment) if attachment.mime_type == "image/svg+xml": work_item.attachments.append( - data_models.PngConvertedSvgAttachment(attachment) + data_model.PngConvertedSvgAttachment(attachment) ) def _draw_diagram_svg( @@ -144,16 +144,16 @@ def _draw_diagram_svg( max_width: int, cls: str, render_params: dict[str, t.Any] | None = None, - ) -> tuple[str, data_models.CapellaDiagramAttachment | None]: + ) -> tuple[str, data_model.CapellaDiagramAttachment | None]: file_name = f"{C2P_IMAGE_PREFIX}{file_name}.svg" if self.generate_attachments: if not isinstance(diagram, context.ContextDiagram): - attachment = data_models.CapellaDiagramAttachment( + attachment = data_model.CapellaDiagramAttachment( diagram, file_name, render_params, title ) else: - attachment = data_models.CapellaContextDiagramAttachment( + attachment = data_model.CapellaContextDiagramAttachment( diagram, file_name, render_params, title ) else: @@ -196,7 +196,7 @@ def __make_href_filter(self, obj: object) -> str | None: def __insert_diagram( self, - work_item: data_models.CapellaWorkItem, + work_item: data_model.CapellaWorkItem, diagram: m.AbstractDiagram, file_name: str, render_params: dict[str, t.Any] | None = None, @@ -233,7 +233,7 @@ def __insert_diagram( def _draw_additional_attributes_diagram( self, - work_item: data_models.CapellaWorkItem, + work_item: data_model.CapellaWorkItem, diagram: m.AbstractDiagram, attribute: str, title: str, @@ -258,7 +258,7 @@ def _draw_additional_attributes_diagram( def _sanitize_linked_text(self, obj: m.ModelElement | m.Diagram) -> tuple[ list[str], markupsafe.Markup, - list[data_models.Capella2PolarionAttachment], + list[data_model.Capella2PolarionAttachment], ]: linked_text = getattr( obj, "specification", {"capella:linkedText": markupsafe.Markup("")} @@ -277,7 +277,7 @@ def _sanitize_text( ) -> tuple[ list[str], markupsafe.Markup, - list[data_models.Capella2PolarionAttachment], + list[data_model.Capella2PolarionAttachment], ]: referenced_uuids: list[str] = [] replaced_markup = RE_DESCR_LINK_PATTERN.sub( @@ -287,7 +287,7 @@ def _sanitize_text( text, ) - attachments: list[data_models.Capella2PolarionAttachment] = [] + attachments: list[data_model.Capella2PolarionAttachment] = [] def repair_images(node: etree._Element) -> None: if ( @@ -312,7 +312,7 @@ def repair_images(node: etree._Element) -> None: str(file_path).encode("utf8") ).hexdigest() attachments.append( - data_models.Capella2PolarionAttachment( + data_model.Capella2PolarionAttachment( "", "", file_path.name, @@ -395,7 +395,7 @@ def __generic_work_item( self, converter_data: data_session.ConverterData, work_item_id: str | None, - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: obj = converter_data.capella_element raw_description = getattr(obj, "description", None) uuids, value, attachments = self._sanitize_text( @@ -404,7 +404,7 @@ def __generic_work_item( converter_data.description_references = uuids requirement_types = self._get_requirement_types_text(obj) - converter_data.work_item = data_models.CapellaWorkItem( + converter_data.work_item = data_model.CapellaWorkItem( id=work_item_id, type=converter_data.type_config.p_type, title=obj.name, @@ -423,7 +423,7 @@ def _diagram( self, converter_data: data_session.ConverterData, render_params: dict[str, t.Any] | None = None, - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Serialize a diagram for Polarion.""" diagram = converter_data.capella_element assert converter_data.work_item is not None @@ -434,7 +434,7 @@ def _diagram( diagram, "diagram", "Diagram", 750, "diagram", render_params ) - converter_data.work_item = data_models.CapellaWorkItem( + converter_data.work_item = data_model.CapellaWorkItem( id=work_item_id, type=converter_data.type_config.p_type, title=diagram.name, @@ -449,7 +449,7 @@ def _diagram( def _include_pre_and_post_condition( self, converter_data: data_session.ConverterData - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Return generic attributes and pre- and post-condition.""" obj = converter_data.capella_element assert hasattr(obj, "precondition"), "Missing PreCondition Attribute" @@ -476,7 +476,7 @@ def get_condition(cap: m.ModelElement, name: str) -> str: def _linked_text_as_description( self, converter_data: data_session.ConverterData - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Return attributes for a ``Constraint``.""" assert converter_data.work_item, "No work item set yet" assert ( @@ -498,7 +498,7 @@ def _add_context_diagram( converter_data: data_session.ConverterData, render_params: dict[str, t.Any] | None = None, filters: list[str] | None = None, - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Add a new custom field context diagram.""" assert converter_data.work_item, "No work item set yet" diagram = converter_data.capella_element.context_diagram @@ -520,7 +520,7 @@ def _add_tree_diagram( converter_data: data_session.ConverterData, render_params: dict[str, t.Any] | None = None, filters: list[str] | None = None, - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Add a new custom field tree diagram.""" assert converter_data.work_item, "No work item set yet" diagram = converter_data.capella_element.tree_view @@ -541,7 +541,7 @@ def _add_jinja_fields( self, converter_data: data_session.ConverterData, fields: dict[str, dict[str, str]], - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Add a new custom field and fill it with rendered jinja content.""" assert converter_data.work_item, "No work item set yet" for field, jinja_properties in fields.items(): @@ -561,7 +561,7 @@ def _jinja_as_description( converter_data: data_session.ConverterData, template_path: str, template_folder: str = "", - ) -> data_models.CapellaWorkItem: + ) -> data_model.CapellaWorkItem: """Use a Jinja template to render the description content.""" assert converter_data.work_item, "No work item set yet" assert ( diff --git a/capella2polarion/converters/link_converter.py b/capella2polarion/converters/link_converter.py index 522632b3..2ae5a618 100644 --- a/capella2polarion/converters/link_converter.py +++ b/capella2polarion/converters/link_converter.py @@ -12,7 +12,7 @@ import polarion_rest_api_client as polarion_api from capellambse import model as m -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo from capella2polarion.converters import ( converter_config, @@ -246,7 +246,7 @@ def create_grouped_link_fields( def _create_link_fields( self, - work_item: data_models.CapellaWorkItem, + work_item: data_model.CapellaWorkItem, role: str, links: list[polarion_api.WorkItemLink], reverse: bool = False, @@ -310,7 +310,7 @@ def _create_link_fields( def create_grouped_back_link_fields( self, - work_item: data_models.CapellaWorkItem, + work_item: data_model.CapellaWorkItem, links: dict[str, list[polarion_api.WorkItemLink]], ): """Create fields for the given WorkItem using a list of backlinks. diff --git a/capella2polarion/converters/model_converter.py b/capella2polarion/converters/model_converter.py index 29ce3f16..13edbf62 100644 --- a/capella2polarion/converters/model_converter.py +++ b/capella2polarion/converters/model_converter.py @@ -10,7 +10,7 @@ import capellambse import polarion_rest_api_client as polarion_api -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo from capella2polarion.converters import ( converter_config, @@ -84,7 +84,7 @@ def generate_work_items( generate_links: bool = False, generate_attachments: bool = False, generate_grouped_links_custom_fields: bool = False, - ) -> dict[str, data_models.CapellaWorkItem]: + ) -> dict[str, data_model.CapellaWorkItem]: """Return a work items mapping from model elements for Polarion. The dictionary maps Capella UUIDs to ``CapellaWorkItem`` s. In diff --git a/capella2polarion/data_model/__init__.py b/capella2polarion/data_model/__init__.py new file mode 100644 index 00000000..7f5ae191 --- /dev/null +++ b/capella2polarion/data_model/__init__.py @@ -0,0 +1,7 @@ +# Copyright DB InfraGO AG and contributors +# SPDX-License-Identifier: Apache-2.0 +"""A module for custom data models of cappela2polarion.""" + +from capella2polarion.data_model.document_data import * +from capella2polarion.data_model.work_item_attachments import * +from capella2polarion.data_model.work_items import * diff --git a/capella2polarion/data_model/document_data.py b/capella2polarion/data_model/document_data.py new file mode 100644 index 00000000..86e0191d --- /dev/null +++ b/capella2polarion/data_model/document_data.py @@ -0,0 +1,33 @@ +# Copyright DB InfraGO AG and contributors +# SPDX-License-Identifier: Apache-2.0 +"""Module providing data classes for documents.""" + +from __future__ import annotations + +import dataclasses + +import polarion_rest_api_client as polarion_api + +from capella2polarion.converters import text_work_item_provider + +__all__ = ["DocumentData", "DocumentInfo"] + + +@dataclasses.dataclass +class DocumentData: + """A class to store data related to a rendered document.""" + + document: polarion_api.Document + headings: list[polarion_api.WorkItem] + text_work_item_provider: text_work_item_provider.TextWorkItemProvider + + +@dataclasses.dataclass +class DocumentInfo: + """Class for information regarding a document which should be created.""" + + project_id: str | None + module_folder: str + module_name: str + text_work_item_type: str + text_work_item_id_field: str diff --git a/capella2polarion/data_model/work_item_attachments.py b/capella2polarion/data_model/work_item_attachments.py new file mode 100644 index 00000000..1bc2e00f --- /dev/null +++ b/capella2polarion/data_model/work_item_attachments.py @@ -0,0 +1,160 @@ +# Copyright DB InfraGO AG and contributors +# SPDX-License-Identifier: Apache-2.0 +"""Module providing the CapellaWorkItemAttachment classes.""" +from __future__ import annotations + +import base64 +import dataclasses +import hashlib +import logging +import typing as t + +import cairosvg +import polarion_rest_api_client as polarion_api +from capellambse import model +from capellambse_context_diagrams import context + +SVG_MIME_TYPE = "image/svg+xml" +PNG_MIME_TYPE = "image/png" +logger = logging.getLogger(__name__) + + +__all__ = [ + "calculate_content_checksum", + "Capella2PolarionAttachment", + "CapellaDiagramAttachment", + "CapellaContextDiagramAttachment", + "PngConvertedSvgAttachment", +] + + +def calculate_content_checksum( + attachment: polarion_api.WorkItemAttachment, +) -> str: + """Calculate content checksum for an attachment.""" + return base64.b64encode(attachment.content_bytes or b"").decode("utf8") + + +@dataclasses.dataclass +class Capella2PolarionAttachment(polarion_api.WorkItemAttachment): + """Stub Base-Class for Capella2Polarion attachments.""" + + _checksum: str | None = None + + @property + def content_checksum(self) -> str: + """Calculate the checksum for the content of the attachment.""" + if self._checksum is None: + self._checksum = calculate_content_checksum(self) + return self._checksum + + +class CapellaDiagramAttachment(Capella2PolarionAttachment): + """A class for lazy loading content_bytes for diagram attachments.""" + + def __init__( + self, + diagram: model.AbstractDiagram, + file_name: str, + render_params: dict[str, t.Any] | None, + title: str, + ): + super().__init__( + "", + "", + title, + None, + SVG_MIME_TYPE, + file_name, + ) + self.render_params = render_params or {} + self.diagram = diagram + self._content_bytes: bytes | None = None + + @property + def content_bytes(self): + """Diagrams are only rendered, if content_bytes are requested.""" + if self._content_bytes: + return self._content_bytes + try: + diagram_svg = self.diagram.render("svg", **self.render_params) + except Exception as e: + logger.error( + "Failed to render diagram %s", self.diagram.name, exc_info=e + ) + diagram_svg = self.diagram.as_svg + if isinstance(diagram_svg, str): + diagram_svg = diagram_svg.encode("utf8") + self._content_bytes = diagram_svg + return diagram_svg + + @content_bytes.setter + def content_bytes(self, value: bytes | None): + self._content_bytes = value + + +class CapellaContextDiagramAttachment(CapellaDiagramAttachment): + """A dedicated attachment type for Capella context diagrams. + + Implements a checksum property using the elk input instead of + content. This will speed up the checksum calculation a lot. + """ + + def __init__( + self, + diagram: context.ContextDiagram, + file_name: str, + render_params: dict[str, t.Any] | None, + title: str, + ): + super().__init__(diagram, file_name, render_params, title) + + @property + def content_checksum(self): + """Return checksum based on elk input for ContextDiagrams else None.""" + if self._checksum is None: + elk_input = self.diagram.elk_input_data(self.render_params) + self._checksum = hashlib.sha256( + elk_input.json().encode("utf-8") + ).hexdigest() + return self._checksum + + +class PngConvertedSvgAttachment(Capella2PolarionAttachment): + """A special attachment type for PNGs which shall be created from SVGs. + + An SVG attachment must be provided to create this attachment. The + actual conversion of SVG to PNG takes place when content bytes are + requested. For that reason creating this attachment does not trigger + diagram rendering as long as context_bytes aren't requested. + """ + + def __init__(self, attachment: polarion_api.WorkItemAttachment): + assert ( + attachment.mime_type == SVG_MIME_TYPE + ), "PngConvertedSvgAttachment must be initialized using an SVG attachment" + assert attachment.file_name is not None, "The file_name must be filled" + super().__init__( + attachment.work_item_id, + "", + attachment.title, + None, + PNG_MIME_TYPE, + f"{attachment.file_name[:-3]}png", + ) + self._content_bytes: bytes | None = None + self._svg_attachment = attachment + + @property + def content_bytes(self): + """The content bytes are created from the SVG when requested.""" + if not self._content_bytes: + self._content_bytes = cairosvg.svg2png( + self._svg_attachment.content_bytes + ) + + return self._content_bytes + + @content_bytes.setter + def content_bytes(self, value: bytes | None): + self._content_bytes = value diff --git a/capella2polarion/data_models.py b/capella2polarion/data_model/work_items.py similarity index 54% rename from capella2polarion/data_models.py rename to capella2polarion/data_model/work_items.py index 2d985ea6..a58ae150 100644 --- a/capella2polarion/data_models.py +++ b/capella2polarion/data_model/work_items.py @@ -8,25 +8,16 @@ import hashlib import json import logging -import typing as t -import cairosvg import polarion_rest_api_client as polarion_api -from capellambse import model -from capellambse_context_diagrams import context -from capella2polarion.converters import text_work_item_provider +from capella2polarion.data_model import work_item_attachments as wi_att WORK_ITEM_CHECKSUM_KEY = "__C2P__WORK_ITEM" -SVG_MIME_TYPE = "image/svg+xml" -PNG_MIME_TYPE = "image/png" logger = logging.getLogger(__name__) -def _calculate_content_checksum( - attachment: polarion_api.WorkItemAttachment, -) -> str: - return base64.b64encode(attachment.content_bytes or b"").decode("utf8") +__all__ = ["CapellaWorkItem"] class CapellaWorkItem(polarion_api.WorkItem): @@ -87,12 +78,14 @@ def _calculate_attachment_checksums(self): ] = attachment for base_file_name, attachments in attachment_groups.items(): - if attachment := attachments.pop(SVG_MIME_TYPE, None): + if attachment := attachments.pop(wi_att.SVG_MIME_TYPE, None): # For SVGs we expect a PNG to be present - if png_attachment := attachments.pop(PNG_MIME_TYPE, None): + if png_attachment := attachments.pop( + wi_att.PNG_MIME_TYPE, None + ): # Only for non context diagrams we use the PNG if not isinstance( - attachment, CapellaContextDiagramAttachment + attachment, wi_att.CapellaContextDiagramAttachment ): attachment = png_attachment else: @@ -116,7 +109,7 @@ def _calculate_attachment_checksums(self): self.uuid_capella, ) - if isinstance(attachment, Capella2PolarionAttachment): + if isinstance(attachment, wi_att.Capella2PolarionAttachment): content_checksum = attachment.content_checksum else: logger.warning( @@ -126,7 +119,9 @@ def _calculate_attachment_checksums(self): self.id, self.uuid_capella, ) - content_checksum = _calculate_content_checksum(attachment) + content_checksum = wi_att.calculate_content_checksum( + attachment + ) attachment_checksums[base_file_name] = hashlib.sha256( json.dumps( @@ -189,148 +184,3 @@ def calculate_checksum(self) -> str: | dict(sorted(self._attachment_checksums.items())) ) return self.checksum - - -@dataclasses.dataclass -class Capella2PolarionAttachment(polarion_api.WorkItemAttachment): - """Stub Base-Class for Capella2Polarion attachments.""" - - _checksum: str | None = None - - @property - def content_checksum(self) -> str: - """Calculate the checksum for the content of the attachment.""" - if self._checksum is None: - self._checksum = _calculate_content_checksum(self) - return self._checksum - - -class CapellaDiagramAttachment(Capella2PolarionAttachment): - """A class for lazy loading content_bytes for diagram attachments.""" - - def __init__( - self, - diagram: model.AbstractDiagram, - file_name: str, - render_params: dict[str, t.Any] | None, - title: str, - ): - super().__init__( - "", - "", - title, - None, - SVG_MIME_TYPE, - file_name, - ) - self.render_params = render_params or {} - self.diagram = diagram - self._content_bytes: bytes | None = None - - @property - def content_bytes(self): - """Diagrams are only rendered, if content_bytes are requested.""" - if self._content_bytes: - return self._content_bytes - try: - diagram_svg = self.diagram.render("svg", **self.render_params) - except Exception as e: - logger.error( - "Failed to render diagram %s", self.diagram.name, exc_info=e - ) - diagram_svg = self.diagram.as_svg - if isinstance(diagram_svg, str): - diagram_svg = diagram_svg.encode("utf8") - self._content_bytes = diagram_svg - return diagram_svg - - @content_bytes.setter - def content_bytes(self, value: bytes | None): - self._content_bytes = value - - -class CapellaContextDiagramAttachment(CapellaDiagramAttachment): - """A dedicated attachment type for Capella context diagrams. - - Implements a checksum property using the elk input instead of - content. This will speed up the checksum calculation a lot. - """ - - def __init__( - self, - diagram: context.ContextDiagram, - file_name: str, - render_params: dict[str, t.Any] | None, - title: str, - ): - super().__init__(diagram, file_name, render_params, title) - - @property - def content_checksum(self): - """Return checksum based on elk input for ContextDiagrams else None.""" - if self._checksum is None: - elk_input = self.diagram.elk_input_data(self.render_params) - self._checksum = hashlib.sha256( - elk_input.json().encode("utf-8") - ).hexdigest() - return self._checksum - - -class PngConvertedSvgAttachment(Capella2PolarionAttachment): - """A special attachment type for PNGs which shall be created from SVGs. - - An SVG attachment must be provided to create this attachment. The - actual conversion of SVG to PNG takes place when content bytes are - requested. For that reason creating this attachment does not trigger - diagram rendering as long as context_bytes aren't requested. - """ - - def __init__(self, attachment: polarion_api.WorkItemAttachment): - assert ( - attachment.mime_type == SVG_MIME_TYPE - ), "PngConvertedSvgAttachment must be initialized using an SVG attachment" - assert attachment.file_name is not None, "The file_name must be filled" - super().__init__( - attachment.work_item_id, - "", - attachment.title, - None, - PNG_MIME_TYPE, - f"{attachment.file_name[:-3]}png", - ) - self._content_bytes: bytes | None = None - self._svg_attachment = attachment - - @property - def content_bytes(self): - """The content bytes are created from the SVG when requested.""" - if not self._content_bytes: - self._content_bytes = cairosvg.svg2png( - self._svg_attachment.content_bytes - ) - - return self._content_bytes - - @content_bytes.setter - def content_bytes(self, value: bytes | None): - self._content_bytes = value - - -@dataclasses.dataclass -class DocumentData: - """A class to store data related to a rendered document.""" - - document: polarion_api.Document - headings: list[polarion_api.WorkItem] - text_work_item_provider: text_work_item_provider.TextWorkItemProvider - - -@dataclasses.dataclass -class DocumentInfo: - """Class for information regarding a document which should be created.""" - - project_id: str | None - module_folder: str - module_name: str - text_work_item_type: str - text_work_item_id_field: str diff --git a/tests/conftest.py b/tests/conftest.py index fc991f8f..e08ec98b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,7 +14,7 @@ import pytest from capellambse import model as m -from capella2polarion import cli, data_models +from capella2polarion import cli, data_model from capella2polarion.connectors import polarion_repo, polarion_worker from capella2polarion.converters import ( converter_config, @@ -59,9 +59,9 @@ def model() -> capellambse.MelodyModel: @pytest.fixture -def dummy_work_items() -> dict[str, data_models.CapellaWorkItem]: +def dummy_work_items() -> dict[str, data_model.CapellaWorkItem]: return { - f"uuid{i}": data_models.CapellaWorkItem( + f"uuid{i}": data_model.CapellaWorkItem( id=f"Obj-{i}", uuid_capella=f"uuid{i}", title=f"Fake {i}", @@ -119,7 +119,7 @@ class BaseObjectContainer(t.NamedTuple): def base_object( model: capellambse.MelodyModel, monkeypatch: pytest.MonkeyPatch ) -> BaseObjectContainer: - work_item = data_models.CapellaWorkItem( + work_item = data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", status="open" ) c2p_cli = cli.Capella2PolarionCli( @@ -152,7 +152,7 @@ def base_object( "oa", fake_model_type_config, fake, - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", status="open", diff --git a/tests/test_documents.py b/tests/test_documents.py index 0f6525c9..8e22fce4 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -5,7 +5,7 @@ import pytest from lxml import etree, html -from capella2polarion import data_models as dm +from capella2polarion import data_model as dm from capella2polarion.connectors import polarion_repo, polarion_worker from capella2polarion.converters import ( document_config, diff --git a/tests/test_elements.py b/tests/test_elements.py index 1f557b48..3224f66d 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -15,7 +15,7 @@ from capellambse import model as m from capellambse_context_diagrams import context, filters -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo from capella2polarion.converters import ( converter_config, @@ -163,7 +163,7 @@ class GroupedLinksBaseObject(t.TypedDict): link_serializer: link_converter.LinkSerializer - work_items: dict[str, data_models.CapellaWorkItem] + work_items: dict[str, data_model.CapellaWorkItem] config: converter_config.CapellaTypeConfig @@ -171,7 +171,7 @@ class GroupedLinksBaseObject(t.TypedDict): @pytest.fixture() def grouped_links_base_object( base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + dummy_work_items: dict[str, data_model.CapellaWorkItem], ) -> GroupedLinksBaseObject: config = converter_config.CapellaTypeConfig( "fakeModelObject", links=[LINK_CONFIG] @@ -208,7 +208,7 @@ def diagr_base_object( base_object: BaseObjectContainer, ) -> BaseObjectContainer: uuid = diagram_cache_index[0]["uuid"] - work_item = data_models.CapellaWorkItem( + work_item = data_model.CapellaWorkItem( id="Diag-1", checksum="123", uuid_capella=uuid ) @@ -226,17 +226,17 @@ def diagr_base_object( @staticmethod def test_create_diagrams(diagr_base_object: BaseObjectContainer): pw = diagr_base_object.pw - new_work_items: dict[str, data_models.CapellaWorkItem] + new_work_items: dict[str, data_model.CapellaWorkItem] new_work_items = diagr_base_object.mc.generate_work_items( pw.polarion_data_repo, generate_attachments=True ) assert len(new_work_items) == 1 work_item = new_work_items[TEST_DIAG_UUID] - assert isinstance(work_item, data_models.CapellaWorkItem) + assert isinstance(work_item, data_model.CapellaWorkItem) description = work_item.description work_item.description = None work_item.attachments = [] - assert work_item == data_models.CapellaWorkItem(**TEST_SER_DIAGRAM) + assert work_item == data_model.CapellaWorkItem(**TEST_SER_DIAGRAM) assert description is not None assert description.value == TEST_DIAG_DESCR.format( title="Diagram", @@ -273,13 +273,13 @@ def test_create_work_items( mock_generic_work_item := mock.MagicMock(), ) mock_generic_work_item.side_effect = [ - expected := data_models.CapellaWorkItem( + expected := data_model.CapellaWorkItem( uuid_capella="uuid1", title="Fake 1", type="fakeModelObject", description=polarion_api.HtmlContent(markupsafe.Markup("")), ), - expected1 := data_models.CapellaWorkItem( + expected1 := data_model.CapellaWorkItem( uuid_capella="uuid2", title="Fake 2", type="fakeModelObject", @@ -321,7 +321,7 @@ def test_create_work_items_with_special_polarion_type( } base_object.c2pcli.capella_model = model - expected = data_models.CapellaWorkItem( + expected = data_model.CapellaWorkItem( uuid_capella=uuid, type=_type[0].lower() + _type[1:], description=polarion_api.HtmlContent(markupsafe.Markup("")), @@ -338,7 +338,7 @@ def test_create_work_items_with_special_polarion_type( @staticmethod def test_create_links_custom_resolver(base_object: BaseObjectContainer): - work_item_obj_2 = data_models.CapellaWorkItem( + work_item_obj_2 = data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", type="fakeModelObject", @@ -383,14 +383,14 @@ def test_create_links_custom_exchanges_resolver( funtion_obj = base_object.c2pcli.capella_model.by_uuid(function_uuid) obj = base_object.c2pcli.capella_model.by_uuid(uuid) - work_item_obj_1 = data_models.CapellaWorkItem( + work_item_obj_1 = data_model.CapellaWorkItem( id="Obj-1", uuid_capella=function_uuid, type=type(funtion_obj).__name__, description=polarion_api.HtmlContent(markupsafe.Markup("")), status="open", ) - work_item_obj_2 = data_models.CapellaWorkItem( + work_item_obj_2 = data_model.CapellaWorkItem( id="Obj-2", uuid_capella=uuid, type="functionalExchange", @@ -498,7 +498,7 @@ def test_create_links_no_new_links_with_errors( "\n\t" ) - work_item_obj_2 = data_models.CapellaWorkItem( + work_item_obj_2 = data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", type="fakeModelObject", @@ -548,14 +548,14 @@ def test_create_links_with_new_links_and_errors( "\n\t" ) - work_item_obj_2 = data_models.CapellaWorkItem( + work_item_obj_2 = data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", type="fakeModelObject", description=polarion_api.HtmlContent(markupsafe.Markup("")), status="open", ) - work_item_obj_1 = data_models.CapellaWorkItem( + work_item_obj_1 = data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", type="fakeModelObject", @@ -626,7 +626,7 @@ def test_create_links_from_ElementList(base_object: BaseObjectContainer): fake_objects = {"uuid4": fake, "uuid5": fake1, "uuid6": obj} work_items = [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id=f"Obj-{i}", uuid_capella=f"uuid{i}", type="fakeModelObject", @@ -675,7 +675,7 @@ def test_create_links_from_ElementList(base_object: BaseObjectContainer): def test_create_link_from_single_attribute( base_object: BaseObjectContainer, ): - work_item_2 = data_models.CapellaWorkItem( + work_item_2 = data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", type="fakeModelObject", @@ -707,7 +707,7 @@ def test_create_link_from_single_attribute( def test_create_link_from_single_attribute_with_role_prefix( base_object: BaseObjectContainer, ): - work_item_2 = data_models.CapellaWorkItem( + work_item_2 = data_model.CapellaWorkItem( id="Obj-2", type="_C2P_fakeModelObject", description=polarion_api.HtmlContent(markupsafe.Markup("")), @@ -741,8 +741,8 @@ def test_create_link_from_single_attribute_with_role_prefix( def test_update_work_items( monkeypatch: pytest.MonkeyPatch, base_object: BaseObjectContainer ): - polarion_work_item_list: list[data_models.CapellaWorkItem] = [ - data_models.CapellaWorkItem( + polarion_work_item_list: list[data_model.CapellaWorkItem] = [ + data_model.CapellaWorkItem( id="Obj-1", type="type", uuid_capella="uuid1", @@ -764,7 +764,7 @@ def test_update_work_items( base_object.pw.load_polarion_work_item_map() base_object.mc.converter_session["uuid1"].work_item = ( - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", title="Fake 1", @@ -807,7 +807,7 @@ def test_update_work_items( work_item = base_object.pw.project_client.work_items.update.call_args[ 0 ][0] - assert isinstance(work_item, data_models.CapellaWorkItem) + assert isinstance(work_item, data_model.CapellaWorkItem) assert work_item.id == "Obj-1" assert work_item.title == "Fake 1" assert work_item.description @@ -821,8 +821,8 @@ def test_update_work_items( def test_update_deleted_work_item( monkeypatch: pytest.MonkeyPatch, base_object: BaseObjectContainer ): - polarion_work_item_list: list[data_models.CapellaWorkItem] = [ - data_models.CapellaWorkItem( + polarion_work_item_list: list[data_model.CapellaWorkItem] = [ + data_model.CapellaWorkItem( id="Obj-1", type="type", uuid_capella="uuid1", @@ -840,7 +840,7 @@ def test_update_deleted_work_item( base_object.pw.load_polarion_work_item_map() base_object.mc.converter_session["uuid1"].work_item = ( - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", type="type", uuid_capella="uuid1", @@ -877,7 +877,7 @@ def test_update_deleted_work_item( work_item = base_object.pw.project_client.work_items.update.call_args[ 0 ][0] - assert isinstance(work_item, data_models.CapellaWorkItem) + assert isinstance(work_item, data_model.CapellaWorkItem) assert work_item.status == "open" @staticmethod @@ -886,7 +886,7 @@ def test_update_work_items_filters_work_items_with_same_checksum( ): base_object.pw.polarion_data_repo.update_work_items( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", status="open", @@ -911,7 +911,7 @@ def test_update_work_items_same_checksum_force( base_object.pw.force_update = True base_object.pw.polarion_data_repo.update_work_items( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", status="open", @@ -957,7 +957,7 @@ def test_update_links(base_object: BaseObjectContainer): work_item.linked_work_items = [link] base_object.pw.polarion_data_repo.update_work_items( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", status="open", @@ -966,7 +966,7 @@ def test_update_links(base_object: BaseObjectContainer): ] ) base_object.mc.converter_session["uuid2"].work_item = ( - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", status="open", @@ -1039,7 +1039,7 @@ def test_update_links(base_object: BaseObjectContainer): def test_patch_work_item_grouped_links( monkeypatch: pytest.MonkeyPatch, base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + dummy_work_items: dict[str, data_model.CapellaWorkItem], ): base_object.mc.converter_session = { work_item.uuid_capella: data_session.ConverterData( @@ -1053,13 +1053,13 @@ def test_patch_work_item_grouped_links( base_object.pw.polarion_data_repo = ( polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-0", uuid_capella="uuid0", status="open" ), - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-1", uuid_capella="uuid1", status="open" ), - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", status="open" ), ] @@ -1140,7 +1140,7 @@ def mock_back_link(converter_data, back_links): @staticmethod def test_maintain_grouped_links_attributes( base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + dummy_work_items: dict[str, data_model.CapellaWorkItem], ): config = converter_config.CapellaTypeConfig( "fakeModelObject", @@ -1200,7 +1200,7 @@ def test_maintain_grouped_links_attributes( @staticmethod def test_maintain_grouped_links_attributes_with_role_prefix( base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + dummy_work_items: dict[str, data_model.CapellaWorkItem], ): config = converter_config.CapellaTypeConfig( "fakeModelObject", @@ -1255,7 +1255,7 @@ def test_grouped_links_attributes_different_link_field_in_config( ): converter_data_1 = base_object.mc.converter_session["uuid1"] converter_data_2 = base_object.mc.converter_session["uuid2"] - converter_data_2.work_item = data_models.CapellaWorkItem( + converter_data_2.work_item = data_model.CapellaWorkItem( id="Obj-2", uuid_capella="uuid2", status="open" ) base_object.pw.polarion_data_repo.update_work_items( @@ -1344,7 +1344,7 @@ def test_grouped_links_attributes_with_includes( work_items = converter.generate_work_items( base_object.pw.polarion_data_repo ) - work_item: data_models.CapellaWorkItem | None + work_item: data_model.CapellaWorkItem | None for i, work_item in enumerate(work_items.values()): work_item.id = f"WI-{i}" @@ -1513,7 +1513,7 @@ def test_grouped_linked_work_items_order_consistency( config = converter_config.CapellaTypeConfig( "fakeModelObject", ) - work_item = data_models.CapellaWorkItem("id", title="Dummy") + work_item = data_model.CapellaWorkItem("id", title="Dummy") converter_data = data_session.ConverterData( "test", config, FakeModelObject(""), work_item ) @@ -1579,7 +1579,7 @@ def test_diagram(model: capellambse.MelodyModel): serialized_diagram.attachments = [] - assert serialized_diagram == data_models.CapellaWorkItem( + assert serialized_diagram == data_model.CapellaWorkItem( type="diagram", uuid_capella=TEST_DIAG_UUID, title="[CC] Capability", @@ -1769,7 +1769,7 @@ def test_generic_work_item( model, polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( id="TEST", uuid_capella=TEST_E_UUID ) ] @@ -1789,7 +1789,7 @@ def test_generic_work_item( status = work_item.status work_item.status = None - assert work_item == data_models.CapellaWorkItem(**expected) + assert work_item == data_model.CapellaWorkItem(**expected) assert status == "open" @staticmethod @@ -2023,7 +2023,7 @@ def test_generic_work_item_with_type_prefix( type_config = config.get_type_config(layer, c_type, **attributes) assert type_config is not None type_config.p_type = f"{prefix}_{type_config.p_type}" - ework_item = data_models.CapellaWorkItem(id=f"{prefix}_TEST") + ework_item = data_model.CapellaWorkItem(id=f"{prefix}_TEST") serializer = element_converter.CapellaWorkItemSerializer( model, polarion_repo.PolarionDataRepository([ework_item]), @@ -2035,7 +2035,7 @@ def test_generic_work_item_with_type_prefix( assert work_item is not None work_item.status = None - assert work_item == data_models.CapellaWorkItem(**expected) + assert work_item == data_model.CapellaWorkItem(**expected) @staticmethod def test_read_config_context_diagram_with_params(): diff --git a/tests/test_polarion_worker_documents.py b/tests/test_polarion_worker_documents.py index 714847bb..c7ddb12c 100644 --- a/tests/test_polarion_worker_documents.py +++ b/tests/test_polarion_worker_documents.py @@ -4,7 +4,7 @@ import polarion_rest_api_client as polarion_api -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_worker from capella2polarion.converters import text_work_item_provider @@ -29,7 +29,7 @@ def test_update_document( value=path.read_text("utf-8"), ), ) - document_data = data_models.DocumentData( + document_data = data_model.DocumentData( document, [], text_work_item_provider.TextWorkItemProvider( @@ -78,7 +78,7 @@ def test_create_document( value=path.read_text("utf-8"), ), ) - document_data = data_models.DocumentData( + document_data = data_model.DocumentData( document, [], text_work_item_provider.TextWorkItemProvider( @@ -123,7 +123,7 @@ def test_use_correct_client( ), ) - document_data = data_models.DocumentData( + document_data = data_model.DocumentData( document, [], text_work_item_provider.TextWorkItemProvider(), diff --git a/tests/test_workitem_attachments.py b/tests/test_workitem_attachments.py index 0a7e692a..6bdb5504 100644 --- a/tests/test_workitem_attachments.py +++ b/tests/test_workitem_attachments.py @@ -11,7 +11,7 @@ import pytest from capellambse_context_diagrams import context -from capella2polarion import data_models +from capella2polarion import data_model from capella2polarion.connectors import polarion_repo, polarion_worker from capella2polarion.converters import ( converter_config, @@ -136,11 +136,11 @@ def test_diagram_attachments_new( ): converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( - [data_models.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID)] + [data_model.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID)] ) worker.project_client.work_items.get.return_value = ( - data_models.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID) + data_model.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID) ) worker.project_client.work_items.attachments = mock.MagicMock() worker.project_client.work_items.attachments.create.side_effect = ( @@ -166,7 +166,7 @@ def test_diagram_attachments_new( created_attachments: list[polarion_api.WorkItemAttachment] = ( worker.project_client.work_items.attachments.create.call_args.args[0] ) - work_item: data_models.CapellaWorkItem = ( + work_item: data_model.CapellaWorkItem = ( worker.project_client.work_items.update.call_args.args[0] ) @@ -197,14 +197,14 @@ def test_new_diagram( worker.polarion_data_repo = polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, checksum=checksum ) ] ) worker.project_client.work_items.get.return_value = ( - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, checksum=checksum ) ) @@ -243,7 +243,7 @@ def test_diagram_attachments_updated( ): converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( - [data_models.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID)] + [data_model.CapellaWorkItem(WORKITEM_ID, uuid_capella=TEST_DIAG_UUID)] ) existing_attachments = [ polarion_api.WorkItemAttachment( @@ -261,7 +261,7 @@ def test_diagram_attachments_updated( ] worker.project_client.work_items.get.return_value = ( - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, attachments=existing_attachments, @@ -290,7 +290,7 @@ def test_diagram_attachments_updated( assert worker.project_client.work_items.attachments.update.call_count == 2 assert worker.project_client.work_items.attachments.get_all.call_count == 1 - work_item: data_models.CapellaWorkItem = ( + work_item: data_model.CapellaWorkItem = ( worker.project_client.work_items.update.call_args.args[0] ) @@ -307,7 +307,7 @@ def test_diagram_attachments_unchanged_work_item_changed( worker: polarion_worker.CapellaPolarionWorker, ): converter = model_converter.ModelConverter(model, "TEST") - diagram_work_item = data_models.CapellaWorkItem( + diagram_work_item = data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, checksum=json.dumps( @@ -358,7 +358,7 @@ def test_diagram_attachments_unchanged_work_item_changed( assert worker.project_client.work_items.attachments.create.call_count == 0 assert worker.project_client.work_items.attachments.update.call_count == 0 - work_item: data_models.CapellaWorkItem = ( + work_item: data_model.CapellaWorkItem = ( worker.project_client.work_items.update.call_args.args[0] ) @@ -377,7 +377,7 @@ def test_diagram_attachments_fully_unchanged( converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, checksum=DIAGRAM_CHECKSUM, @@ -410,7 +410,7 @@ def test_add_context_diagram( uuid = "11906f7b-3ae9-4343-b998-95b170be2e2b" converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( - [data_models.CapellaWorkItem(WORKITEM_ID, uuid_capella=uuid)] + [data_model.CapellaWorkItem(WORKITEM_ID, uuid_capella=uuid)] ) converter.converter_session[uuid] = data_session.ConverterData( @@ -434,7 +434,7 @@ def test_add_context_diagram( created_attachments: list[polarion_api.WorkItemAttachment] = ( worker.project_client.work_items.attachments.create.call_args.args[0] ) - work_item: data_models.CapellaWorkItem = ( + work_item: data_model.CapellaWorkItem = ( worker.project_client.work_items.update.call_args.args[0] ) @@ -463,7 +463,7 @@ def test_update_context_diagram_no_changes( converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=uuid, checksum=json.dumps( @@ -499,7 +499,7 @@ def test_update_context_diagram_with_changes( converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=uuid, checksum=json.dumps( @@ -557,7 +557,7 @@ def test_diagram_delete_attachments( converter = model_converter.ModelConverter(model, "TEST") worker.polarion_data_repo = polarion_repo.PolarionDataRepository( [ - data_models.CapellaWorkItem( + data_model.CapellaWorkItem( WORKITEM_ID, uuid_capella=TEST_DIAG_UUID, checksum=json.dumps( @@ -609,7 +609,7 @@ def test_diagram_delete_attachments( assert worker.project_client.work_items.attachments.update.call_count == 0 assert worker.project_client.work_items.attachments.delete.call_count == 2 - work_item: data_models.CapellaWorkItem = ( + work_item: data_model.CapellaWorkItem = ( worker.project_client.work_items.update.call_args.args[0] )