fameio 2.3.0__py3-none-any.whl → 3.0.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.
Files changed (63) hide show
  1. CHANGELOG.md +28 -0
  2. fameio/__init__.py +4 -1
  3. fameio/{source/cli → cli}/__init__.py +2 -0
  4. fameio/{source/cli → cli}/convert_results.py +8 -8
  5. fameio/{source/cli → cli}/make_config.py +5 -5
  6. fameio/{source/cli → cli}/options.py +0 -8
  7. fameio/{source/cli → cli}/parser.py +26 -63
  8. fameio/input/__init__.py +27 -0
  9. fameio/input/loader/__init__.py +68 -0
  10. fameio/input/loader/controller.py +129 -0
  11. fameio/input/loader/loader.py +109 -0
  12. fameio/input/metadata.py +149 -0
  13. fameio/input/resolver.py +44 -0
  14. fameio/{source → input}/scenario/__init__.py +1 -2
  15. fameio/{source → input}/scenario/agent.py +24 -38
  16. fameio/input/scenario/attribute.py +203 -0
  17. fameio/{source → input}/scenario/contract.py +50 -61
  18. fameio/{source → input}/scenario/exception.py +8 -13
  19. fameio/{source → input}/scenario/fameiofactory.py +6 -6
  20. fameio/{source → input}/scenario/generalproperties.py +22 -47
  21. fameio/{source → input}/scenario/scenario.py +34 -31
  22. fameio/input/scenario/stringset.py +48 -0
  23. fameio/{source → input}/schema/__init__.py +2 -2
  24. fameio/input/schema/agenttype.py +125 -0
  25. fameio/input/schema/attribute.py +268 -0
  26. fameio/{source → input}/schema/java_packages.py +26 -22
  27. fameio/{source → input}/schema/schema.py +25 -22
  28. fameio/{source → input}/validator.py +32 -35
  29. fameio/{source → input}/writer.py +86 -86
  30. fameio/{source/logs.py → logs.py} +25 -9
  31. fameio/{source/results → output}/agent_type.py +21 -22
  32. fameio/{source/results → output}/conversion.py +34 -31
  33. fameio/{source/results → output}/csv_writer.py +7 -7
  34. fameio/{source/results → output}/data_transformer.py +24 -24
  35. fameio/{source/results → output}/input_dao.py +51 -49
  36. fameio/{source/results → output}/output_dao.py +16 -17
  37. fameio/{source/results → output}/reader.py +30 -31
  38. fameio/{source/results → output}/yaml_writer.py +2 -3
  39. fameio/scripts/__init__.py +2 -2
  40. fameio/scripts/convert_results.py +16 -15
  41. fameio/scripts/make_config.py +9 -9
  42. fameio/{source/series.py → series.py} +28 -26
  43. fameio/{source/time.py → time.py} +8 -8
  44. fameio/{source/tools.py → tools.py} +2 -2
  45. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/METADATA +277 -72
  46. fameio-3.0.0.dist-info/RECORD +56 -0
  47. fameio/source/__init__.py +0 -8
  48. fameio/source/loader.py +0 -181
  49. fameio/source/metadata.py +0 -32
  50. fameio/source/path_resolver.py +0 -34
  51. fameio/source/scenario/attribute.py +0 -130
  52. fameio/source/scenario/stringset.py +0 -51
  53. fameio/source/schema/agenttype.py +0 -132
  54. fameio/source/schema/attribute.py +0 -203
  55. fameio/source/schema/exception.py +0 -9
  56. fameio-2.3.0.dist-info/RECORD +0 -55
  57. /fameio/{source/results → output}/__init__.py +0 -0
  58. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/LICENSE.txt +0 -0
  59. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/LICENSES/Apache-2.0.txt +0 -0
  60. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/LICENSES/CC-BY-4.0.txt +0 -0
  61. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/LICENSES/CC0-1.0.txt +0 -0
  62. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/WHEEL +0 -0
  63. {fameio-2.3.0.dist-info → fameio-3.0.0.dist-info}/entry_points.txt +0 -0
@@ -3,26 +3,26 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from __future__ import annotations
5
5
 
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, Optional, Final
7
7
 
8
- from fameio.source.logs import log
9
- from fameio.source.scenario.attribute import Attribute
10
- from fameio.source.scenario.exception import get_or_default, get_or_raise, log_and_raise
11
- from fameio.source.time import FameTime
12
- from fameio.source.tools import ensure_is_list, keys_to_lower
8
+ from fameio.input.metadata import Metadata
9
+ from fameio.logs import log
10
+ from fameio.time import FameTime
11
+ from fameio.tools import ensure_is_list, keys_to_lower
12
+ from .attribute import Attribute
13
+ from .exception import get_or_default, get_or_raise, log_and_raise
13
14
 
14
15
 
15
- class Contract:
16
+ class Contract(Metadata):
16
17
  """Contract between two Agents of a scenario"""
17
18
 
18
- _KEY_SENDER = "SenderId".lower()
19
- _KEY_RECEIVER = "ReceiverId".lower()
20
- _KEY_PRODUCT = "ProductName".lower()
21
- _KEY_FIRST_DELIVERY = "FirstDeliveryTime".lower()
22
- _KEY_INTERVAL = "DeliveryIntervalInSteps".lower()
23
- _KEY_EXPIRE = "ExpirationTime".lower()
24
- _KEY_METADATA = "MetaData".lower()
25
- _KEY_ATTRIBUTES = "Attributes".lower()
19
+ KEY_SENDER: Final[str] = "SenderId".lower()
20
+ KEY_RECEIVER: Final[str] = "ReceiverId".lower()
21
+ KEY_PRODUCT: Final[str] = "ProductName".lower()
22
+ KEY_FIRST_DELIVERY: Final[str] = "FirstDeliveryTime".lower()
23
+ KEY_INTERVAL: Final[str] = "DeliveryIntervalInSteps".lower()
24
+ KEY_EXPIRE: Final[str] = "ExpirationTime".lower()
25
+ KEY_ATTRIBUTES: Final[str] = "Attributes".lower()
26
26
 
27
27
  _ERR_MISSING_KEY = "Contract requires key '{}' but is missing it."
28
28
  _ERR_MULTI_CONTRACT_CORRUPT = (
@@ -42,9 +42,10 @@ class Contract:
42
42
  delivery_interval: int,
43
43
  first_delivery_time: int,
44
44
  expiration_time: Optional[int] = None,
45
- meta_data: Optional[dict] = None,
45
+ metadata: Optional[dict] = None,
46
46
  ) -> None:
47
47
  """Constructs a new Contract"""
48
+ super().__init__({self.KEY_METADATA: metadata} if metadata else None)
48
49
  assert product_name != ""
49
50
  if sender_id == receiver_id:
50
51
  log().warning(self._ERR_SENDER_IS_RECEIVER.format(sender_id))
@@ -56,7 +57,6 @@ class Contract:
56
57
  self._delivery_interval = delivery_interval
57
58
  self._first_delivery_time = first_delivery_time
58
59
  self._expiration_time = expiration_time
59
- self._meta_data = meta_data
60
60
  self._attributes = {}
61
61
 
62
62
  def _notify_data_changed(self):
@@ -104,12 +104,7 @@ class Contract:
104
104
  return self._expiration_time
105
105
 
106
106
  @property
107
- def meta_data(self) -> Optional[dict]:
108
- """Returns the metadata of the contract if available, None otherwise"""
109
- return self._meta_data
110
-
111
- @property
112
- def attributes(self) -> Dict[str, Attribute]:
107
+ def attributes(self) -> dict[str, Attribute]:
113
108
  """Returns dictionary of all Attributes of the contract"""
114
109
  return self._attributes
115
110
 
@@ -124,30 +119,30 @@ class Contract:
124
119
  def from_dict(cls, definitions: dict) -> Contract:
125
120
  """Parses Contract from given `definitions`"""
126
121
  definitions = keys_to_lower(definitions)
127
- sender_id = get_or_raise(definitions, Contract._KEY_SENDER, Contract._ERR_MISSING_KEY)
128
- receiver_id = get_or_raise(definitions, Contract._KEY_RECEIVER, Contract._ERR_MISSING_KEY)
129
- product_name = get_or_raise(definitions, Contract._KEY_PRODUCT, Contract._ERR_MISSING_KEY)
122
+ sender_id = get_or_raise(definitions, Contract.KEY_SENDER, Contract._ERR_MISSING_KEY)
123
+ receiver_id = get_or_raise(definitions, Contract.KEY_RECEIVER, Contract._ERR_MISSING_KEY)
124
+ product_name = get_or_raise(definitions, Contract.KEY_PRODUCT, Contract._ERR_MISSING_KEY)
130
125
  first_delivery_time = FameTime.convert_string_if_is_datetime(
131
- get_or_raise(definitions, Contract._KEY_FIRST_DELIVERY, Contract._ERR_MISSING_KEY)
126
+ get_or_raise(definitions, Contract.KEY_FIRST_DELIVERY, Contract._ERR_MISSING_KEY)
132
127
  )
133
- delivery_interval = get_or_raise(definitions, Contract._KEY_INTERVAL, Contract._ERR_MISSING_KEY)
134
- expiration_time = get_or_default(definitions, Contract._KEY_EXPIRE, None)
128
+ delivery_interval = get_or_raise(definitions, Contract.KEY_INTERVAL, Contract._ERR_MISSING_KEY)
129
+ expiration_time = get_or_default(definitions, Contract.KEY_EXPIRE, None)
135
130
  expiration_time = FameTime.convert_string_if_is_datetime(expiration_time) if expiration_time else None
136
- meta_data = get_or_default(definitions, Contract._KEY_METADATA, None)
137
- result = cls(
131
+
132
+ contract = cls(
138
133
  sender_id,
139
134
  receiver_id,
140
135
  product_name,
141
136
  delivery_interval,
142
137
  first_delivery_time,
143
138
  expiration_time,
144
- meta_data,
145
139
  )
146
- attribute_definitions = get_or_default(definitions, Contract._KEY_ATTRIBUTES, dict())
147
- result._init_attributes_from_dict(attribute_definitions)
148
- return result
140
+ contract._extract_metadata(definitions)
141
+ attribute_definitions = get_or_default(definitions, Contract.KEY_ATTRIBUTES, {})
142
+ contract._init_attributes_from_dict(attribute_definitions)
143
+ return contract
149
144
 
150
- def _init_attributes_from_dict(self, attributes: Dict[str, Any]) -> None:
145
+ def _init_attributes_from_dict(self, attributes: dict[str, Any]) -> None:
151
146
  """Resets Contract `attributes` from dict; Must only be called when creating a new Contract"""
152
147
  assert len(self._attributes) == 0
153
148
  self._attributes = {}
@@ -155,47 +150,41 @@ class Contract:
155
150
  full_name = f"{type}.{id}{name}"
156
151
  self.add_attribute(name, Attribute(full_name, value))
157
152
 
158
- def to_dict(self) -> dict:
153
+ def _to_dict(self) -> dict:
159
154
  """Serializes the Contract content to a dict"""
160
155
  result = {
161
- self._KEY_SENDER: self.sender_id,
162
- self._KEY_RECEIVER: self.receiver_id,
163
- self._KEY_PRODUCT: self.product_name,
164
- self._KEY_FIRST_DELIVERY: self.first_delivery_time,
165
- self._KEY_INTERVAL: self.delivery_interval,
156
+ self.KEY_SENDER: self.sender_id,
157
+ self.KEY_RECEIVER: self.receiver_id,
158
+ self.KEY_PRODUCT: self.product_name,
159
+ self.KEY_FIRST_DELIVERY: self.first_delivery_time,
160
+ self.KEY_INTERVAL: self.delivery_interval,
166
161
  }
167
162
 
168
163
  if self.expiration_time is not None:
169
- result[self._KEY_EXPIRE] = self.expiration_time
164
+ result[self.KEY_EXPIRE] = self.expiration_time
170
165
 
171
166
  if len(self.attributes) > 0:
172
- attributes_dict = {}
173
- for attr_name, attr_value in self.attributes.items():
174
- attributes_dict[attr_name] = attr_value.generic_content
175
- result[self._KEY_ATTRIBUTES] = attributes_dict
176
- if self.meta_data:
177
- result[self._KEY_METADATA] = self._meta_data
178
-
167
+ result[self.KEY_ATTRIBUTES] = {name: value.to_dict() for name, value in self.attributes.items()}
179
168
  return result
180
169
 
181
170
  @staticmethod
182
- def split_contract_definitions(multi_definition: dict) -> List[dict]:
171
+ def split_contract_definitions(multi_definition: dict) -> list[dict]:
183
172
  """Splits given `multi_definition` dictionary into list of individual Contract definitions"""
184
173
  contracts = []
185
174
  base_data = {}
186
175
  multi_definition = keys_to_lower(multi_definition)
187
176
  for key in [
188
- Contract._KEY_PRODUCT,
189
- Contract._KEY_FIRST_DELIVERY,
190
- Contract._KEY_INTERVAL,
191
- Contract._KEY_EXPIRE,
192
- Contract._KEY_METADATA,
193
- Contract._KEY_ATTRIBUTES,
177
+ Contract.KEY_PRODUCT,
178
+ Contract.KEY_FIRST_DELIVERY,
179
+ Contract.KEY_INTERVAL,
180
+ Contract.KEY_EXPIRE,
181
+ Contract.KEY_METADATA,
182
+ Contract.KEY_ATTRIBUTES,
194
183
  ]:
195
184
  if key in multi_definition:
196
185
  base_data[key] = multi_definition[key]
197
- senders = ensure_is_list(get_or_raise(multi_definition, Contract._KEY_SENDER, Contract._ERR_MISSING_KEY))
198
- receivers = ensure_is_list(get_or_raise(multi_definition, Contract._KEY_RECEIVER, Contract._ERR_MISSING_KEY))
186
+ senders = ensure_is_list(get_or_raise(multi_definition, Contract.KEY_SENDER, Contract._ERR_MISSING_KEY))
187
+ receivers = ensure_is_list(get_or_raise(multi_definition, Contract.KEY_RECEIVER, Contract._ERR_MISSING_KEY))
199
188
  if len(senders) > 1 and len(receivers) == 1:
200
189
  for index in range(len(senders)):
201
190
  contracts.append(Contract._copy_contract(senders[index], receivers[0], base_data))
@@ -213,8 +202,8 @@ class Contract:
213
202
  def _copy_contract(sender: int, receiver: int, base_data: dict) -> dict:
214
203
  """Returns a new contract definition dictionary, with given `sender` and `receiver` and copied `base_data`"""
215
204
  contract = {
216
- Contract._KEY_SENDER: sender,
217
- Contract._KEY_RECEIVER: receiver,
205
+ Contract.KEY_SENDER: sender,
206
+ Contract.KEY_RECEIVER: receiver,
218
207
  }
219
208
  contract.update(base_data)
220
209
  return contract
@@ -1,31 +1,32 @@
1
- # SPDX-FileCopyrightText: 2023 German Aerospace Center <fame@dlr.de>
1
+ # SPDX-FileCopyrightText: 2024 German Aerospace Center <fame@dlr.de>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  from typing import NoReturn, Any, Union
6
6
 
7
- from fameio.source.logs import log_error_and_raise, log
7
+ from fameio.input import ScenarioError
8
+ from fameio.logs import log_error_and_raise, log
8
9
 
9
10
  _DEFAULT_USED = "Using default value '{}' for missing key '{}'"
10
11
 
11
12
 
12
13
  def log_and_raise(message: str) -> NoReturn:
13
- """Raises ScenarioException with given `message`"""
14
- log_error_and_raise(ScenarioException(message))
14
+ """Raises ScenarioError with given `message`"""
15
+ log_error_and_raise(ScenarioError(message))
15
16
 
16
17
 
17
18
  def get_or_raise(dictionary: dict, key: str, message: str) -> Union[Any, NoReturn]:
18
19
  """Returns value associated with `key` in given `dictionary`, or raises ScenarioException if key is missing"""
19
20
  if key not in dictionary or dictionary[key] is None:
20
- log_error_and_raise(ScenarioException(message.format(key)))
21
+ log_error_and_raise(ScenarioError(message.format(key)))
21
22
  else:
22
23
  return dictionary[key]
23
24
 
24
25
 
25
26
  def assert_or_raise(assertion: bool, msg: str) -> None:
26
- """Raises new ScenarioException with given `msg` if `assertion` is False"""
27
+ """Raises new ScenarioError with given `msg` if `assertion` is False"""
27
28
  if not assertion:
28
- log_error_and_raise(ScenarioException(msg))
29
+ log_error_and_raise(ScenarioError(msg))
29
30
 
30
31
 
31
32
  def get_or_default(dictionary: dict, key: str, default_value) -> Any:
@@ -35,9 +36,3 @@ def get_or_default(dictionary: dict, key: str, default_value) -> Any:
35
36
  else:
36
37
  log().debug(_DEFAULT_USED.format(default_value, key))
37
38
  return default_value
38
-
39
-
40
- class ScenarioException(Exception):
41
- """Indicates an error while parsing a scenario or one of its components"""
42
-
43
- pass
@@ -1,11 +1,11 @@
1
- # SPDX-FileCopyrightText: 2023 German Aerospace Center <fame@dlr.de>
1
+ # SPDX-FileCopyrightText: 2024 German Aerospace Center <fame@dlr.de>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- from fameio.source.scenario.stringset import StringSet
5
- from fameio.source.schema.schema import Schema
6
- from fameio.source.scenario.generalproperties import GeneralProperties
7
- from fameio.source.scenario.agent import Agent
8
- from fameio.source.scenario.contract import Contract
4
+ from fameio.input.schema import Schema
5
+ from .agent import Agent
6
+ from .contract import Contract
7
+ from .generalproperties import GeneralProperties
8
+ from .stringset import StringSet
9
9
 
10
10
 
11
11
  class FameIOFactory:
@@ -3,27 +3,25 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from __future__ import annotations
5
5
 
6
- from fameio.source.logs import log
7
- from fameio.source.scenario.exception import get_or_default, get_or_raise
8
- from fameio.source.time import FameTime
9
- from fameio.source.tools import keys_to_lower
6
+ from typing import Final
7
+
8
+ from fameio.logs import log
9
+ from fameio.time import FameTime
10
+ from fameio.tools import keys_to_lower
11
+ from .exception import get_or_default, get_or_raise
10
12
 
11
13
 
12
14
  class GeneralProperties:
13
15
  """Hosts general properties of a scenario"""
14
16
 
15
- _KEY_RUN = "RunId".lower()
16
- _KEY_SIMULATION = "Simulation".lower()
17
- _KEY_START = "StartTime".lower()
18
- _KEY_STOP = "StopTime".lower()
19
- _KEY_SEED = "RandomSeed".lower()
20
- _KEY_OUTPUT = "Output".lower()
21
- _KEY_INTERVAL = "Interval".lower()
22
- _KEY_PROCESS = "Process".lower()
17
+ KEY_RUN: Final[str] = "RunId".lower()
18
+ KEY_SIMULATION = "Simulation".lower()
19
+ KEY_START = "StartTime".lower()
20
+ KEY_STOP = "StopTime".lower()
21
+ KEY_SEED = "RandomSeed".lower()
23
22
 
24
23
  _ERR_MISSING_KEY = "General Properties requires key '{}' but it is missing."
25
24
  _ERR_SIMULATION_DURATION = "Simulation starts after its end time - check start and stop times."
26
- _WARN_OUTPUT_DEPRECATED = "Deprecation warning: GeneralProperties.Output will be removed with FAME-Io version > 3.0"
27
25
 
28
26
  def __init__(
29
27
  self,
@@ -31,8 +29,6 @@ class GeneralProperties:
31
29
  simulation_start_time: int,
32
30
  simulation_stop_time: int,
33
31
  simulation_random_seed: int,
34
- output_interval: int,
35
- output_process: int,
36
32
  ) -> None:
37
33
  if simulation_stop_time < simulation_start_time:
38
34
  log().warning(GeneralProperties._ERR_SIMULATION_DURATION)
@@ -40,57 +36,46 @@ class GeneralProperties:
40
36
  self._simulation_start_time = simulation_start_time
41
37
  self._simulation_stop_time = simulation_stop_time
42
38
  self._simulation_random_seed = simulation_random_seed
43
- self._output_interval = output_interval
44
- self._output_process = output_process
45
39
 
46
40
  @classmethod
47
41
  def from_dict(cls, definitions: dict) -> GeneralProperties:
48
42
  """Parse general properties from provided `definitions`"""
49
43
  definitions = keys_to_lower(definitions)
50
- run_id = get_or_default(definitions, GeneralProperties._KEY_RUN, 1)
44
+ run_id = get_or_default(definitions, GeneralProperties.KEY_RUN, 1)
51
45
 
52
46
  simulation_definition = keys_to_lower(
53
47
  get_or_raise(
54
48
  definitions,
55
- GeneralProperties._KEY_SIMULATION,
49
+ GeneralProperties.KEY_SIMULATION,
56
50
  GeneralProperties._ERR_MISSING_KEY,
57
51
  )
58
52
  )
59
53
  start_time = FameTime.convert_string_if_is_datetime(
60
54
  get_or_raise(
61
55
  simulation_definition,
62
- GeneralProperties._KEY_START,
56
+ GeneralProperties.KEY_START,
63
57
  GeneralProperties._ERR_MISSING_KEY,
64
58
  )
65
59
  )
66
60
  stop_time = FameTime.convert_string_if_is_datetime(
67
61
  get_or_raise(
68
62
  simulation_definition,
69
- GeneralProperties._KEY_STOP,
63
+ GeneralProperties.KEY_STOP,
70
64
  GeneralProperties._ERR_MISSING_KEY,
71
65
  )
72
66
  )
73
- random_seed = get_or_default(simulation_definition, GeneralProperties._KEY_SEED, 1)
74
-
75
- output_definitions = keys_to_lower(get_or_default(definitions, GeneralProperties._KEY_OUTPUT, dict()))
76
- if len(output_definitions) > 1:
77
- log().warning(GeneralProperties._WARN_OUTPUT_DEPRECATED)
78
- output_interval = get_or_default(output_definitions, GeneralProperties._KEY_INTERVAL, 100)
79
- output_process = get_or_default(output_definitions, GeneralProperties._KEY_PROCESS, 0)
80
-
81
- return cls(run_id, start_time, stop_time, random_seed, output_interval, output_process)
67
+ random_seed = get_or_default(simulation_definition, GeneralProperties.KEY_SEED, 1)
68
+ return cls(run_id, start_time, stop_time, random_seed)
82
69
 
83
70
  def to_dict(self) -> dict:
84
71
  """Serializes the general properties to a dict"""
85
- result = {self._KEY_RUN: self._run_id}
72
+ result = {self.KEY_RUN: self._run_id}
86
73
  simulation_dict = {
87
- self._KEY_START: self.simulation_start_time,
88
- self._KEY_STOP: self.simulation_stop_time,
89
- self._KEY_SEED: self.simulation_random_seed,
74
+ self.KEY_START: self.simulation_start_time,
75
+ self.KEY_STOP: self.simulation_stop_time,
76
+ self.KEY_SEED: self.simulation_random_seed,
90
77
  }
91
- result[self._KEY_SIMULATION] = simulation_dict
92
- output_dict = {self._KEY_INTERVAL: self.output_interval, self._KEY_PROCESS: self.output_process}
93
- result[self._KEY_OUTPUT] = output_dict
78
+ result[self.KEY_SIMULATION] = simulation_dict
94
79
  return result
95
80
 
96
81
  @property
@@ -112,13 +97,3 @@ class GeneralProperties:
112
97
  def simulation_random_seed(self) -> int:
113
98
  """Returns the simulation random seed"""
114
99
  return self._simulation_random_seed
115
-
116
- @property
117
- def output_interval(self) -> int:
118
- """Returns the output interval"""
119
- return self._output_interval
120
-
121
- @property
122
- def output_process(self) -> int:
123
- """Returns the output process"""
124
- return self._output_process
@@ -3,30 +3,32 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from __future__ import annotations
5
5
 
6
- from typing import List, Dict
6
+ from typing import Final
7
7
 
8
- from fameio.source.scenario.agent import Agent
9
- from fameio.source.scenario.contract import Contract
10
- from fameio.source.scenario.exception import get_or_default, get_or_raise
11
- from fameio.source.scenario.fameiofactory import FameIOFactory
12
- from fameio.source.scenario.generalproperties import GeneralProperties
13
- from fameio.source.scenario.stringset import StringSet
14
- from fameio.source.schema.schema import Schema
15
- from fameio.source.tools import keys_to_lower
8
+ from fameio.input.metadata import Metadata
9
+ from fameio.input.schema import Schema
10
+ from fameio.tools import keys_to_lower
11
+ from .agent import Agent
12
+ from .contract import Contract
13
+ from .exception import get_or_default, get_or_raise
14
+ from .fameiofactory import FameIOFactory
15
+ from .generalproperties import GeneralProperties
16
+ from .stringset import StringSet
16
17
 
17
18
 
18
- class Scenario:
19
+ class Scenario(Metadata):
19
20
  """Definition of a scenario"""
20
21
 
21
- _KEY_SCHEMA = "Schema".lower()
22
- _KEY_GENERAL = "GeneralProperties".lower()
23
- _KEY_AGENTS = "Agents".lower()
24
- _KEY_CONTRACTS = "Contracts".lower()
25
- _KEY_STRING_SETS = "StringSets".lower()
22
+ KEY_SCHEMA: Final[str] = "Schema".lower()
23
+ KEY_GENERAL: Final[str] = "GeneralProperties".lower()
24
+ KEY_AGENTS: Final[str] = "Agents".lower()
25
+ KEY_CONTRACTS: Final[str] = "Contracts".lower()
26
+ KEY_STRING_SETS: Final[str] = "StringSets".lower()
26
27
 
27
28
  _MISSING_KEY = "Scenario definition misses required key '{}'."
28
29
 
29
30
  def __init__(self, schema: Schema, general_props: GeneralProperties) -> None:
31
+ super().__init__()
30
32
  self._schema = schema
31
33
  self._general_props = general_props
32
34
  self._string_sets = {}
@@ -38,46 +40,47 @@ class Scenario:
38
40
  """Parse scenario from provided `definitions` using given `factory`"""
39
41
  definitions = keys_to_lower(definitions)
40
42
 
41
- schema = factory.new_schema_from_dict(get_or_raise(definitions, Scenario._KEY_SCHEMA, Scenario._MISSING_KEY))
43
+ schema = factory.new_schema_from_dict(get_or_raise(definitions, Scenario.KEY_SCHEMA, Scenario._MISSING_KEY))
42
44
  general_props = factory.new_general_properties_from_dict(
43
- get_or_raise(definitions, Scenario._KEY_GENERAL, Scenario._MISSING_KEY)
45
+ get_or_raise(definitions, Scenario.KEY_GENERAL, Scenario._MISSING_KEY)
44
46
  )
45
47
  scenario = cls(schema, general_props)
48
+ scenario._extract_metadata(definitions)
46
49
 
47
- for name, string_set_definition in get_or_default(definitions, Scenario._KEY_STRING_SETS, {}).items():
50
+ for name, string_set_definition in get_or_default(definitions, Scenario.KEY_STRING_SETS, {}).items():
48
51
  scenario.add_string_set(name, factory.new_string_set_from_dict(string_set_definition))
49
52
 
50
- for agent_definition in get_or_default(definitions, Scenario._KEY_AGENTS, []):
53
+ for agent_definition in get_or_default(definitions, Scenario.KEY_AGENTS, []):
51
54
  scenario.add_agent(factory.new_agent_from_dict(agent_definition))
52
55
 
53
- for multi_contract_definition in get_or_default(definitions, Scenario._KEY_CONTRACTS, []):
56
+ for multi_contract_definition in get_or_default(definitions, Scenario.KEY_CONTRACTS, []):
54
57
  for single_contract_definition in Contract.split_contract_definitions(multi_contract_definition):
55
58
  scenario.add_contract(factory.new_contract_from_dict(single_contract_definition))
56
59
 
57
60
  return scenario
58
61
 
59
- def to_dict(self) -> dict:
62
+ def _to_dict(self) -> dict:
60
63
  """Serializes the scenario content to a dict"""
61
64
  result = {
62
- Scenario._KEY_GENERAL: self.general_properties.to_dict(),
63
- Scenario._KEY_SCHEMA: self.schema.to_dict(),
65
+ Scenario.KEY_GENERAL: self.general_properties.to_dict(),
66
+ Scenario.KEY_SCHEMA: self.schema.to_dict(),
64
67
  }
65
68
  if self.string_sets:
66
- result[Scenario._KEY_STRING_SETS] = {
69
+ result[Scenario.KEY_STRING_SETS] = {
67
70
  name: string_set.to_dict() for name, string_set in self.string_sets.items()
68
71
  }
69
72
  if self.agents:
70
- result[Scenario._KEY_AGENTS] = []
73
+ result[Scenario.KEY_AGENTS] = []
71
74
  for agent in self.agents:
72
- result[Scenario._KEY_AGENTS].append(agent.to_dict())
75
+ result[Scenario.KEY_AGENTS].append(agent.to_dict())
73
76
  if self.contracts:
74
- result[Scenario._KEY_CONTRACTS] = []
77
+ result[Scenario.KEY_CONTRACTS] = []
75
78
  for contract in self.contracts:
76
- result[Scenario._KEY_CONTRACTS].append(contract.to_dict())
79
+ result[Scenario.KEY_CONTRACTS].append(contract.to_dict())
77
80
  return result
78
81
 
79
82
  @property
80
- def agents(self) -> List[Agent]:
83
+ def agents(self) -> list[Agent]:
81
84
  """Returns all the agents of this scenario as a list"""
82
85
  return self._agents
83
86
 
@@ -86,7 +89,7 @@ class Scenario:
86
89
  self._agents.append(agent)
87
90
 
88
91
  @property
89
- def contracts(self) -> List[Contract]:
92
+ def contracts(self) -> list[Contract]:
90
93
  """Returns all the contracts of this scenario as a list"""
91
94
  return self._contracts
92
95
 
@@ -105,7 +108,7 @@ class Scenario:
105
108
  return self._general_props
106
109
 
107
110
  @property
108
- def string_sets(self) -> Dict[str, StringSet]:
111
+ def string_sets(self) -> dict[str, StringSet]:
109
112
  """Returns StringSets of this scenario"""
110
113
  return self._string_sets
111
114
 
@@ -0,0 +1,48 @@
1
+ # SPDX-FileCopyrightText: 2024 German Aerospace Center <fame@dlr.de>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from __future__ import annotations
5
+
6
+ from typing import Union, Final
7
+
8
+ from fameio.input.metadata import Metadata, MetadataComponent, ValueContainer
9
+ from fameio.tools import keys_to_lower
10
+ from .exception import log_and_raise
11
+
12
+
13
+ class StringSet(Metadata):
14
+ """Hosts a StringSet in the given format"""
15
+
16
+ KEY_VALUES: Final[str] = "Values".lower()
17
+
18
+ ValueType = Union[list[str], dict[str, dict]]
19
+ StringSetType = dict[str, Union[dict, ValueType]]
20
+
21
+ _ERR_KEY_MISSING = "Missing mandatory key '{}' in StringSet definition {}."
22
+
23
+ def __init__(self, definitions=None):
24
+ super().__init__(definitions)
25
+ self._value_container: ValueContainer = ValueContainer(definitions)
26
+
27
+ @classmethod
28
+ def from_dict(cls, definition: StringSetType) -> StringSet:
29
+ """Returns StringSet initialised from `definition`"""
30
+ string_set = cls(definition)
31
+ definition = keys_to_lower(definition)
32
+ if cls.KEY_VALUES in definition:
33
+ string_set._value_container = ValueContainer(definition[cls.KEY_VALUES])
34
+ else:
35
+ log_and_raise(cls._ERR_KEY_MISSING.format(cls.KEY_VALUES, definition))
36
+ return string_set
37
+
38
+ def _to_dict(self) -> dict[str, dict[str, dict[str, dict[str, dict]]]]:
39
+ return {self.KEY_VALUES: self._value_container.to_dict()}
40
+
41
+ @property
42
+ def values(self) -> dict[str, MetadataComponent]:
43
+ """Returns values and their associated MetadataComponent"""
44
+ return self._value_container.values
45
+
46
+ def is_in_set(self, key: str) -> bool:
47
+ """Returns True if `key` is a valid name in this StringSet"""
48
+ return self._value_container.has_value(key)
@@ -1,8 +1,8 @@
1
- # SPDX-FileCopyrightText: 2023 German Aerospace Center <fame@dlr.de>
1
+ # SPDX-FileCopyrightText: 2024 German Aerospace Center <fame@dlr.de>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  from .agenttype import AgentType
6
6
  from .attribute import AttributeSpecs, AttributeType
7
- from .exception import SchemaException
7
+ from .java_packages import JavaPackages
8
8
  from .schema import Schema