generated from Hochfrequenz/python_template_repository
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This basically ports code that has been introduced in AHBicht to the MAUS: Hochfrequenz/ahbicht#158 * ✨ Implement MAUS Provider * ✔Add unit tests
- Loading branch information
Showing
2 changed files
with
130 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
""" | ||
MAUS s (plural of MAUS) are data structures which are structurally equivalent to the maus.DeepAnwendungshandbuch. | ||
For more information see the MAUS repo and its documentation: https://github.com/Hochfrequenz/mig_ahb_utility_stack/ | ||
A MAUS Provider is a class that returns MAUS s' from what ever data source the implementation prefers. | ||
The MAUS provider is supposed to be used with dependency injection. | ||
""" | ||
|
||
import json | ||
from abc import ABC, abstractmethod | ||
from pathlib import Path | ||
from typing import Optional | ||
|
||
from maus import DeepAnwendungshandbuch | ||
from maus.edifact import EdifactFormat, EdifactFormatVersion | ||
from maus.models.anwendungshandbuch import DeepAnwendungshandbuchSchema | ||
|
||
# pylint:disable=too-few-public-methods | ||
|
||
|
||
class MausProvider(ABC): | ||
""" | ||
A MausProvider is a class that provides MAUS' (Deep Anwendungshandbuch) to calling code. | ||
""" | ||
|
||
@abstractmethod | ||
def get_maus( | ||
self, edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str | ||
) -> Optional[DeepAnwendungshandbuch]: | ||
""" | ||
Return a MAUS for the given parameters. returns None if the requested MAUS is not available. | ||
""" | ||
raise NotImplementedError("Has to be implemented in inheriting class") | ||
|
||
|
||
class FileBasedMausProvider(MausProvider): | ||
""" | ||
A MAUS provider that uses the file system to retrieve MAUS s. | ||
""" | ||
|
||
def __init__(self, base_path: Path, encoding: str = "utf-8"): | ||
""" | ||
initialize by providing a base path relative to which the MAUS s can be found. | ||
""" | ||
self.base_path: Path = base_path | ||
self._encoding = encoding | ||
|
||
@abstractmethod | ||
def to_path( | ||
self, edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str | ||
) -> Path: | ||
""" | ||
returns the path of the maus file relative to the given parameters. | ||
""" | ||
raise NotImplementedError("Has to be implemented in inheriting class") | ||
|
||
def get_maus( | ||
self, edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str | ||
) -> Optional[DeepAnwendungshandbuch]: | ||
relative_path = self.to_path(edifact_format, edifact_format_version, pruefidentifikator) | ||
full_path: Path = self.base_path / relative_path | ||
try: | ||
with open(full_path, "r", encoding=self._encoding) as maus_infile: | ||
file_content_json = json.load(maus_infile) | ||
maus = DeepAnwendungshandbuchSchema().load(file_content_json) | ||
except FileNotFoundError: | ||
return None | ||
return maus |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
""" | ||
Test the maus provider as a concept and the file based maus provider as an implementation. | ||
""" | ||
import json | ||
from pathlib import Path | ||
|
||
import pytest # type:ignore[import] | ||
|
||
from maus import DeepAnwendungshandbuch | ||
from maus.edifact import EdifactFormat, EdifactFormatVersion | ||
from maus.maus_provider import FileBasedMausProvider, MausProvider | ||
from maus.models.anwendungshandbuch import AhbMetaInformation, DeepAnwendungshandbuchSchema | ||
|
||
pytestmark = pytest.mark.asyncio | ||
|
||
|
||
class MyFooBarMausProvider(FileBasedMausProvider): | ||
""" | ||
A maus provider, just for this test. | ||
""" | ||
|
||
def to_path( | ||
self, edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str | ||
) -> Path: | ||
return Path(f"{edifact_format_version}/{edifact_format}/{pruefidentifikator}_maus.json") | ||
|
||
|
||
class TestMausProvider: | ||
""" | ||
Test the file based maus provider | ||
""" | ||
|
||
def test_file_based_maus_provider_not_found(self, tmpdir_factory): | ||
maus_root_dir = tmpdir_factory.mktemp("test_dir") | ||
# we just create an empty temporary directory, just for the sake of having a directory | ||
provider: MausProvider = MyFooBarMausProvider(base_path=maus_root_dir) | ||
assert provider is not None | ||
actual = provider.get_maus( | ||
edifact_format=EdifactFormat.UTILMD, | ||
edifact_format_version=EdifactFormatVersion.FV2104, | ||
pruefidentifikator="11001", | ||
) | ||
assert actual is None # because nothing was found | ||
|
||
def test_file_based_maus_provider_success(self, tmpdir_factory): | ||
maus_root_dir = tmpdir_factory.mktemp("test_dir") | ||
# no we create something more: a directory structure compatible with the above MyFooBarMausProvider | ||
maus_root_dir.mkdir("FV2104") | ||
maus_root_dir.mkdir("FV2104/UTILMD") | ||
# a minimal maus that is serializable and deserializable | ||
example_maus = DeepAnwendungshandbuch(meta=AhbMetaInformation(pruefidentifikator="11001"), lines=[]) | ||
with open(maus_root_dir / "FV2104/UTILMD/11001_maus.json", "w+") as maus_test_outfile: | ||
deep_ahb_dict = DeepAnwendungshandbuchSchema().dump(example_maus) # create a dictionary | ||
json.dump(deep_ahb_dict, maus_test_outfile) # dump the dictionary to the file | ||
provider: MausProvider = MyFooBarMausProvider(base_path=maus_root_dir) | ||
assert provider is not None | ||
actual = provider.get_maus( | ||
edifact_format=EdifactFormat.UTILMD, | ||
edifact_format_version=EdifactFormatVersion.FV2104, | ||
pruefidentifikator="11001", | ||
) | ||
assert actual is not None # because the file was found | ||
assert actual == example_maus # is equivalent to the original because it was read from the file |