fameio 3.1.1__py3-none-any.whl → 3.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fameio/cli/convert_results.py +10 -10
- fameio/cli/make_config.py +9 -9
- fameio/cli/options.py +6 -4
- fameio/cli/parser.py +87 -51
- fameio/cli/reformat.py +58 -0
- fameio/input/__init__.py +4 -4
- fameio/input/loader/__init__.py +13 -13
- fameio/input/loader/controller.py +64 -18
- fameio/input/loader/loader.py +25 -16
- fameio/input/metadata.py +57 -38
- fameio/input/resolver.py +9 -10
- fameio/input/scenario/agent.py +62 -26
- fameio/input/scenario/attribute.py +93 -40
- fameio/input/scenario/contract.py +160 -56
- fameio/input/scenario/exception.py +41 -18
- fameio/input/scenario/fameiofactory.py +57 -6
- fameio/input/scenario/generalproperties.py +22 -12
- fameio/input/scenario/scenario.py +117 -38
- fameio/input/scenario/stringset.py +29 -11
- fameio/input/schema/agenttype.py +27 -10
- fameio/input/schema/attribute.py +108 -45
- fameio/input/schema/java_packages.py +14 -12
- fameio/input/schema/schema.py +39 -15
- fameio/input/validator.py +198 -54
- fameio/input/writer.py +137 -46
- fameio/logs.py +28 -47
- fameio/output/__init__.py +5 -1
- fameio/output/agent_type.py +89 -28
- fameio/output/conversion.py +52 -37
- fameio/output/csv_writer.py +107 -27
- fameio/output/data_transformer.py +17 -24
- fameio/output/execution_dao.py +170 -0
- fameio/output/input_dao.py +71 -33
- fameio/output/output_dao.py +33 -11
- fameio/output/reader.py +64 -21
- fameio/output/yaml_writer.py +16 -8
- fameio/scripts/__init__.py +22 -4
- fameio/scripts/convert_results.py +126 -52
- fameio/scripts/convert_results.py.license +1 -1
- fameio/scripts/exception.py +7 -0
- fameio/scripts/make_config.py +34 -13
- fameio/scripts/make_config.py.license +1 -1
- fameio/scripts/reformat.py +71 -0
- fameio/scripts/reformat.py.license +3 -0
- fameio/series.py +174 -59
- fameio/time.py +79 -25
- fameio/tools.py +48 -8
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/METADATA +50 -34
- fameio-3.3.0.dist-info/RECORD +60 -0
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/WHEEL +1 -1
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/entry_points.txt +1 -0
- CHANGELOG.md +0 -288
- fameio-3.1.1.dist-info/RECORD +0 -56
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/LICENSE.txt +0 -0
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/LICENSES/Apache-2.0.txt +0 -0
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/LICENSES/CC-BY-4.0.txt +0 -0
- {fameio-3.1.1.dist-info → fameio-3.3.0.dist-info}/LICENSES/CC0-1.0.txt +0 -0
fameio/cli/convert_results.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
# SPDX-FileCopyrightText:
|
1
|
+
# SPDX-FileCopyrightText: 2025 German Aerospace Center <fame@dlr.de>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
from __future__ import annotations
|
5
|
+
|
4
6
|
import argparse
|
5
|
-
from typing import Any
|
7
|
+
from typing import Any
|
6
8
|
|
7
9
|
from fameio.cli.options import Options, ResolveOptions, TimeOptions
|
8
10
|
from fameio.cli.parser import (
|
@@ -24,8 +26,8 @@ CLI_DEFAULTS = {
|
|
24
26
|
Options.FILE: None,
|
25
27
|
Options.LOG_LEVEL: "WARN",
|
26
28
|
Options.LOG_FILE: None,
|
27
|
-
Options.AGENT_LIST: None,
|
28
29
|
Options.OUTPUT: None,
|
30
|
+
Options.AGENT_LIST: None,
|
29
31
|
Options.SINGLE_AGENT_EXPORT: False,
|
30
32
|
Options.MEMORY_SAVING: False,
|
31
33
|
Options.RESOLVE_COMPLEX_FIELD: ResolveOptions.SPLIT,
|
@@ -38,9 +40,8 @@ _INFILE_PATH_HELP = "Provide path to protobuf file"
|
|
38
40
|
_OUTFILE_PATH_HELP = "Provide path to folder to store output .csv files"
|
39
41
|
|
40
42
|
|
41
|
-
def handle_args(args: list[str], defaults:
|
42
|
-
"""
|
43
|
-
Handles command line arguments and returns `run_config` for convert_results script
|
43
|
+
def handle_args(args: list[str], defaults: dict[Options, Any] | None = None) -> dict[Options, Any]:
|
44
|
+
"""Handles command line arguments and returns `run_config` for convert_results script.
|
44
45
|
|
45
46
|
Args:
|
46
47
|
args: list of (command line) arguments, e.g., ['-f', 'my_file']; arg values take precedence over defaults
|
@@ -54,9 +55,8 @@ def handle_args(args: list[str], defaults: Optional[dict[Options, Any]] = None)
|
|
54
55
|
return map_namespace_to_options_dict(parsed)
|
55
56
|
|
56
57
|
|
57
|
-
def _prepare_parser(defaults:
|
58
|
-
"""
|
59
|
-
Creates a parser with given defaults to handle `make_config` configuration arguments
|
58
|
+
def _prepare_parser(defaults: dict[Options, Any] | None) -> argparse.ArgumentParser:
|
59
|
+
"""Creates a parser with given defaults to handle `make_config` configuration arguments.
|
60
60
|
|
61
61
|
Returns:
|
62
62
|
new parser using given defaults for its arguments; if a default is not specified, hard-coded defaults are used
|
@@ -80,5 +80,5 @@ def _prepare_parser(defaults: Optional[dict[Options, Any]]) -> argparse.Argument
|
|
80
80
|
|
81
81
|
|
82
82
|
def _get_default(defaults: dict, option: Options) -> Any:
|
83
|
-
"""Returns default for given `option` or its cli default"""
|
83
|
+
"""Returns default for given `option` or its cli default."""
|
84
84
|
return defaults.get(option, CLI_DEFAULTS[option])
|
fameio/cli/make_config.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
# SPDX-FileCopyrightText:
|
1
|
+
# SPDX-FileCopyrightText: 2025 German Aerospace Center <fame@dlr.de>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
from __future__ import annotations
|
5
|
+
|
4
6
|
import argparse
|
5
7
|
from pathlib import Path
|
6
|
-
from typing import Any
|
8
|
+
from typing import Any
|
7
9
|
|
8
10
|
from fameio.cli.options import Options
|
9
11
|
from fameio.cli.parser import (
|
@@ -31,9 +33,8 @@ _ENCODING_HELP = (
|
|
31
33
|
)
|
32
34
|
|
33
35
|
|
34
|
-
def handle_args(args: list[str], defaults:
|
35
|
-
"""
|
36
|
-
Converts given `arguments` and returns a configuration for the make_config script
|
36
|
+
def handle_args(args: list[str], defaults: dict[Options, Any] | None = None) -> dict[Options, Any]:
|
37
|
+
"""Converts given `args` and returns a configuration for the make_config script.
|
37
38
|
|
38
39
|
Args:
|
39
40
|
args: list of (command line) arguments, e.g., ['-f', 'my_file']; arg values take precedence over defaults
|
@@ -47,9 +48,8 @@ def handle_args(args: list[str], defaults: Optional[dict[Options, Any]] = None)
|
|
47
48
|
return map_namespace_to_options_dict(parsed)
|
48
49
|
|
49
50
|
|
50
|
-
def _prepare_parser(defaults:
|
51
|
-
"""
|
52
|
-
Creates a parser with given defaults to handle `make_config` configuration arguments
|
51
|
+
def _prepare_parser(defaults: dict[Options, Any] | None) -> argparse.ArgumentParser:
|
52
|
+
"""Creates a parser with given defaults to handle `make_config` configuration arguments.
|
53
53
|
|
54
54
|
Returns:
|
55
55
|
new parser using given defaults for its arguments; if a default is not specified, hard-coded defaults are used
|
@@ -65,5 +65,5 @@ def _prepare_parser(defaults: Optional[dict[Options, Any]]) -> argparse.Argument
|
|
65
65
|
|
66
66
|
|
67
67
|
def _get_default(defaults: dict, option: Options) -> Any:
|
68
|
-
"""Returns default for given `option` or, if missing, its cli default"""
|
68
|
+
"""Returns default for given `option` or, if missing, its cli default."""
|
69
69
|
return defaults.get(option, CLI_DEFAULTS[option])
|
fameio/cli/options.py
CHANGED
@@ -6,7 +6,7 @@ from enum import Enum, auto
|
|
6
6
|
|
7
7
|
|
8
8
|
class ParsableEnum(Enum):
|
9
|
-
"""Extend this to create an enum that can be parsed with argparse"""
|
9
|
+
"""Extend this to create an enum that can be parsed with argparse."""
|
10
10
|
|
11
11
|
@classmethod
|
12
12
|
def instantiate(cls, name: str) -> Enum:
|
@@ -20,7 +20,7 @@ class ParsableEnum(Enum):
|
|
20
20
|
|
21
21
|
|
22
22
|
class Options(Enum):
|
23
|
-
"""Specifies command line configuration options"""
|
23
|
+
"""Specifies command line configuration options."""
|
24
24
|
|
25
25
|
FILE = auto()
|
26
26
|
LOG_LEVEL = auto()
|
@@ -34,10 +34,12 @@ class Options(Enum):
|
|
34
34
|
TIME_MERGING = auto()
|
35
35
|
INPUT_RECOVERY = auto()
|
36
36
|
INPUT_ENCODING = auto()
|
37
|
+
FILE_PATTERN = auto()
|
38
|
+
REPLACE = auto()
|
37
39
|
|
38
40
|
|
39
41
|
class TimeOptions(ParsableEnum, Enum):
|
40
|
-
"""Specifies options for conversion of time in output"""
|
42
|
+
"""Specifies options for conversion of time in output."""
|
41
43
|
|
42
44
|
INT = auto()
|
43
45
|
UTC = auto()
|
@@ -45,7 +47,7 @@ class TimeOptions(ParsableEnum, Enum):
|
|
45
47
|
|
46
48
|
|
47
49
|
class ResolveOptions(ParsableEnum, Enum):
|
48
|
-
"""Specifies options for resolving complex fields in output files"""
|
50
|
+
"""Specifies options for resolving complex fields in output files."""
|
49
51
|
|
50
52
|
IGNORE = auto()
|
51
53
|
SPLIT = auto()
|
fameio/cli/parser.py
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
# SPDX-FileCopyrightText: 2025 German Aerospace Center <fame@dlr.de>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
from __future__ import annotations
|
5
|
+
|
4
6
|
import copy
|
5
7
|
from argparse import ArgumentParser, ArgumentTypeError, BooleanOptionalAction, Namespace
|
6
|
-
from enum import Enum
|
7
8
|
from pathlib import Path
|
8
|
-
from typing import
|
9
|
+
from typing import Any
|
9
10
|
|
10
11
|
from fameio.cli.options import TimeOptions, ResolveOptions, Options
|
11
12
|
from fameio.logs import LogLevel
|
12
13
|
|
13
14
|
_ERR_INVALID_MERGING_DEFAULT = "Invalid merge-times default: needs list of 3 integers separated by spaces but was: '{}'"
|
14
15
|
|
15
|
-
_OPTION_ARGUMENT_NAME: dict[str,
|
16
|
+
_OPTION_ARGUMENT_NAME: dict[str, Options] = {
|
16
17
|
"file": Options.FILE,
|
17
18
|
"log": Options.LOG_LEVEL,
|
18
19
|
"logfile": Options.LOG_FILE,
|
@@ -25,13 +26,15 @@ _OPTION_ARGUMENT_NAME: dict[str, Union[Options, dict]] = {
|
|
25
26
|
"input_recovery": Options.INPUT_RECOVERY,
|
26
27
|
"complex_column": Options.RESOLVE_COMPLEX_FIELD,
|
27
28
|
"merge_times": Options.TIME_MERGING,
|
29
|
+
"file_pattern": Options.FILE_PATTERN,
|
30
|
+
"replace": Options.REPLACE,
|
28
31
|
}
|
29
32
|
|
30
33
|
|
31
|
-
def add_file_argument(parser: ArgumentParser, default:
|
32
|
-
"""
|
33
|
-
|
34
|
-
If a default is not specified, the argument is required (optional otherwise)
|
34
|
+
def add_file_argument(parser: ArgumentParser, default: Path | None, help_text: str) -> None:
|
35
|
+
"""Adds 'file' argument to the provided `parser` with the provided `help_text`.
|
36
|
+
|
37
|
+
If a default is not specified, the argument is required (optional otherwise).
|
35
38
|
|
36
39
|
Args:
|
37
40
|
parser: to add the argument to
|
@@ -44,26 +47,26 @@ def add_file_argument(parser: ArgumentParser, default: Optional[Path], help_text
|
|
44
47
|
parser.add_argument("-f", "--file", type=Path, required=True, help=help_text)
|
45
48
|
|
46
49
|
|
47
|
-
def add_select_agents_argument(parser: ArgumentParser,
|
48
|
-
"""Adds optional repeatable string argument 'agent' to given `parser
|
49
|
-
help_text = "Provide list of agents to extract (default=
|
50
|
-
parser.add_argument("-a", "--agents", nargs="*", type=str, default=
|
50
|
+
def add_select_agents_argument(parser: ArgumentParser, default_value: list[str] | None) -> None:
|
51
|
+
"""Adds optional repeatable string argument 'agent' to given `parser`."""
|
52
|
+
help_text = f"Provide list of agents to extract (default={default_value})"
|
53
|
+
parser.add_argument("-a", "--agents", nargs="*", type=str, default=default_value, help=help_text)
|
51
54
|
|
52
55
|
|
53
|
-
def add_logfile_argument(parser: ArgumentParser,
|
54
|
-
"""Adds optional argument 'logfile' to given `parser
|
55
|
-
help_text = "provide logging file (default=
|
56
|
-
parser.add_argument("-lf", "--logfile", type=Path, default=
|
56
|
+
def add_logfile_argument(parser: ArgumentParser, default_value: Path | None) -> None:
|
57
|
+
"""Adds optional argument 'logfile' to given `parser`."""
|
58
|
+
help_text = f"provide logging file (default={default_value})"
|
59
|
+
parser.add_argument("-lf", "--logfile", type=Path, default=default_value, help=help_text)
|
57
60
|
|
58
61
|
|
59
62
|
def add_output_argument(parser: ArgumentParser, default_value, help_text: str) -> None:
|
60
|
-
"""Adds optional argument 'output' to given `parser` using the given `help_text` and `default_value
|
63
|
+
"""Adds optional argument 'output' to given `parser` using the given `help_text` and `default_value`."""
|
61
64
|
parser.add_argument("-o", "--output", type=Path, default=default_value, help=help_text)
|
62
65
|
|
63
66
|
|
64
67
|
def add_log_level_argument(parser: ArgumentParser, default_value: str) -> None:
|
65
|
-
"""Adds optional argument 'log' to given `parser
|
66
|
-
help_text = f"choose logging level (default
|
68
|
+
"""Adds optional argument 'log' to given `parser`."""
|
69
|
+
help_text = f"choose logging level (default={default_value})"
|
67
70
|
# noinspection PyTypeChecker
|
68
71
|
parser.add_argument(
|
69
72
|
"-l",
|
@@ -75,14 +78,14 @@ def add_log_level_argument(parser: ArgumentParser, default_value: str) -> None:
|
|
75
78
|
)
|
76
79
|
|
77
80
|
|
78
|
-
def add_encoding_argument(parser: ArgumentParser, default_value:
|
81
|
+
def add_encoding_argument(parser: ArgumentParser, default_value: str | None, help_text: str) -> None:
|
79
82
|
"""Adds optional argument `enc` to given parser"""
|
80
83
|
parser.add_argument("-enc", "--encoding", type=str, default=default_value, help=help_text)
|
81
84
|
|
82
85
|
|
83
86
|
def add_single_export_argument(parser: ArgumentParser, default_value: bool) -> None:
|
84
|
-
"""Adds optional repeatable string argument 'agent' to given `parser
|
85
|
-
help_text = "Enable export of single agents (default=
|
87
|
+
"""Adds optional repeatable string argument 'agent' to given `parser`."""
|
88
|
+
help_text = f"Enable export of single agents (default={default_value})"
|
86
89
|
parser.add_argument(
|
87
90
|
"-se",
|
88
91
|
"--single-export",
|
@@ -93,8 +96,8 @@ def add_single_export_argument(parser: ArgumentParser, default_value: bool) -> N
|
|
93
96
|
|
94
97
|
|
95
98
|
def add_memory_saving_argument(parser: ArgumentParser, default_value: bool) -> None:
|
96
|
-
"""Adds optional bool argument to given `parser` to enable memory saving mode"""
|
97
|
-
help_text = "Reduces memory usage profile at the cost of runtime (default=
|
99
|
+
"""Adds optional bool argument to given `parser` to enable memory saving mode."""
|
100
|
+
help_text = f"Reduces memory usage profile at the cost of runtime (default={default_value})"
|
98
101
|
parser.add_argument(
|
99
102
|
"-m",
|
100
103
|
"--memory-saving",
|
@@ -104,10 +107,10 @@ def add_memory_saving_argument(parser: ArgumentParser, default_value: bool) -> N
|
|
104
107
|
)
|
105
108
|
|
106
109
|
|
107
|
-
def add_resolve_complex_argument(parser: ArgumentParser, default_value:
|
108
|
-
"""Instructs given `parser` how to deal with complex field outputs"""
|
110
|
+
def add_resolve_complex_argument(parser: ArgumentParser, default_value: ResolveOptions | str):
|
111
|
+
"""Instructs given `parser` how to deal with complex field outputs."""
|
109
112
|
default_value = default_value if isinstance(default_value, ResolveOptions) else ResolveOptions[default_value]
|
110
|
-
help_text = f"How to deal with complex index columns? (default={default_value})"
|
113
|
+
help_text = f"How to deal with complex index columns? (default={default_value.name})"
|
111
114
|
parser.add_argument(
|
112
115
|
"-cc",
|
113
116
|
"--complex-column",
|
@@ -118,10 +121,10 @@ def add_resolve_complex_argument(parser: ArgumentParser, default_value: Union[Re
|
|
118
121
|
)
|
119
122
|
|
120
123
|
|
121
|
-
def add_time_argument(parser: ArgumentParser, default_value:
|
122
|
-
"""Adds optional argument to given `parser` to define conversion of TimeSteps"""
|
124
|
+
def add_time_argument(parser: ArgumentParser, default_value: TimeOptions | str) -> None:
|
125
|
+
"""Adds optional argument to given `parser` to define conversion of TimeSteps."""
|
123
126
|
default_value = default_value if isinstance(default_value, TimeOptions) else TimeOptions[default_value]
|
124
|
-
help_text = "Apply conversion of time steps to given format (default=
|
127
|
+
help_text = f"Apply conversion of time steps to given format (default={default_value.name})"
|
125
128
|
parser.add_argument(
|
126
129
|
"-t",
|
127
130
|
"--time",
|
@@ -132,8 +135,8 @@ def add_time_argument(parser: ArgumentParser, default_value: Union[TimeOptions,
|
|
132
135
|
)
|
133
136
|
|
134
137
|
|
135
|
-
def add_merge_time_argument(parser: ArgumentParser, defaults:
|
136
|
-
"""Adds optional three-fold argument for merging of TimeSteps to given `parser
|
138
|
+
def add_merge_time_argument(parser: ArgumentParser, defaults: list[int] | None = None) -> None:
|
139
|
+
"""Adds optional three-fold argument for merging of TimeSteps to given `parser`."""
|
137
140
|
if defaults is None:
|
138
141
|
defaults = []
|
139
142
|
if (
|
@@ -150,29 +153,61 @@ def add_merge_time_argument(parser: ArgumentParser, defaults: Optional[list[int]
|
|
150
153
|
parser.add_argument("-mt", "--merge-times", type=int, nargs=3, default=defaults, help=help_text)
|
151
154
|
|
152
155
|
|
153
|
-
def add_inputs_recovery_argument(parser: ArgumentParser,
|
154
|
-
"""Adds optional bool argument to given `parser` to recover inputs"""
|
155
|
-
|
156
|
-
parser
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
156
|
+
def add_inputs_recovery_argument(parser: ArgumentParser, default_value: bool) -> None:
|
157
|
+
"""Adds optional bool argument to given `parser` to recover inputs."""
|
158
|
+
description = "(no) inputs will be recovered"
|
159
|
+
_add_optional_boolean_argument(parser, default_value, "input-recovery", description)
|
160
|
+
|
161
|
+
|
162
|
+
def _add_optional_boolean_argument(parser: ArgumentParser, default: bool, arg_name: str, description: str) -> None:
|
163
|
+
"""Adds optional boolean argument to parser.
|
164
|
+
|
165
|
+
Argument named `arg_name` is added to given `parser` overwriting the provided default.
|
166
|
+
Help from argument `description` is added as help text.
|
167
|
+
|
168
|
+
Args:
|
169
|
+
parser: to add the argument to
|
170
|
+
default: of the argument
|
171
|
+
arg_name: long name of the argument, no short name allowed; will be prepended with 'no-' for negation
|
172
|
+
description: to create the help text from: "If --(no-)<arg_name> is specified, <description> (default=X)'
|
173
|
+
"""
|
174
|
+
default_str = "--" + ("no-" if not default else "") + arg_name
|
175
|
+
help_text = f"If --(no-){arg_name} is specified, {description} (default={default_str})"
|
176
|
+
parser.add_argument(f"--{arg_name}", action=BooleanOptionalAction, default=default, help=help_text)
|
162
177
|
|
163
178
|
|
164
|
-
def
|
165
|
-
"""
|
166
|
-
|
167
|
-
|
168
|
-
|
179
|
+
def add_file_pattern_argument(parser: ArgumentParser, default_value: str | None) -> None:
|
180
|
+
"""Adds argument to given `parser` to specify a file pattern; if no default provided, the argument is mandatory."""
|
181
|
+
help_text = f"Path to csv file(s) that are to be converted (default='{default_value}')"
|
182
|
+
required = not bool(default_value)
|
183
|
+
parser.add_argument("--file-pattern", "-fp", required=required, type=str, default=default_value, help=help_text)
|
184
|
+
|
185
|
+
|
186
|
+
def add_replace_argument(parser: ArgumentParser, default_value: bool) -> None:
|
187
|
+
"""Adds optional bool argument to given `parser` to replace converted files."""
|
188
|
+
description = "original files will (not) be replaced"
|
189
|
+
_add_optional_boolean_argument(parser, default_value, "replace", description)
|
190
|
+
|
191
|
+
|
192
|
+
def update_default_config(overrides: dict[Options, Any] | None, defaults: dict[Options, Any]) -> dict[Options, Any]:
|
193
|
+
"""Returns `defaults` with updated fields received from `overrides`.
|
194
|
+
|
195
|
+
Args:
|
196
|
+
overrides: updates to be applied to `defaults`
|
197
|
+
defaults: base values, possibly replaced by options specified in `config`
|
198
|
+
|
199
|
+
Returns:
|
200
|
+
Deep copy of given `defaults` with updates values as specified in `overrides`
|
201
|
+
"""
|
202
|
+
result = copy.deepcopy(defaults)
|
203
|
+
if overrides:
|
204
|
+
for name, option in overrides.items():
|
169
205
|
result[name] = option
|
170
206
|
return result
|
171
207
|
|
172
208
|
|
173
209
|
def map_namespace_to_options_dict(parsed: Namespace) -> dict[Options, Any]:
|
174
|
-
"""
|
175
|
-
Maps given parsing results to their corresponding configuration option
|
210
|
+
"""Maps given parsing results to their corresponding configuration option.
|
176
211
|
|
177
212
|
Args:
|
178
213
|
parsed: result of a parsing
|
@@ -183,10 +218,11 @@ def map_namespace_to_options_dict(parsed: Namespace) -> dict[Options, Any]:
|
|
183
218
|
return _map_namespace_to_options(parsed, _OPTION_ARGUMENT_NAME)
|
184
219
|
|
185
220
|
|
186
|
-
def _map_namespace_to_options(parsed: Namespace, names_to_options: dict[str,
|
187
|
-
"""
|
188
|
-
|
189
|
-
|
221
|
+
def _map_namespace_to_options(parsed: Namespace, names_to_options: dict[str, Options]) -> dict[Options, Any]:
|
222
|
+
"""Maps given parsing results to their corresponding configuration option.
|
223
|
+
|
224
|
+
Elements that cannot be mapped are ignored.
|
225
|
+
If a configuration option has inner elements, these will be also read and added as inner dictionary.
|
190
226
|
|
191
227
|
Args:
|
192
228
|
parsed: result of a parsing
|
fameio/cli/reformat.py
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 German Aerospace Center <fame@dlr.de>
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
from __future__ import annotations
|
5
|
+
|
6
|
+
import argparse
|
7
|
+
from typing import Any
|
8
|
+
|
9
|
+
from fameio.cli.options import Options
|
10
|
+
from fameio.cli.parser import (
|
11
|
+
map_namespace_to_options_dict,
|
12
|
+
add_logfile_argument,
|
13
|
+
add_log_level_argument,
|
14
|
+
add_file_pattern_argument,
|
15
|
+
add_replace_argument,
|
16
|
+
)
|
17
|
+
|
18
|
+
CLI_DEFAULTS = {
|
19
|
+
Options.LOG_LEVEL: "WARN",
|
20
|
+
Options.LOG_FILE: None,
|
21
|
+
Options.FILE_PATTERN: None,
|
22
|
+
Options.REPLACE: False,
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
def handle_args(args: list[str], defaults: dict[Options, Any] | None = None) -> dict[Options, Any]:
|
27
|
+
"""Converts given `args` and returns a configuration for the transform script.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
args: list of (command line) arguments, e.g., ['-fp', 'my_file']; arg values take precedence over defaults
|
31
|
+
defaults: optional default values used for unspecified parameters; missing defaults are replaced by CLI defaults
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
final configuration compiled from (given) `defaults` and given `args`
|
35
|
+
"""
|
36
|
+
parser = _prepare_parser(defaults)
|
37
|
+
parsed = parser.parse_args(args)
|
38
|
+
return map_namespace_to_options_dict(parsed)
|
39
|
+
|
40
|
+
|
41
|
+
def _prepare_parser(defaults: dict[Options, Any] | None) -> argparse.ArgumentParser:
|
42
|
+
"""Creates a parser with given defaults to handle `reformat` configuration arguments.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
new parser using given defaults for its arguments; if a default is not specified, hard-coded defaults are used
|
46
|
+
"""
|
47
|
+
defaults = defaults if (defaults is not None) else {}
|
48
|
+
parser = argparse.ArgumentParser()
|
49
|
+
add_log_level_argument(parser, _get_default(defaults, Options.LOG_LEVEL))
|
50
|
+
add_logfile_argument(parser, _get_default(defaults, Options.LOG_FILE))
|
51
|
+
add_file_pattern_argument(parser, _get_default(defaults, Options.FILE_PATTERN))
|
52
|
+
add_replace_argument(parser, _get_default(defaults, Options.REPLACE))
|
53
|
+
return parser
|
54
|
+
|
55
|
+
|
56
|
+
def _get_default(defaults: dict, option: Options) -> Any:
|
57
|
+
"""Returns default for given `option` or its cli default."""
|
58
|
+
return defaults.get(option, CLI_DEFAULTS[option])
|
fameio/input/__init__.py
CHANGED
@@ -4,16 +4,16 @@
|
|
4
4
|
|
5
5
|
|
6
6
|
class InputError(Exception):
|
7
|
-
"""An error that occurred while
|
7
|
+
"""An error that occurred while preparing a fame input file."""
|
8
8
|
|
9
9
|
|
10
10
|
class SchemaError(InputError):
|
11
|
-
"""An error that occurred while parsing a Schema"""
|
11
|
+
"""An error that occurred while parsing a Schema."""
|
12
12
|
|
13
13
|
|
14
14
|
class ScenarioError(InputError):
|
15
|
-
"""An error that occurred while parsing a Scenario"""
|
15
|
+
"""An error that occurred while parsing a Scenario."""
|
16
16
|
|
17
17
|
|
18
18
|
class YamlLoaderError(InputError):
|
19
|
-
"""An error that occurred while parsing a YAML file"""
|
19
|
+
"""An error that occurred while parsing a YAML file."""
|
fameio/input/loader/__init__.py
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
# SPDX-FileCopyrightText:
|
1
|
+
# SPDX-FileCopyrightText: 2025 German Aerospace Center <fame@dlr.de>
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
from __future__ import annotations
|
5
|
+
|
4
6
|
from pathlib import Path
|
5
7
|
from typing import Any
|
6
8
|
|
7
9
|
import yaml
|
8
10
|
|
9
11
|
from fameio.input import YamlLoaderError
|
10
|
-
from fameio.input.resolver import PathResolver
|
11
12
|
from fameio.input.loader.controller import LoaderController
|
12
13
|
from fameio.input.loader.loader import FameYamlLoader
|
13
|
-
from fameio.
|
14
|
+
from fameio.input.resolver import PathResolver
|
15
|
+
from fameio.logs import log, log_critical
|
14
16
|
|
15
17
|
ALLOWED_SUFFIXES: tuple[str, ...] = (".yaml", ".yml")
|
16
18
|
|
@@ -29,9 +31,8 @@ def _include_callback(own_loader: FameYamlLoader, args: yaml.Node) -> Any:
|
|
29
31
|
FameYamlLoader.add_constructor(FameYamlLoader.INCLUDE_COMMAND, _include_callback)
|
30
32
|
|
31
33
|
|
32
|
-
def load_yaml(yaml_file_path: Path, path_resolver: PathResolver = PathResolver(), encoding: str = None) -> dict:
|
33
|
-
"""
|
34
|
-
Loads the YAML file from given and returns its content as a dict
|
34
|
+
def load_yaml(yaml_file_path: Path, path_resolver: PathResolver = PathResolver(), encoding: str | None = None) -> dict:
|
35
|
+
"""Loads the YAML file from given `yaml_file_path` and returns its content as a dict.
|
35
36
|
|
36
37
|
Args:
|
37
38
|
yaml_file_path: Path to the YAML file that is to be read
|
@@ -42,27 +43,26 @@ def load_yaml(yaml_file_path: Path, path_resolver: PathResolver = PathResolver()
|
|
42
43
|
Content of the specified YAML file
|
43
44
|
|
44
45
|
Raises:
|
45
|
-
YamlLoaderError: if the YAML file could not be read
|
46
|
+
YamlLoaderError: if the YAML file could not be found, read, or parsed
|
46
47
|
"""
|
47
48
|
log().info(_INFO_LOADING.format(yaml_file_path))
|
48
49
|
_update_current_controller(path_resolver, encoding)
|
49
50
|
return __CONTROLLERS[0].load(yaml_file_path)
|
50
51
|
|
51
52
|
|
52
|
-
def _update_current_controller(path_resolver: PathResolver, encoding: str) -> None:
|
53
|
-
"""Updates the current LoaderController to use the given `path_resolver` and `encoding
|
53
|
+
def _update_current_controller(path_resolver: PathResolver, encoding: str | None) -> None:
|
54
|
+
"""Updates the current LoaderController to use the given `path_resolver` and `encoding`."""
|
54
55
|
__CONTROLLERS[0] = LoaderController(path_resolver, encoding)
|
55
56
|
|
56
57
|
|
57
58
|
def validate_yaml_file_suffix(yaml_file: Path) -> None:
|
58
|
-
"""
|
59
|
-
Ensures that given file has a file suffix compatible with YAML
|
59
|
+
"""Ensures that given file has a file suffix compatible with YAML.
|
60
60
|
|
61
61
|
Args:
|
62
62
|
yaml_file: that is to be checked for suffix correctness
|
63
63
|
|
64
64
|
Raises:
|
65
|
-
YamlLoaderError: if given file has no YAML-associated file suffix
|
65
|
+
YamlLoaderError: if given file has no YAML-associated file suffix, logged with level "CRITICAL"
|
66
66
|
"""
|
67
67
|
if yaml_file.suffix.lower() not in ALLOWED_SUFFIXES:
|
68
|
-
|
68
|
+
raise log_critical(YamlLoaderError(_ERR_NO_YAML_SUFFIX.format(ALLOWED_SUFFIXES, yaml_file)))
|