diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c020b3b..92fc973 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,18 @@ # to update all repo revisions just run: pre-commit autoupdate repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v5.0.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.10.0 hooks: - id: black language_version: python3 - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort name: isort (python) diff --git a/pyproject.toml b/pyproject.toml index a1c011d..b7f7f58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ ] dependencies = [ "ebdamame>=0.4.1", - "rebdhuhn>=0.9.0", + "rebdhuhn>=0.14.6", "cattrs", "click", "pydantic-settings" diff --git a/requirements.txt b/requirements.txt index c8e590c..ab7c5ee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -48,7 +48,7 @@ python-docx==1.1.2 # via ebdamame python-dotenv==1.0.1 # via pydantic-settings -rebdhuhn==0.14.2 +rebdhuhn==0.14.6 # via # ebd-toolchain (pyproject.toml) # ebdamame diff --git a/src/ebd_toolchain/main.py b/src/ebd_toolchain/main.py index 9430ad5..f4fa79d 100644 --- a/src/ebd_toolchain/main.py +++ b/src/ebd_toolchain/main.py @@ -34,7 +34,7 @@ from ebdamame.docxtableconverter import DocxTableConverter from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict -from rebdhuhn.graph_conversion import convert_empty_table_to_graph, convert_table_to_graph +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, KrokiDotBadRequestError, KrokiPlantUmlBadRequestError from rebdhuhn.models.ebd_graph import EbdGraph @@ -82,16 +82,7 @@ def _dump_svg(svg_path: Path, ebd_graph: EbdGraph, converter: DotToSvgConverter) def _dump_json(json_path: Path, ebd_table: EbdTable | EbdTableMetaData) -> None: with open(json_path, "w+", encoding="utf-8") as json_file: - if isinstance(ebd_table, EbdTableMetaData): - json.dump( - cattrs.unstructure(EbdTable(metadata=ebd_table, rows=[])), - json_file, - ensure_ascii=False, - indent=2, - sort_keys=True, - ) - else: - json.dump(cattrs.unstructure(ebd_table), json_file, ensure_ascii=False, indent=2, sort_keys=True) + json.dump(cattrs.unstructure(ebd_table), json_file, ensure_ascii=False, indent=2, sort_keys=True) @click.command() @@ -130,11 +121,13 @@ def _main(input_path: Path, output_path: Path, export_types: list[Literal["puml" 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}") - if output_path.exists(): - click.secho(f"The output directory '{output_path}' exists already.", fg="yellow") - else: - output_path.mkdir(parents=True) - click.secho(f"Created a new directory at {output_path}", fg="green") + if output_path.exists() and output_path.is_dir(): + click.secho(f"The output directory '{output_path}' exists already. Will remove its content.", fg="yellow") + for item in output_path.iterdir(): + if item.is_file(): + item.unlink() + output_path.mkdir(parents=True, exist_ok=True) + click.secho(f"Created a new directory at {output_path}", fg="green") all_ebd_keys = get_all_ebd_keys(input_path) error_sources: dict[type, list[str]] = {} @@ -153,59 +146,29 @@ def handle_known_error(error: Exception, ebd_key: str) -> None: continue assert ebd_kapitel is not None assert ebd_kapitel.subsection_title is not None - if isinstance(docx_tables, EbdNoTableSection): - ebd_meta_data = EbdTableMetaData( - ebd_code=ebd_key, - ebd_name=ebd_kapitel.subsection_title, - chapter=ebd_kapitel.chapter_title, # type:ignore[arg-type] - # pylint:disable=line-too-long - section=f"{ebd_kapitel.chapter}.{ebd_kapitel.section}.{ebd_kapitel.subsection}: {ebd_kapitel.section_title}", - role="N/A", - remark=docx_tables.remark, - ) - if "json" in export_types: - json_path = output_path / Path(f"{ebd_key}.json") - _dump_json(json_path, ebd_meta_data) - click.secho(f"💾 Successfully exported '{ebd_key}.json' to {json_path.absolute()}") - try: - ebd_graph = convert_empty_table_to_graph(ebd_meta_data) - except ( - EbdCrossReferenceNotSupportedError, - EndeInWrongColumnError, - OutcomeCodeAmbiguousError, - ) as known_issue: - handle_known_error(known_issue, ebd_key) - continue - except Exception as unknown_error: # pylint:disable=broad-except - click.secho(f"Error while graphing {ebd_key}: {str(unknown_error)}; Skip!", fg="red") - continue - try: - if "dot" in export_types: - dot_path = output_path / Path(f"{ebd_key}.dot") - _dump_dot(dot_path, ebd_graph) - click.secho(f"💾 Successfully exported '{ebd_key}.dot' to {dot_path.absolute()}") - if "svg" in export_types: - 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, 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. - click.secho(str(assertion_error), fg="red") - # both the SVG and dot path require graphviz to work, hence the common error handling block - continue try: - assert not isinstance(docx_tables, EbdNoTableSection) - converter = DocxTableConverter( - docx_tables, - ebd_key=ebd_key, - ebd_name=ebd_kapitel.subsection_title, - chapter=ebd_kapitel.chapter_title, # type:ignore[arg-type] - # pylint:disable=line-too-long - section=f"{ebd_kapitel.chapter}.{ebd_kapitel.section}.{ebd_kapitel.subsection}: {ebd_kapitel.section_title}", - ) - ebd_table = converter.convert_docx_tables_to_ebd_table() + if isinstance(docx_tables, EbdNoTableSection): + ebd_meta_data = EbdTableMetaData( + ebd_code=ebd_key, + ebd_name=ebd_kapitel.subsection_title, + chapter=ebd_kapitel.chapter_title, # type:ignore[arg-type] + # pylint:disable=line-too-long + section=f"{ebd_kapitel.chapter}.{ebd_kapitel.section}.{ebd_kapitel.subsection}: {ebd_kapitel.section_title}", + role="N/A", + remark=docx_tables.remark, + ) + ebd_table = EbdTable(metadata=ebd_meta_data, rows=[]) + + else: + converter = DocxTableConverter( + docx_tables, + ebd_key=ebd_key, + ebd_name=ebd_kapitel.subsection_title, + chapter=ebd_kapitel.chapter_title, # type:ignore[arg-type] + # pylint:disable=line-too-long + section=f"{ebd_kapitel.chapter}.{ebd_kapitel.section}.{ebd_kapitel.subsection}: {ebd_kapitel.section_title}", + ) + ebd_table = converter.convert_docx_tables_to_ebd_table() except Exception as scraping_error: # pylint:disable=broad-except click.secho(f"Error while scraping {ebd_key}: {str(scraping_error)}; Skip!", fg="red") continue @@ -222,21 +185,24 @@ def handle_known_error(error: Exception, ebd_key: str) -> None: click.secho(f"Error while graphing {ebd_key}: {str(unknown_error)}; Skip!", fg="red") continue if "puml" in export_types: - try: - puml_path = output_path / Path(f"{ebd_key}.puml") - _dump_puml(puml_path, ebd_graph) - click.secho(f"💾 Successfully exported '{ebd_key}.puml' to {puml_path.absolute()}") - except AssertionError as assertion_error: - # https://github.com/Hochfrequenz/rebdhuhn/issues/35 - click.secho(str(assertion_error), fg="red") - 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") + if not any(ebd_table.rows): + click.secho(f"EBD {ebd_key} has no ebd table; Skip puml creation!", fg="yellow") + else: + try: + puml_path = output_path / Path(f"{ebd_key}.puml") + _dump_puml(puml_path, ebd_graph) + click.secho(f"💾 Successfully exported '{ebd_key}.puml' to {puml_path.absolute()}") + except AssertionError as assertion_error: + # https://github.com/Hochfrequenz/rebdhuhn/issues/35 + click.secho(str(assertion_error), fg="red") + 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") try: if "dot" in export_types: