Skip to content

Commit 9decb06

Browse files
authored
Merge pull request #323 from FAIRmat-NFDI/appdef-graph
Refactor internal representation of nxdl's to tree structure
2 parents 0330245 + 87f1375 commit 9decb06

File tree

18 files changed

+1713
-444
lines changed

18 files changed

+1713
-444
lines changed

pynxtools/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
import os
2020
import re
2121
from datetime import datetime
22-
from glob import glob
23-
from typing import Union
2422

2523
from pynxtools._build_wrapper import get_vcs_version
2624
from pynxtools.definitions.dev_tools.globals.nxdl import get_nxdl_version
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from pynxtools.dataconverter import helpers, validation
2+
3+
helpers.validate_data_dict = validation.validate_data_dict # type: ignore

pynxtools/dataconverter/convert.py

Lines changed: 35 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@
2424
import logging
2525
import os
2626
import sys
27-
import xml.etree.ElementTree as ET
2827
from gettext import gettext
2928
from pathlib import Path
30-
from typing import List, Optional, Tuple
29+
from typing import List, Literal, Optional, Tuple
3130

3231
import click
32+
import lxml.etree as ET
3333
import yaml
3434
from click_default_group import DefaultGroup
3535

3636
from pynxtools.dataconverter import helpers
37+
from pynxtools.dataconverter.nexus_tree import generate_tree_from
3738
from pynxtools.dataconverter.readers.base.reader import BaseReader
3839
from pynxtools.dataconverter.template import Template
40+
from pynxtools.dataconverter.validation import validate_dict_against
3941
from pynxtools.dataconverter.writer import Writer
4042
from pynxtools.nexus import nexus
4143

@@ -99,61 +101,11 @@ def get_names_of_all_readers() -> List[str]:
99101
return sorted(all_readers + plugins)
100102

101103

