diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 98fe259..e138c8f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -13,6 +13,8 @@ jobs: os: [ubuntu-latest] steps: - uses: actions/checkout@v4 + with: + submodules: 'recursive' - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 3cf5358..ec1ce60 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -13,6 +13,8 @@ jobs: os: [ubuntu-latest] steps: - uses: actions/checkout@v4 + with: + submodules: 'recursive' - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: diff --git a/docker-compose.yaml b/docker-compose.yaml index c6339fd..ec6319c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,9 @@ services: kroki: image: yuzutech/kroki:0.24.1 - + ports: + - "8000:8000" # Expose localhost:8000 + # this is required for the test_main.py to directly use kroki scrape-and-plot: build: . image: ghcr.io/hochfrequenz/ebd_toolchain:latest diff --git a/pyproject.toml b/pyproject.toml index 5f0cf24..01bd931 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ ] dependencies = [ "ebdamame>=0.1.3", - "rebdhuhn>=0.4.0", + "rebdhuhn>=0.5.1", "cattrs", "click", "pydantic-settings" diff --git a/src/ebd_toolchain/main.py b/src/ebd_toolchain/main.py index d4c4268..7979af4 100644 --- a/src/ebd_toolchain/main.py +++ b/src/ebd_toolchain/main.py @@ -36,7 +36,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from rebdhuhn.graph_conversion import convert_table_to_graph from rebdhuhn.graphviz import convert_dot_to_svg_kroki, convert_graph_to_dot -from rebdhuhn.kroki import DotToSvgConverter, Kroki +from rebdhuhn.kroki import DotToSvgConverter, Kroki, KrokiDotBadRequestError, KrokiPlantUmlBadRequestError from rebdhuhn.models.ebd_graph import EbdGraph from rebdhuhn.models.ebd_table import EbdTable from rebdhuhn.models.errors import ( @@ -108,11 +108,16 @@ def _dump_json(json_path: Path, ebd_table: EbdTable) -> None: multiple=True, help="Choose which file you'd like to create", ) -# pylint:disable=too-many-locals, too-many-branches, too-many-statements, def main(input_path: Path, output_path: Path, export_types: list[Literal["puml", "dot", "json", "svg"]]) -> None: """ A program to get a machine-readable version of the AHBs docx files published by edi@energy. """ + _main(input_path, output_path, export_types) + + +# pylint:disable=too-many-locals, too-many-branches, too-many-statements, +def _main(input_path: Path, output_path: Path, export_types: list[Literal["puml", "dot", "json", "svg"]]) -> None: + """same as main but without the click decorators""" settings = Settings() # type:ignore[call-arg] # read settings from environment variable/.env file kroki_client = Kroki(kroki_host=f"http://{settings.kroki_host}:{settings.kroki_port}") @@ -175,7 +180,11 @@ def handle_known_error(error: Exception, ebd_key: str) -> None: except AssertionError as assertion_error: # https://github.com/Hochfrequenz/rebdhuhn/issues/35 click.secho(str(assertion_error), fg="red") - except (NotExactlyTwoOutgoingEdgesError, GraphTooComplexForPlantumlError) as known_issue: + except ( + NotExactlyTwoOutgoingEdgesError, + GraphTooComplexForPlantumlError, + KrokiPlantUmlBadRequestError, + ) as known_issue: handle_known_error(known_issue, ebd_key) except Exception as general_error: # pylint:disable=broad-exception-caught click.secho(f"Error while exporting {ebd_key} as UML: {str(general_error)}; Skip!", fg="yellow") @@ -189,7 +198,7 @@ def handle_known_error(error: Exception, ebd_key: str) -> None: svg_path = output_path / Path(f"{ebd_key}.svg") _dump_svg(svg_path, ebd_graph, kroki_client) click.secho(f"💾 Successfully exported '{ebd_key}.svg' to {svg_path.absolute()}") - except PathsNotGreaterThanOneError as known_issue: + except (PathsNotGreaterThanOneError, KrokiDotBadRequestError) as known_issue: handle_known_error(known_issue, ebd_key) except AssertionError as assertion_error: # e.g. AssertionError: If indegree > 1, the number of paths should always be greater than 1 too. diff --git a/unittests/test_main.py b/unittests/test_main.py new file mode 100644 index 0000000..e0d0988 --- /dev/null +++ b/unittests/test_main.py @@ -0,0 +1,39 @@ +""" +tests the main script +""" + +from pathlib import Path +from typing import Literal + +import pytest +from _pytest.monkeypatch import MonkeyPatch + +from ebd_toolchain.main import _main + +repo_root = Path(__file__).parent.parent +recent_docx_file = ( + repo_root + / "edi_energy_mirror" + / "edi_energy_de" + / "FV2504" + / "Entscheidungsbaum-DiagrammeundCodelisten-informatorischeLesefassung4.0a_99991231_20250404.docx" +) +assert recent_docx_file.exists() + + +@pytest.mark.parametrize( + "input_path, export_types", [pytest.param(recent_docx_file, ["puml", "dot", "json", "svg"], id="recent call")] +) +def test_main( + input_path: Path, + export_types: list[Literal["puml", "dot", "json", "svg"]], + tmp_path: Path, + monkeypatch: MonkeyPatch, +) -> None: + monkeypatch.setenv("KROKI_PORT", "8000") + monkeypatch.setenv("KROKI_HOST", "localhost") + # if you run into ConnectionErrors use + # docker-compose up -d + # in the repo root + _main(input_path, tmp_path, export_types) + # we don't assert on the results but instead just check that it doesn't crash