Skip to content

Commit bdd57e5

Browse files
feat: pybabel extractor for YAML files
1 parent a0f235d commit bdd57e5

File tree

4 files changed

+154
-29
lines changed

4 files changed

+154
-29
lines changed

ohsome_quality_api/utils/helper.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,6 @@ def write_geojson(outfile: str, geojson_object: Feature | FeatureCollection) ->
118118
logging.info("Output file written:\t" + str(outfile))
119119

120120

121-
def flatten_sequence(input_seq: dict | list | tuple | set) -> list:
122-
"""Returns the given input sequence as a list.
123-
124-
If the input is a dict, it returns all values.
125-
"""
126-
output = []
127-
if isinstance(input_seq, dict):
128-
input_seq = input_seq.values()
129-
for val in input_seq:
130-
if isinstance(val, dict | list | tuple | set):
131-
output += flatten_sequence(val)
132-
else:
133-
output.append(val)
134-
return output
135-
136-
137121
def get_project_root() -> Path:
138122
"""Get root of the Python project."""
139123
return Path(__file__).resolve().parent.parent.parent.resolve()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from typing import Iterator
2+
3+
import yaml
4+
5+
6+
def flatten_sequence(input_seq: dict | list | tuple | set) -> list:
7+
"""Returns the given input sequence as a list.
8+
9+
If the input is a dict, it returns all values.
10+
"""
11+
output = []
12+
if isinstance(input_seq, dict):
13+
input_seq = input_seq.values()
14+
for val in input_seq:
15+
if isinstance(val, dict | list | tuple | set):
16+
output += flatten_sequence(val)
17+
else:
18+
output.append(val)
19+
return output
20+
21+
22+
def filter_dictonary_by_keys(dictonary: dict, whitelist: list | tuple) -> dict:
23+
if not isinstance(dictonary, dict):
24+
return dictonary
25+
result = {}
26+
for key, value in dictonary.items():
27+
if key in whitelist:
28+
if isinstance(value, dict):
29+
result[key] = filter_dictonary_by_keys(value, whitelist)
30+
else:
31+
result[key] = value
32+
elif isinstance(value, dict):
33+
filtered_value = filter_dictonary_by_keys(value, whitelist)
34+
if filtered_value:
35+
result[key] = filtered_value
36+
return result
37+
38+
39+
def pybabel_yaml_extractor(
40+
fileobj,
41+
keywords,
42+
comment_tags,
43+
options: dict,
44+
) -> Iterator[str]:
45+
"""Method for extracting localizable text from YAML files.
46+
47+
Usage:
48+
pybabel_yaml_extractor(fileobj, options={"keys": "name,description"})
49+
50+
Complies with the following interface:
51+
https://babel.readthedocs.io/en/latest/messages.html#writing-extraction-methods
52+
"""
53+
if "keys" in options.keys():
54+
keys = options["keys"].split(",")
55+
else:
56+
raise ValueError("Options should contain non-empty `keys` item.")
57+
content = yaml.safe_load(fileobj)
58+
filtered = filter_dictonary_by_keys(content, keys)
59+
flattened = flatten_sequence(filtered)
60+
for string in flattened:
61+
yield string

tests/unittests/test_helper.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
)
1414
from ohsome_quality_api.utils.helper import (
1515
camel_to_hyphen,
16-
flatten_sequence,
1716
get_class_from_key,
1817
get_project_root,
1918
hyphen_to_camel,
@@ -46,18 +45,6 @@ def test_name_to_class(self):
4645
get_class_from_key(class_type="indicator", key=indicator_name)
4746
)
4847

49-
# TODO: add tests for other input than dict
50-
def test_flatten_seq(self):
51-
input_seq = {
52-
"regions": {"default": "ogc_fid"},
53-
"gadm": {
54-
"default": "uid", # ISO 3166-1 alpha-3 country code
55-
"other": (("name_1", "name_2"), ("id_1", "id_2")),
56-
},
57-
}
58-
output_seq = ["ogc_fid", "uid", "name_1", "name_2", "id_1", "id_2"]
59-
self.assertListEqual(flatten_sequence(input_seq), output_seq)
60-
6148
def test_json_serialize_valid_input_datetime(self):
6249
self.assertIsInstance(json_serialize(datetime.datetime.now()), str)
6350

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import pytest
2+
import yaml
3+
4+
from ohsome_quality_api.utils.pybabel_yaml_extractor import (
5+
filter_dictonary_by_keys,
6+
flatten_sequence,
7+
pybabel_yaml_extractor,
8+
)
9+
10+
11+
def test_flatten_seq():
12+
input_seq = {
13+
"regions": {"default": "ogc_fid"},
14+
"gadm": {
15+
"default": "uid", # ISO 3166-1 alpha-3 country code
16+
"other": (("name_1", "name_2"), ("id_1", "id_2")),
17+
},
18+
}
19+
output_seq = ["ogc_fid", "uid", "name_1", "name_2", "id_1", "id_2"]
20+
assert flatten_sequence(input_seq) == output_seq
21+
22+
23+
def test_filter_dictonary_by_keys():
24+
input = {
25+
"regions": {"default": "ogc_fid"},
26+
"gadm": {
27+
"default": "uid", # ISO 3166-1 alpha-3 country code
28+
"other": (("name_1", "name_2"), ("id_1", "id_2")),
29+
},
30+
}
31+
output = filter_dictonary_by_keys(input, ["other"])
32+
assert output == {"gadm": {"other": (("name_1", "name_2"), ("id_1", "id_2"))}}
33+
34+
35+
def test_no_keys(tmp_path):
36+
path = tmp_path / "foo.yaml"
37+
with open(path, "w") as file:
38+
file.write(
39+
yaml.dump(
40+
{
41+
"name": "Silenthand Olleander",
42+
"race": "Human",
43+
"traits": ["ONE_HAND", "ONE_EYE"],
44+
}
45+
)
46+
)
47+
options = {}
48+
with open(path, "r") as file:
49+
with pytest.raises(ValueError):
50+
list(pybabel_yaml_extractor(file, None, None, options))
51+
52+
53+
def test_flat(tmp_path):
54+
path = tmp_path / "foo.yaml"
55+
with open(path, "w") as file:
56+
file.write(
57+
yaml.dump(
58+
{
59+
"name": "Silenthand Olleander",
60+
"race": "Human",
61+
"traits": ["ONE_HAND", "ONE_EYE"],
62+
}
63+
)
64+
)
65+
options = {"keys": "name,traits"}
66+
with open(path, "r") as file:
67+
result = list(pybabel_yaml_extractor(file, None, None, options))
68+
assert result == ["Silenthand Olleander", "ONE_HAND", "ONE_EYE"]
69+
70+
71+
def test_nested(tmp_path):
72+
path = tmp_path / "foo.yaml"
73+
with open(path, "w") as file:
74+
file.write(
75+
yaml.dump(
76+
{
77+
"hero": {
78+
"hp": 34,
79+
"sp": 8,
80+
"level": 4,
81+
},
82+
"orc": {
83+
"hp": 12,
84+
"sp": 0,
85+
"level": 2,
86+
},
87+
}
88+
)
89+
)
90+
options = {"keys": "hp"}
91+
with open(path, "r") as file:
92+
result = list(pybabel_yaml_extractor(file, None, None, options))
93+
assert result == [34, 12]

0 commit comments

Comments
 (0)