diff --git a/pyproject.toml b/pyproject.toml index bec5594..1f99f1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,8 @@ tests = [ ] type_check = [ "mypy==1.13.0", - "types-requests==2.32.0.20241016" + "types-requests==2.32.0.20241016", + "lxml-stubs==0.5.1" ] [project.urls] diff --git a/src/rebdhuhn/__init__.py b/src/rebdhuhn/__init__.py index 718c8a7..7168c01 100644 --- a/src/rebdhuhn/__init__.py +++ b/src/rebdhuhn/__init__.py @@ -5,3 +5,12 @@ from rebdhuhn.graph_conversion import convert_table_to_digraph, convert_table_to_graph from rebdhuhn.graphviz import convert_dot_to_svg_kroki, convert_graph_to_dot from rebdhuhn.plantuml import convert_graph_to_plantuml, convert_plantuml_to_svg_kroki + +__all__ = [ + "convert_table_to_digraph", + "convert_table_to_graph", + "convert_dot_to_svg_kroki", + "convert_graph_to_dot", + "convert_graph_to_plantuml", + "convert_plantuml_to_svg_kroki", +] diff --git a/src/rebdhuhn/add_watermark.py b/src/rebdhuhn/add_watermark.py index 2497049..8637e84 100644 --- a/src/rebdhuhn/add_watermark.py +++ b/src/rebdhuhn/add_watermark.py @@ -10,7 +10,7 @@ from pathlib import Path from typing import TextIO, Tuple, Union -from lxml import etree # type:ignore[import-untyped] +from lxml import etree from svgutils.compose import SVG, Figure # type:ignore[import-untyped] # Sets the size of the watermark compared to the smaller dimension of the ebd diagram @@ -46,8 +46,8 @@ def get_dimensions_of_svg(svg_as_bytes: Union[BytesIO, TextIO]) -> Tuple[float, root = tree.getroot() # root.attrib["height"] gives a string like "123px" # for further usage, we have to remove the unit and convert it to integer - width_of_svg_in_px = convert_dimension_to_float(root.attrib["width"]) - height_of_svg_in_px = convert_dimension_to_float(root.attrib["height"]) + width_of_svg_in_px = convert_dimension_to_float(str(root.attrib["width"])) + height_of_svg_in_px = convert_dimension_to_float(str(root.attrib["height"])) return width_of_svg_in_px, height_of_svg_in_px diff --git a/tox.ini b/tox.ini index c762d06..ea2d72d 100644 --- a/tox.ini +++ b/tox.ini @@ -46,10 +46,11 @@ commands = setenv = PYTHONPATH = {toxinidir}/src deps = -r requirements.txt + .[tests] .[type_check] commands = mypy --show-error-codes --strict src/rebdhuhn - mypy --show-error-codes unittests + mypy --show-error-codes --strict unittests # add single files (ending with .py) or packages here [testenv:coverage] diff --git a/unittests/test_ebd_table_models.py b/unittests/test_ebd_table_models.py index 3288fae..11f676e 100644 --- a/unittests/test_ebd_table_models.py +++ b/unittests/test_ebd_table_models.py @@ -1,5 +1,5 @@ import cattrs -import pytest # type:ignore[import] +import pytest from rebdhuhn.models.ebd_table import ( EbdCheckResult, @@ -46,7 +46,7 @@ class TestEbdTableModels: ) ], ) - def test_instantiation(self, table: EbdTable): + def test_instantiation(self, table: EbdTable) -> None: """ The test is successful already if the instantiation in the parametrization worked """ @@ -118,11 +118,11 @@ def test_instantiation(self, table: EbdTable): ), ], ) - def test_has_subsequent_steps(self, row: EbdTableRow, expected_result: bool): + def test_has_subsequent_steps(self, row: EbdTableRow, expected_result: bool) -> None: actual = row.has_subsequent_steps() assert actual == expected_result - def test_ebd_table_row_use_cases(self): + def test_ebd_table_row_use_cases(self) -> None: row_17_in_e0462 = EbdTableRow( step_number="17", description="Liegt das Eingangsdatum der Anmeldung mehr als sechs Wochen nach dem Lieferbeginndatum der Anmeldung?", @@ -144,7 +144,7 @@ def test_ebd_table_row_use_cases(self): assert row_17_in_e0462.use_cases is not None # if it can be instantiated with use cases that's a good enough test for the model - def test_answer_code_aastersik(self): + def test_answer_code_astersik(self) -> None: """ This is an example from 6.27.1 E_0455_Information prüfen. The tests asserts that the validator of the result code allow the result code 'A**' which is used in E_0455. @@ -157,7 +157,7 @@ def test_answer_code_aastersik(self): assert isinstance(sub_row, EbdTableSubRow) assert sub_row.result_code == "A**" - def test_2023_answer_code_regex(self): + def test_2023_answer_code_regex(self) -> None: """ This is an example from E_0406. The test asserts that the validator of the result code allows the result code 'AC7'. @@ -170,7 +170,7 @@ def test_2023_answer_code_regex(self): assert isinstance(sub_row, EbdTableSubRow) assert sub_row.result_code == "AC7" - def test_collect_answer_codes_instruction(self): + def test_collect_answer_codes_instruction(self) -> None: snippet_from_e0453 = EbdTable( metadata=EbdTableMetaData( ebd_code="E_0453", diff --git a/unittests/test_errors.py b/unittests/test_errors.py index 8bce390..4700ea3 100644 --- a/unittests/test_errors.py +++ b/unittests/test_errors.py @@ -1,4 +1,4 @@ -import pytest # type:ignore[import] +import pytest from rebdhuhn import convert_graph_to_plantuml, convert_table_to_graph from rebdhuhn.models import EbdTable @@ -25,39 +25,39 @@ class TestErrors: """ @pytest.mark.parametrize("table", [pytest.param(table_e0459)]) - def test_not_exactly_two_outgoing_edges_error(self, table: EbdTable): + def test_not_exactly_two_outgoing_edges_error(self, table: EbdTable) -> None: ebd_graph = convert_table_to_graph(table) with pytest.raises(NotExactlyTwoOutgoingEdgesError): _ = convert_graph_to_plantuml(ebd_graph) @pytest.mark.parametrize("table", [pytest.param(table_e0266)]) - def test_loops_in_the_tree_error(self, table: EbdTable): + def test_loops_in_the_tree_error(self, table: EbdTable) -> None: ebd_graph = convert_table_to_graph(table) with pytest.raises(PathsNotGreaterThanOneError): _ = convert_graph_to_plantuml(ebd_graph) @pytest.mark.parametrize("table", [pytest.param(table_e0454)]) - def test_too_complex_for_plantuml(self, table: EbdTable): + def test_too_complex_for_plantuml(self, table: EbdTable) -> None: ebd_graph = convert_table_to_graph(table) with pytest.raises(GraphTooComplexForPlantumlError): _ = convert_graph_to_plantuml(ebd_graph) @pytest.mark.parametrize("table", [pytest.param(e_0401)]) - def test_key_error_because_first_node_has_key_other_than_1(self, table: EbdTable): + def test_key_error_because_first_node_has_key_other_than_1(self, table: EbdTable) -> None: _ = convert_table_to_graph(table) # must _not_ raise a key error anymore @pytest.mark.parametrize("table", [pytest.param(e_0529)]) - def test_backreference_to_missing_node_with_key_1(self, table: EbdTable): + def test_backreference_to_missing_node_with_key_1(self, table: EbdTable) -> None: graph = convert_table_to_graph(table) _ = convert_graph_to_plantuml(graph) # must _not_ raise an assertion error anymore @pytest.mark.parametrize("table", [pytest.param(e_0404)]) - def test_ende_in_wrong_column_error(self, table: EbdTable): + def test_ende_in_wrong_column_error(self, table: EbdTable) -> None: with pytest.raises(EndeInWrongColumnError): _ = convert_table_to_graph(table) @pytest.mark.parametrize("table", [pytest.param(table_e0462)]) - def test_cross_reference_not_supported_error(self, table: EbdTable): + def test_cross_reference_not_supported_error(self, table: EbdTable) -> None: with pytest.raises(EbdCrossReferenceNotSupportedError) as exc_info: _ = convert_table_to_graph(table) assert exc_info.value.cross_reference == "E_0402_Prüfen," diff --git a/unittests/test_table_to_graph.py b/unittests/test_table_to_graph.py index 878a117..e88ae72 100644 --- a/unittests/test_table_to_graph.py +++ b/unittests/test_table_to_graph.py @@ -1,10 +1,11 @@ +# mypy: disable-error-code="no-untyped-def" import os from pathlib import Path from typing import List, Optional -import pytest # type:ignore[import] -from lxml import etree # type:ignore[import] -from networkx import DiGraph # type:ignore[import] +import pytest +from lxml import etree +from networkx import DiGraph # type:ignore[import-untyped] from rebdhuhn import convert_graph_to_plantuml, convert_plantuml_to_svg_kroki, convert_table_to_graph from rebdhuhn.graph_conversion import get_all_edges, get_all_nodes @@ -33,12 +34,12 @@ class InterceptedKrokiClient(Kroki): purposes. """ - def __init__(self): + def __init__(self) -> None: super().__init__() self.intercepted_kroki_response: Optional[str] = None self.intercepted_kroki_response_with_xml_comment: Optional[str] = None - def convert_dot_to_svg(self, *args, **kwargs): + def convert_dot_to_svg(self, *args, **kwargs) -> str: result = super().convert_dot_to_svg(*args, **kwargs) self.intercepted_kroki_response = result result_tree = etree.fromstring(result.encode("utf-8")) @@ -72,7 +73,7 @@ class TestEbdTableModels: ) ], ) - def test_get_all_nodes(self, table: EbdTable, expected_result: List[EbdGraphNode]): + def test_get_all_nodes(self, table: EbdTable, expected_result: List[EbdGraphNode]) -> None: actual = get_all_nodes(table) assert actual == expected_result @@ -123,7 +124,7 @@ def test_get_all_nodes(self, table: EbdTable, expected_result: List[EbdGraphNode ) ], ) - def test_get_all_edges(self, table: EbdTable, expected_result: List[EbdGraphEdge]): + def test_get_all_edges(self, table: EbdTable, expected_result: List[EbdGraphEdge]) -> None: actual = get_all_edges(table) assert actual == expected_result @@ -167,7 +168,7 @@ def test_table_to_digraph(self, table: EbdTable, expected_description: str): svg_file.write(svg_code) @staticmethod - def create_and_save_svg_test(ebd_graph: EbdGraph): + def create_and_save_svg_test(ebd_graph: EbdGraph) -> str: """ Creates the test svgs and saves them to the output folder. Also returns the kroki answer svg code as string to be stored for the mock request. @@ -187,6 +188,7 @@ def create_and_save_svg_test(ebd_graph: EbdGraph): svg_file.write(svg_code) svg_code_for_mock = kroki_client.intercepted_kroki_response_with_xml_comment + assert svg_code_for_mock is not None return svg_code_for_mock @pytest.mark.parametrize( @@ -213,7 +215,7 @@ def create_and_save_svg_test(ebd_graph: EbdGraph): ), ], ) - def test_table_to_digraph_dot_real_kroki_request(self, table: EbdTable, expected_description: str): + def test_table_to_digraph_dot_real_kroki_request(self, table: EbdTable, expected_description: str) -> None: """ Test the conversion pipeline. The results are stored in `unittests/output` for you to inspect the result manually. The test only checks if the svg can be built. @@ -257,7 +259,7 @@ def test_table_to_digraph_dot_real_kroki_request(self, table: EbdTable, expected ), ], ) - def test_table_to_digraph_dot_with_mock(self, table: EbdTable, expected_description: str, requests_mock): + def test_table_to_digraph_dot_with_mock(self, table: EbdTable, expected_description: str, requests_mock) -> None: """ Test the conversion pipeline. The results are stored in `unittests/output` for you to inspect the result manually. The test only checks if the svg can be built. @@ -275,7 +277,7 @@ def test_table_to_digraph_dot_with_mock(self, table: EbdTable, expected_descript self.create_and_save_svg_test(ebd_graph) @staticmethod - def create_and_save_watermark_and_background_svg(add_background: bool): + def create_and_save_watermark_and_background_svg(add_background: bool) -> str: """ Creates the test svgs and saves them to the output folder. Also returns the kroki answer svg code as string to be stored for the mock request. @@ -308,6 +310,7 @@ def create_and_save_watermark_and_background_svg(add_background: bool): ebd_svg.write(svg_code_with_watermark) svg_code_for_mock = kroki_client.intercepted_kroki_response_with_xml_comment + assert svg_code_for_mock is not None return svg_code_for_mock @pytest.mark.parametrize( @@ -348,7 +351,7 @@ def test_table_to_digraph_dot_with_watermark_real_kroki_request(self, add_backgr ), ], ) - def test_table_to_digraph_dot_with_watermark_with_mock(self, add_background: bool, requests_mock): + def test_table_to_digraph_dot_with_watermark_with_mock(self, add_background: bool, requests_mock) -> None: """ Test the combination of background and watermark addition to the svg. The results are stored in `unittests/output` for you to inspect the result manually. @@ -361,7 +364,7 @@ def test_table_to_digraph_dot_with_watermark_with_mock(self, add_background: boo requests_mock.post("http://localhost:8125/", text=kroki_response_string) self.create_and_save_watermark_and_background_svg(add_background) - def test_table_to_digraph_dot_with_background(self, requests_mock): + def test_table_to_digraph_dot_with_background(self, requests_mock) -> None: """ Test the addition of a background in 'HF white' to the svg. The results are stored in `unittests/output` for you to inspect the result manually. @@ -396,7 +399,7 @@ def test_table_to_digraph_dot_with_background(self, requests_mock): with open(file_path2, "w", encoding="utf-8") as ebd_svg: ebd_svg.write(svg_code) - def test_table_e0401_too_complex_for_plantuml(self): + def test_table_e0401_too_complex_for_plantuml(self) -> None: """ Test the conversion pipeline for E_0401. In this case the plantuml conversion should fail because the graph is too complex for this implementation. @@ -463,7 +466,7 @@ def test_table_e0401_too_complex_for_plantuml(self): # todo: add E_0462 ], ) - def test_table_to_graph(self, table: EbdTable, expected_result: EbdGraph): + def test_table_to_graph(self, table: EbdTable, expected_result: EbdGraph) -> None: actual = convert_table_to_graph(table) pytest.skip("todo @leon - wird später in den examples.py ergänzt") assert actual == expected_result