102-
def get_nxdl_root_and_path(nxdl: str):
103-
"""Get xml root element and file path from nxdl name e.g. NXapm.
104-
105-
Parameters
106-
----------
107-
nxdl: str
108-
Name of nxdl file e.g. NXapm from NXapm.nxdl.xml.
109-
110-
Returns
111-
-------
112-
ET.root
113-
Root element of nxdl file.
114-
str
115-
Path of nxdl file.
116-
117-
Raises
118-
------
119-
FileNotFoundError
120-
Error if no file with the given nxdl name is found.
121-
"""
122-
# Reading in the NXDL and generating a template
123-
definitions_path = nexus.get_nexus_definitions_path()
124-
if nxdl == "NXtest":
125-
nxdl_f_path = os.path.join(
126-
f"{os.path.abspath(os.path.dirname(__file__))}/../../",
127-
"tests",
128-
"data",
129-
"dataconverter",
130-
"NXtest.nxdl.xml",
131-
)
132-
elif nxdl == "NXroot":
133-
nxdl_f_path = os.path.join(definitions_path, "base_classes", "NXroot.nxdl.xml")
134-
else:
135-
nxdl_f_path = os.path.join(
136-
definitions_path, "contributed_definitions", f"{nxdl}.nxdl.xml"
137-
)
138-
if not os.path.exists(nxdl_f_path):
139-
nxdl_f_path = os.path.join(
140-
definitions_path, "applications", f"{nxdl}.nxdl.xml"
141-
)
142-
if not os.path.exists(nxdl_f_path):
143-
nxdl_f_path = os.path.join(
144-
definitions_path, "base_classes", f"{nxdl}.nxdl.xml"
145-
)
146-
if not os.path.exists(nxdl_f_path):
147-
raise FileNotFoundError(f"The nxdl file, {nxdl}, was not found.")
148-
149-
return ET.parse(nxdl_f_path).getroot(), nxdl_f_path
150-
151-
152104
def transfer_data_into_template(
153105
input_file,
154106
reader,
155107
nxdl_name,
156-
nxdl_root: Optional[ET.Element] = None,
108+
nxdl_root: Optional[ET._Element] = None,
157109
skip_verify: bool = False,
158110
**kwargs,
159111
):
@@ -182,7 +134,7 @@ def transfer_data_into_template(
182134
183135
"""
184136
if nxdl_root is None:
185-
nxdl_root, _ = get_nxdl_root_and_path(nxdl=nxdl_name)
137+
nxdl_root, _ = helpers.get_nxdl_root_and_path(nxdl=nxdl_name)
186138

187139
template = Template()
188140
helpers.generate_template_from_nxdl(nxdl_root, template)
@@ -204,14 +156,24 @@ def transfer_data_into_template(
204156
"The chosen NXDL isn't supported by the selected reader."
205157
)
206158

159+
if "ignore_undocumented" in kwargs:
160+
ignore_undocumented = kwargs["ignore_undocumented"]
161+
del kwargs["ignore_undocumented"]
162+
else:
163+
ignore_undocumented = False
164+
207165
data = data_reader().read( # type: ignore[operator]
208166
template=Template(template), file_paths=input_file, **kwargs
209167
)
210168
entry_names = data.get_all_entry_names()
211169
for entry_name in entry_names:
212170
helpers.write_nexus_def_to_entry(data, entry_name, nxdl_name)
213171
if not skip_verify:
214-
helpers.validate_data_dict(template, data, nxdl_root)
172+
validate_dict_against(
173+
nxdl_name,
174+
data,
175+
ignore_undocumented=ignore_undocumented,
176+
)
215177
return data
216178

217179

@@ -254,7 +216,7 @@ def convert(
254216
None.
255217
"""
256218

257-
nxdl_root, nxdl_f_path = get_nxdl_root_and_path(nxdl)
219+
nxdl_root, nxdl_f_path = helpers.get_nxdl_root_and_path(nxdl)
258220

259221
data = transfer_data_into_template(
260222
input_file=input_file,
@@ -366,6 +328,12 @@ def main_cli():
366328
default=False,
367329
help="Shows a log output for all undocumented fields",
368330
)
331+
@click.option(
332+
"--ignore-undocumented",
333+
is_flag=True,
334+
default=False,
335+
help="Ignore all undocumented fields during validation.",
336+
)
369337
@click.option(
370338
"--skip-verify",
371339
is_flag=True,
@@ -386,6 +354,7 @@ def convert_cli(
386354
output: str,
387355
fair: bool,
388356
params_file: str,
357+
ignore_undocumented: bool,
389358
undocumented: bool,
390359
skip_verify: bool,
391360
mapping: str,
@@ -435,6 +404,7 @@ def convert_cli(
435404
fair,
436405
undocumented,
437406
skip_verify,
407+
ignore_undocumented=ignore_undocumented,
438408
)
439409
except FileNotFoundError as exc:
440410
raise click.BadParameter(
@@ -472,21 +442,24 @@ def write_to_file(text):
472442
f.write(text)
473443
f.close()
474444

475-
print_or_write = lambda txt: write_to_file(txt) if output else print(txt)
445+
tree = generate_tree_from(nxdl)
476446

477-
nxdl_root, nxdl_f_path = get_nxdl_root_and_path(nxdl)
478-
template = Template()
479-
helpers.generate_template_from_nxdl(nxdl_root, template)
447+
print_or_write = lambda txt: write_to_file(txt) if output else print(txt)
480448

449+
level: Literal["required", "recommended", "optional"] = "optional"
481450
if required:
482-
template = Template(template.get_optionality("required"))
451+
level = "required"
452+
reqs = tree.required_fields_and_attrs_names(level=level)
453+
template = {
454+
helpers.convert_nxdl_path_dict_to_data_converter_dict(req): None for req in reqs
455+
}
483456

484457
if pythonic:
485458
print_or_write(str(template))
486459
return
487460
print_or_write(
488461
json.dumps(
489-
template.get_accumulated_dict(),
462+
template,
490463
indent=4,
491464
sort_keys=True,
492465
ensure_ascii=False,

0 commit comments

Comments
 (0)