Skip to content

Commit 24359ec

Browse files
committed
Added support for conditions in repeatable subsections
1 parent 0bf4ef9 commit 24359ec

4 files changed

Lines changed: 55 additions & 19 deletions

File tree

src/nomad_json_parser/parsers/parser.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# limitations under the License.
1717
#
1818

19+
import ast
1920
from typing import (
2021
TYPE_CHECKING,
2122
)
@@ -50,6 +51,7 @@
5051
MainMapper,
5152
MappedJson,
5253
MapperRule,
54+
RepeatKey,
5355
RepeatPath,
5456
RuleCondition,
5557
SubSectionMapper,
@@ -141,6 +143,13 @@ def create_submapping(subsection, key, logger, archive): # noqa: PLR0912, PLR09
141143
repeat.name = path
142144
repeat_paths.append(repeat)
143145
sectionclass.repeat_paths = repeat_paths
146+
if 'repeat_keys' in subsection:
147+
keys_list = []
148+
for s in subsection['repeat_keys']:
149+
repkey = RepeatKey()
150+
repkey.name = str(s)
151+
keys_list.append(repkey)
152+
sectionclass.repeat_keys = keys_list
144153
if 'repeat_paths' in subsection and 'repeats' not in subsection:
145154
logger.warning('repeat_paths found but not repeats, ignoring repeat_paths.')
146155
if 'subsections' in subsection:
@@ -296,7 +305,7 @@ def transform_subclass( # noqa: PLR0913
296305
return subclass
297306

298307

299-
def checkforvalidkey(path, backjson, submap):
308+
def checkforvalidkey(path, backjson, submap): # noqa: PLR0911, PLR0912
300309
backkey = path['name'].split('*')[1].strip('.')
301310
if backkey:
302311
for j in range(len(backkey.split('.'))):
@@ -306,13 +315,30 @@ def checkforvalidkey(path, backjson, submap):
306315
return False
307316
if not isinstance(backjson, dict):
308317
return False
309-
for rule in submap['rules']:
310-
rulejson = dict(backjson)
311-
for rulekey in rule['source'].split('.'):
312-
try:
313-
rulejson = rulejson[rulekey]
314-
except (KeyError, TypeError):
315-
return False
318+
if 'repeat_keys' in submap:
319+
for key in submap['repeat_keys']:
320+
rulejson = dict(backjson)
321+
if key['name'].startswith('{'):
322+
matching = ast.literal_eval(key['name'])
323+
for k in matching.keys():
324+
try:
325+
if not rulejson[k] == matching[k]:
326+
return False
327+
except (KeyError, TypeError):
328+
return False
329+
else:
330+
try:
331+
rulejson = rulejson[key['name']]
332+
except (KeyError, TypeError):
333+
return False
334+
else:
335+
for rule in submap['rules']:
336+
rulejson = dict(backjson)
337+
for rulekey in rule['source'].split('.'):
338+
try:
339+
rulejson = rulejson[rulekey]
340+
except (KeyError, TypeError):
341+
return False
316342
return True
317343

318344

src/nomad_json_parser/schema_packages/jsonimport.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ def normalize(self, archive, logger: BoundLogger) -> None:
110110
super().normalize(archive, logger)
111111

112112

113+
class RepeatKey(ArchiveSection):
114+
name = Quantity(type=str)
115+
116+
def normalize(self, archive, logger: BoundLogger) -> None:
117+
super().normalize(archive, logger)
118+
119+
113120
class SubSectionMapper(MainMapper):
114121
main_key = Quantity(
115122
type=str, description='Key of the main class, where the SubSection is linked.'
@@ -123,6 +130,7 @@ class SubSectionMapper(MainMapper):
123130
description='Marks a repeatable Subsection, attaches to existing list.',
124131
)
125132
repeat_paths = SubSection(section_def=RepeatPath, repeats=True)
133+
repeat_keys = SubSection(section_def=RepeatKey, repeats=True)
126134
subsections = SubSection(section_def='SubSectionMapper', repeats=True)
127135

128136
def normalize(self, archive, logger: BoundLogger) -> None:

tests/data/basesection_example_mapper.json

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"main_key": "steps",
1919
"repeats": "True",
2020
"repeat_paths": ["*.Steps","Step_3"],
21+
"repeat_keys": ["step_description", {"time_unit": "seconds", "How_long_did_it_take": 300.0}],
2122
"rules": {
2223
"step_name": "name",
2324
"step_description": "comment",
@@ -32,16 +33,17 @@
3233
"repeat_paths": ["Chem.*"],
3334
"rules": {
3435
"name": "name"
36+
},
37+
"subsections": {
38+
"sample_reference_mapping": {
39+
"schema": "nomad.datamodel.metainfo.basesections.v1.CompositeSystem",
40+
"main_key": "reference",
41+
"is_archive": "True",
42+
"rules": {
43+
"labid": "lab_id",
44+
"substance_formula": "name"
45+
}
46+
}
3547
}
36-
},
37-
"sample_reference_mapping": {
38-
"schema": "nomad.datamodel.metainfo.basesections.v1.CompositeSystem",
39-
"main_key": "samples.reference",
40-
"is_archive": "True",
41-
"rules": {
42-
"labid": "lab_id",
43-
"substance_formula": "name"
44-
}
45-
4648
}
4749
}

tests/test_json.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_normalize_mapper(parsed_mapper_archive, caplog):
4545
normalize_all(parsed_mapper_archive)
4646

4747
assert parsed_mapper_archive.data.mapper_key == 'basesectionexamplemapper'
48-
assert len(parsed_mapper_archive.data.subsection_mappings) == 3 # Noqa: PLR2004
48+
assert len(parsed_mapper_archive.data.subsection_mappings) == 2 # Noqa: PLR2004
4949
assert parsed_mapper_archive.data.main_mapping.name == 'main_schema'
5050

5151

0 commit comments

Comments
 (0)