Skip to content

Commit 68bfa63

Browse files
author
Konstantin
committed
feat: introduce function to parse Kommunikation_von (w/o using it yet)
based on #176 (no depedency - just to avoid merge conflicts)
1 parent 0797061 commit 68bfa63

File tree

3 files changed

+149
-2
lines changed

3 files changed

+149
-2
lines changed

src/fundamend/models/anwendungshandbuch.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ class SegmentGroup(FundamendBaseModel):
121121
elements: tuple["Segment | SegmentGroup", ...]
122122

123123

124+
class Kommunikationsrichtung(FundamendBaseModel):
125+
"""
126+
a strongly typed representation of the 'Kommunikation_von' attribute of anwendungsfall
127+
"""
128+
129+
sender: str #: e.g. "NB"
130+
empfaenger: str #: e.g. "MSB"
131+
132+
124133
class Anwendungsfall(FundamendBaseModel):
125134
"""
126135
One 'Anwendungsfall', indicated by `<AWF>` tag, corresponds to one Prüfidentifikator or type of Message

src/fundamend/utils.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
Contains some utility functions that are used in the project.
33
"""
44

5+
from typing import Optional
6+
7+
from fundamend.models.anwendungshandbuch import Kommunikationsrichtung
8+
59

610
def lstrip(prefix: str, text: str) -> str:
711
"""Strip the given prefix from the given text. If the text does not start with the prefix, return the text as is.
@@ -73,4 +77,53 @@ def remove_linebreaks_and_hyphens(original: str) -> str:
7377
return " ".join(result.strip().split())
7478

7579

76-
__all__ = ["lstrip", "rstrip", "strip", "remove_linebreaks_and_hyphens"]
80+
_UNIFIED_SEPARATOR = "/" # how multiple Marktrollen shall be split in the kommunikation_von attribute
81+
82+
83+
def _parse_kommunikation_von_line(kommunikation_von_line: str) -> list[Kommunikationsrichtung]:
84+
"""
85+
parses a single line of kommunikation_von into a list of Kommunikationsrichtung objects
86+
this is necessary because some AHBs have multiple lines in the kommunikation_von attribute which must not be mixed
87+
"""
88+
if not kommunikation_von_line or not kommunikation_von_line.strip():
89+
return []
90+
result: list[Kommunikationsrichtung] = []
91+
parts = kommunikation_von_line.split(" an ")
92+
if len(parts) != 2:
93+
raise ValueError(f"Invalid kommunikation_von string: {kommunikation_von_line}. Expected format: 'X an Y[/Z]'")
94+
sender_str = parts[0]
95+
receiver_str = parts[1]
96+
alternative_separators = [","]
97+
for alternative_separator in alternative_separators:
98+
if alternative_separator in receiver_str:
99+
receiver_str = receiver_str.replace(alternative_separator, _UNIFIED_SEPARATOR)
100+
if alternative_separator in sender_str:
101+
sender_str = sender_str.replace(alternative_separator, _UNIFIED_SEPARATOR)
102+
senders = [x.strip() for x in sender_str.split(_UNIFIED_SEPARATOR)]
103+
receivers = [x.strip() for x in receiver_str.split(_UNIFIED_SEPARATOR)]
104+
for sender in senders:
105+
for receiver in receivers:
106+
result.append(Kommunikationsrichtung(sender=sender, empfaenger=receiver))
107+
return result
108+
109+
110+
def parse_kommunikation_von(kommunikation_von: Optional[str]) -> list[Kommunikationsrichtung]:
111+
"""Splits the kommunikation_von string into something strongly typed
112+
113+
Args:
114+
kommunikation_von: The kommunikation_von string to split, e.g. 'NB an LF/MSB'.
115+
116+
Returns:
117+
Properly typed list of Kommunikationsrichtung objects:
118+
[Kommunikationsrichtung(sender='NB', empfaenger='LF'),
119+
Kommunikationsrichtung(sender='NB', empfaenger='MSB')]
120+
"""
121+
result: list[Kommunikationsrichtung] = []
122+
for line in (kommunikation_von or "").splitlines():
123+
line = line.strip()
124+
if line:
125+
result += _parse_kommunikation_von_line(line)
126+
return result
127+
128+
129+
__all__ = ["lstrip", "rstrip", "strip", "remove_linebreaks_and_hyphens", "parse_kommunikation_von"]

unittests/test_utils.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

3-
from fundamend.utils import remove_linebreaks_and_hyphens
3+
from fundamend.models.anwendungshandbuch import Kommunikationsrichtung
4+
from fundamend.utils import parse_kommunikation_von, remove_linebreaks_and_hyphens
45

56

67
@pytest.mark.parametrize(
@@ -20,3 +21,87 @@
2021
def test_anwendungsfall_beschreibung_normalization(original: str, expected: str) -> None:
2122
actual = remove_linebreaks_and_hyphens(original)
2223
assert actual == expected
24+
25+
26+
@pytest.mark.parametrize(
27+
"original, expected",
28+
[
29+
pytest.param("", [], id="empty string = no directions"),
30+
pytest.param("LF an NB", [Kommunikationsrichtung(sender="LF", empfaenger="NB")], id="simple example"),
31+
pytest.param(
32+
"MSB an NB, LF",
33+
[
34+
Kommunikationsrichtung(sender="MSB", empfaenger="NB"),
35+
Kommunikationsrichtung(sender="MSB", empfaenger="LF"),
36+
],
37+
id="two receivers, comma separated",
38+
),
39+
pytest.param(
40+
"MSB an NB / LF",
41+
[
42+
Kommunikationsrichtung(sender="MSB", empfaenger="NB"),
43+
Kommunikationsrichtung(sender="MSB", empfaenger="LF"),
44+
],
45+
id="two receivers, slash separated",
46+
),
47+
pytest.param(
48+
"NB, LF an MSB",
49+
[
50+
Kommunikationsrichtung(sender="NB", empfaenger="MSB"),
51+
Kommunikationsrichtung(sender="LF", empfaenger="MSB"),
52+
],
53+
id="two senders, comma separated",
54+
),
55+
pytest.param(
56+
"NB / LF an MSB",
57+
[
58+
Kommunikationsrichtung(sender="NB", empfaenger="MSB"),
59+
Kommunikationsrichtung(sender="LF", empfaenger="MSB"),
60+
],
61+
id="two senders, slash separated",
62+
),
63+
pytest.param(
64+
"BIKO an NB / ÜNB",
65+
[
66+
Kommunikationsrichtung(sender="BIKO", empfaenger="NB"),
67+
Kommunikationsrichtung(sender="BIKO", empfaenger="ÜNB"),
68+
],
69+
id="two receivers, slash separated but with Umlaut",
70+
),
71+
pytest.param(
72+
"NB an LF\nMSB an LF, NB, ESA",
73+
[
74+
Kommunikationsrichtung(sender="NB", empfaenger="LF"),
75+
Kommunikationsrichtung(sender="MSB", empfaenger="LF"),
76+
Kommunikationsrichtung(sender="MSB", empfaenger="NB"),
77+
Kommunikationsrichtung(sender="MSB", empfaenger="ESA"),
78+
],
79+
id="two lines",
80+
),
81+
pytest.param(
82+
"NB an LF / MSB\r\nLF an NB, MSB",
83+
[
84+
Kommunikationsrichtung(sender="NB", empfaenger="LF"),
85+
Kommunikationsrichtung(sender="NB", empfaenger="MSB"),
86+
Kommunikationsrichtung(sender="LF", empfaenger="NB"),
87+
Kommunikationsrichtung(sender="LF", empfaenger="MSB"),
88+
],
89+
id="two lines with mixed separators",
90+
# shit is real, I'm not making this up
91+
),
92+
pytest.param(
93+
"MSB an NB/LF/ÜNB/MSB/ESA",
94+
[
95+
Kommunikationsrichtung(sender="MSB", empfaenger="NB"),
96+
Kommunikationsrichtung(sender="MSB", empfaenger="LF"),
97+
Kommunikationsrichtung(sender="MSB", empfaenger="ÜNB"),
98+
Kommunikationsrichtung(sender="MSB", empfaenger="MSB"),
99+
Kommunikationsrichtung(sender="MSB", empfaenger="ESA"),
100+
],
101+
id="many receivers",
102+
),
103+
],
104+
)
105+
def test_parsing_kommunikation_von(original: str, expected: list[Kommunikationsrichtung]) -> None:
106+
actual = parse_kommunikation_von(original)
107+
assert actual == expected

0 commit comments

Comments
 (0)