fameio 2.3.1__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 +24 -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 -83
  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.1.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.1.dist-info/RECORD +0 -55
  57. /fameio/{source/results → output}/__init__.py +0 -0
  58. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/LICENSE.txt +0 -0
  59. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/LICENSES/Apache-2.0.txt +0 -0
  60. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/LICENSES/CC-BY-4.0.txt +0 -0
  61. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/LICENSES/CC0-1.0.txt +0 -0
  62. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/WHEEL +0 -0
  63. {fameio-2.3.1.dist-info → fameio-3.0.0.dist-info}/entry_points.txt +0 -0
@@ -4,20 +4,17 @@
4
4
 
5
5
  import math
6
6
  from collections import Counter
7
- from typing import Any, Dict, List
7
+ from typing import Any
8
8
 
9
- from fameio.source import PathResolver
10
- from fameio.source.logs import log_error_and_raise, log
11
- from fameio.source.scenario import Agent, Attribute, Contract, Scenario
12
- from fameio.source.scenario.stringset import StringSet
13
- from fameio.source.schema.agenttype import AgentType
14
- from fameio.source.schema.attribute import AttributeSpecs, AttributeType
15
- from fameio.source.schema.schema import Schema
16
- from fameio.source.series import TimeSeriesManager, TimeSeriesException
17
- from fameio.source.time import FameTime
9
+ from fameio.input.resolver import PathResolver
10
+ from fameio.input.scenario import Agent, Attribute, Contract, Scenario, StringSet
11
+ from fameio.input.schema import Schema, AttributeSpecs, AttributeType, AgentType
12
+ from fameio.logs import log_error_and_raise, log
13
+ from fameio.series import TimeSeriesManager, TimeSeriesError
14
+ from fameio.time import FameTime
18
15
 
19
16
 
20
- class ValidationException(Exception):
17
+ class ValidationError(Exception):
21
18
  """Indicates an error occurred during validation of any data with a connected schema"""
22
19
 
23
20
  pass
@@ -77,12 +74,12 @@ class SchemaValidator:
77
74
  return timeseries_manager
78
75
 
79
76
  @staticmethod
80
- def ensure_unique_agent_ids(agents: List[Agent]) -> None:
77
+ def ensure_unique_agent_ids(agents: list[Agent]) -> None:
81
78
  """Raises exception if any id for given `agents` is not unique"""
82
79
  list_of_ids = [agent.id for agent in agents]
83
80
  non_unique_ids = [agent_id for agent_id, count in Counter(list_of_ids).items() if count > 1]
84
81
  if non_unique_ids:
85
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_ID_NOT_UNIQUE.format(non_unique_ids)))
82
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_ID_NOT_UNIQUE.format(non_unique_ids)))
86
83
 
87
84
  @staticmethod
88
85
  def ensure_agent_and_timeseries_are_valid(agent: Agent, schema: Schema, timeseries_manager: TimeSeriesManager):
@@ -95,7 +92,7 @@ class SchemaValidator:
95
92
  def ensure_agent_type_in_schema(agent: Agent, schema: Schema) -> None:
96
93
  """Raises exception if type for given `agent` is not specified in given `schema`"""
97
94
  if agent.type_name not in schema.agent_types:
98
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_TYPE_UNKNOWN.format(agent.type_name)))
95
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_TYPE_UNKNOWN.format(agent.type_name)))
99
96
 
100
97
  @staticmethod
101
98
  def ensure_is_valid_agent(agent: Agent, schema: Schema) -> None:
@@ -112,10 +109,10 @@ class SchemaValidator:
112
109
  if name in schema.agent_types:
113
110
  return schema.agent_types[name]
114
111
  else:
115
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_TYPE_UNKNOWN.format(name)))
112
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_TYPE_UNKNOWN.format(name)))
116
113
 
117
114
  @staticmethod
118
- def _ensure_mandatory_present(attributes: Dict[str, Attribute], specifications: Dict[str, AttributeSpecs]) -> None:
115
+ def _ensure_mandatory_present(attributes: dict[str, Attribute], specifications: dict[str, AttributeSpecs]) -> None:
119
116
  """
120
117
  Raises Exception if in given list of `specifications` at least one item is mandatory,
121
118
  provides no defaults and is not contained in given `attributes` dictionary
@@ -125,7 +122,7 @@ class SchemaValidator:
125
122
  if specification.is_mandatory:
126
123
  if not specification.has_default_value:
127
124
  log_error_and_raise(
128
- ValidationException(SchemaValidator._ATTRIBUTE_MISSING.format(specification.full_name))
125
+ ValidationError(SchemaValidator._ATTRIBUTE_MISSING.format(specification.full_name))
129
126
  )
130
127
  else:
131
128
  if specification.has_default_value:
@@ -141,11 +138,11 @@ class SchemaValidator:
141
138
  SchemaValidator._ensure_mandatory_present(attribute.nested, specification.nested_attributes)
142
139
 
143
140
  @staticmethod
144
- def _ensure_attributes_exist(attributes: Dict[str, Attribute], specifications: Dict[str, AttributeSpecs]) -> None:
141
+ def _ensure_attributes_exist(attributes: dict[str, Attribute], specifications: dict[str, AttributeSpecs]) -> None:
145
142
  """Raises exception any entry of given `attributes` has no corresponding type `specification`"""
146
143
  for name, attribute in attributes.items():
147
144
  if name not in specifications:
148
- log_error_and_raise(ValidationException(SchemaValidator._ATTRIBUTE_UNKNOWN.format(attribute)))
145
+ log_error_and_raise(ValidationError(SchemaValidator._ATTRIBUTE_UNKNOWN.format(attribute)))
149
146
  if attribute.has_nested:
150
147
  specification = specifications[name]
151
148
  SchemaValidator._ensure_attributes_exist(attribute.nested, specification.nested_attributes)
@@ -156,7 +153,7 @@ class SchemaValidator:
156
153
 
157
154
  @staticmethod
158
155
  def _ensure_value_and_type_match(
159
- attributes: Dict[str, Attribute], specifications: Dict[str, AttributeSpecs]
156
+ attributes: dict[str, Attribute], specifications: dict[str, AttributeSpecs]
160
157
  ) -> None:
161
158
  """Raises exception if in given list of `attributes` its value does not match associated type `specification`"""
162
159
  for name, attribute in attributes.items():
@@ -166,10 +163,10 @@ class SchemaValidator:
166
163
  type_spec = specification.attr_type
167
164
  if not SchemaValidator._is_compatible(specification, value):
168
165
  message = SchemaValidator._INCOMPATIBLE.format(value, type_spec, specification.full_name)
169
- log_error_and_raise(ValidationException(message))
166
+ log_error_and_raise(ValidationError(message))
170
167
  if not SchemaValidator._is_allowed_value(specification, value):
171
168
  message = SchemaValidator._DISALLOWED.format(value, specification.full_name)
172
- log_error_and_raise(ValidationException(message))
169
+ log_error_and_raise(ValidationError(message))
173
170
  if attribute.has_nested:
174
171
  SchemaValidator._ensure_value_and_type_match(attribute.nested, specification.nested_attributes)
175
172
  if attribute.has_nested_list:
@@ -210,7 +207,7 @@ class SchemaValidator:
210
207
  elif attribute_type is AttributeType.TIME_SERIES:
211
208
  return isinstance(value, (str, int)) or (isinstance(value, float) and not math.isnan(value))
212
209
  else:
213
- log_error_and_raise(ValidationException(SchemaValidator._TYPE_NOT_IMPLEMENTED.format(attribute_type)))
210
+ log_error_and_raise(ValidationError(SchemaValidator._TYPE_NOT_IMPLEMENTED.format(attribute_type)))
214
211
 
215
212
  @staticmethod
216
213
  def _is_allowed_value(attribute: AttributeSpecs, value) -> bool:
@@ -239,7 +236,7 @@ class SchemaValidator:
239
236
 
240
237
  @staticmethod
241
238
  def _ensure_valid_timeseries(
242
- attributes: Dict[str, Attribute], specifications: Dict[str, AttributeSpecs], manager: TimeSeriesManager
239
+ attributes: dict[str, Attribute], specifications: dict[str, AttributeSpecs], manager: TimeSeriesManager
243
240
  ) -> None:
244
241
  """Recursively searches for time_series in agent attributes and registers them at given `manager`"""
245
242
  for name, attribute in attributes.items():
@@ -249,9 +246,9 @@ class SchemaValidator:
249
246
  if attribute_type is AttributeType.TIME_SERIES:
250
247
  try:
251
248
  manager.register_and_validate(attribute.value)
252
- except TimeSeriesException as e:
249
+ except TimeSeriesError as e:
253
250
  message = SchemaValidator._TIME_SERIES_INVALID.format(specification.full_name)
254
- log_error_and_raise(ValidationException(message, e))
251
+ log_error_and_raise(ValidationError(message, e))
255
252
  if attribute.has_nested:
256
253
  SchemaValidator._ensure_valid_timeseries(attribute.nested, specification.nested_attributes, manager)
257
254
  if attribute.has_nested_list:
@@ -259,7 +256,7 @@ class SchemaValidator:
259
256
  SchemaValidator._ensure_valid_timeseries(entry, specification.nested_attributes, manager)
260
257
 
261
258
  @staticmethod
262
- def ensure_string_set_consistency(agent: Agent, schema: Schema, string_sets: Dict[str, StringSet]) -> None:
259
+ def ensure_string_set_consistency(agent: Agent, schema: Schema, string_sets: dict[str, StringSet]) -> None:
263
260
  """
264
261
  Raises exception if
265
262
  a) an agent's attribute is of type StringSet but the corresponding StringSet is not defined in the scenario
@@ -271,7 +268,7 @@ class SchemaValidator:
271
268
 
272
269
  @staticmethod
273
270
  def _ensure_string_set_consistency(
274
- attributes: Dict[str, Attribute], specifications: Dict[str, AttributeSpecs], string_sets: Dict[str, StringSet]
271
+ attributes: dict[str, Attribute], specifications: dict[str, AttributeSpecs], string_sets: dict[str, StringSet]
275
272
  ) -> None:
276
273
  """
277
274
  Recursively iterates through all attributes of an agent, applying tests if attribute type is `StringSet`
@@ -290,10 +287,10 @@ class SchemaValidator:
290
287
  msg = SchemaValidator._MISSING_STRING_SET_ENTRY.format(
291
288
  attribute.value, str(attribute), name
292
289
  )
293
- log_error_and_raise(ValidationException(msg))
290
+ log_error_and_raise(ValidationError(msg))
294
291
  else:
295
292
  msg = SchemaValidator._MISSING_STRING_SET.format(specification.full_name)
296
- log_error_and_raise(ValidationException(msg))
293
+ log_error_and_raise(ValidationError(msg))
297
294
  if attribute.has_nested:
298
295
  SchemaValidator._ensure_string_set_consistency(
299
296
  attribute.nested, specification.nested_attributes, string_sets
@@ -303,20 +300,20 @@ class SchemaValidator:
303
300
  SchemaValidator._ensure_string_set_consistency(entry, specification.nested_attributes, string_sets)
304
301
 
305
302
  @staticmethod
306
- def ensure_is_valid_contract(contract: Contract, schema: Schema, agent_types_by_id: Dict[int, str]) -> None:
303
+ def ensure_is_valid_contract(contract: Contract, schema: Schema, agent_types_by_id: dict[int, str]) -> None:
307
304
  """Raises exception if given `contract` does not meet the `schema`'s requirements, using `agent_types_by_id`"""
308
305
  sender_id = contract.sender_id
309
306
  if sender_id not in agent_types_by_id:
310
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_MISSING.format(sender_id)))
307
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_MISSING.format(sender_id)))
311
308
  if contract.receiver_id not in agent_types_by_id:
312
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_MISSING.format(contract.receiver_id)))
309
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_MISSING.format(contract.receiver_id)))
313
310
  sender_type_name = agent_types_by_id[sender_id]
314
311
  if sender_type_name not in schema.agent_types:
315
- log_error_and_raise(ValidationException(SchemaValidator._AGENT_TYPE_UNKNOWN.format(sender_type_name)))
312
+ log_error_and_raise(ValidationError(SchemaValidator._AGENT_TYPE_UNKNOWN.format(sender_type_name)))
316
313
  sender_type = schema.agent_types[sender_type_name]
317
314
  product = contract.product_name
318
315
  if product not in sender_type.products:
319
- log_error_and_raise(ValidationException(SchemaValidator._PRODUCT_MISSING.format(product, sender_type_name)))
316
+ log_error_and_raise(ValidationError(SchemaValidator._PRODUCT_MISSING.format(product, sender_type_name)))
320
317
 
321
318
  @staticmethod
322
319
  def check_agents_have_contracts(scenario: Scenario) -> None:
@@ -1,36 +1,29 @@
1
1
  # SPDX-FileCopyrightText: 2024 German Aerospace Center <fame@dlr.de>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- import sys
5
4
  import importlib.metadata as metadata
5
+ import sys
6
6
  from pathlib import Path
7
- from typing import Any, Dict, List, Union
8
-
9
- from fameprotobuf.Contract_pb2 import ProtoContract
10
- from fameprotobuf.DataStorage_pb2 import DataStorage
11
- from fameprotobuf.ExecutionData_pb2 import ExecutionData
12
- from fameprotobuf.Field_pb2 import NestedField
13
- from fameprotobuf.InputFile_pb2 import InputData
14
- from fameprotobuf.Model_pb2 import ModelData
15
-
16
- from fameio.source.logs import log_error_and_raise, log
17
- from fameio.source.results.reader import Reader
18
- from fameio.source.scenario import (
19
- Agent,
20
- Attribute,
21
- Contract,
22
- GeneralProperties,
23
- Scenario,
24
- )
25
- from fameio.source.schema import Schema
26
- from fameio.source.schema.attribute import AttributeSpecs, AttributeType
27
- from fameio.source.schema.java_packages import JavaPackages
28
- from fameio.source.series import TimeSeriesManager
29
- from fameio.source.time import FameTime
30
- from fameio.source.tools import ensure_is_list
31
-
32
-
33
- class ProtoWriterException(Exception):
7
+ from typing import Any, Union
8
+
9
+ from fameprotobuf.contract_pb2 import ProtoContract
10
+ from fameprotobuf.data_storage_pb2 import DataStorage
11
+ from fameprotobuf.execution_data_pb2 import ExecutionData
12
+ from fameprotobuf.field_pb2 import NestedField
13
+ from fameprotobuf.input_file_pb2 import InputData
14
+ from fameprotobuf.model_pb2 import ModelData
15
+
16
+ import fameio
17
+ from fameio.input.scenario import Agent, Attribute, Contract, GeneralProperties, Scenario, StringSet
18
+ from fameio.input.schema import AttributeSpecs, AttributeType, JavaPackages, Schema
19
+ from fameio.logs import log_error_and_raise, log
20
+ from fameio.output.reader import Reader
21
+ from fameio.series import TimeSeriesManager
22
+ from fameio.time import FameTime
23
+ from fameio.tools import ensure_is_list
24
+
25
+
26
+ class ProtoWriterError(Exception):
34
27
  """Indicates an error during writing of protobuf file"""
35
28
 
36
29
  pass
@@ -39,7 +32,7 @@ class ProtoWriterException(Exception):
39
32
  class ProtoWriter:
40
33
  """Writes a given scenario to protobuf file"""
41
34
 
42
- _FAME_PROTOBUF_STREAM_HEADER = "famecoreprotobufstreamfilev001" # noqa
35
+ _FAME_PROTOBUF_STREAM_HEADER = fameio.FILE_HEADER_V2
43
36
 
44
37
  _TYPE_NOT_IMPLEMENTED = "AttributeType '{}' not implemented."
45
38
  _CONTRACT_UNSUPPORTED = (
@@ -72,43 +65,42 @@ class ProtoWriter:
72
65
  self._add_contracts(pb_input, scenario.contracts)
73
66
  self._set_time_series(pb_input)
74
67
  self._set_schema(pb_input, scenario.schema)
68
+ self._set_string_sets(pb_input, scenario.string_sets)
75
69
 
76
70
  self._set_java_package_names(pb_data_storage.model, scenario.schema.packages)
77
- self._set_execution_versions(pb_data_storage.execution.versions)
71
+ self._set_execution_versions(pb_data_storage.execution.version_data)
78
72
  return pb_data_storage
79
73
 
80
74
  @staticmethod
81
75
  def _set_general_properties(pb_input: InputData, general_properties: GeneralProperties) -> None:
82
76
  """Saves a scenario's general properties to specified protobuf `pb_input` container"""
83
77
  log().info("Adding General Properties")
84
- pb_input.runId = general_properties.run_id
85
- pb_input.simulation.startTime = general_properties.simulation_start_time
86
- pb_input.simulation.stopTime = general_properties.simulation_stop_time
87
- pb_input.simulation.randomSeed = general_properties.simulation_random_seed
88
- pb_input.output.interval = general_properties.output_interval
89
- pb_input.output.process = general_properties.output_process
90
-
91
- def _add_agents(self, pb_input: InputData, agents: List[Agent], schema: Schema) -> None:
78
+ pb_input.run_id = general_properties.run_id
79
+ pb_input.simulation.start_time = general_properties.simulation_start_time
80
+ pb_input.simulation.stop_time = general_properties.simulation_stop_time
81
+ pb_input.simulation.random_seed = general_properties.simulation_random_seed
82
+
83
+ def _add_agents(self, pb_input: InputData, agents: list[Agent], schema: Schema) -> None:
92
84
  """Triggers setting of `agents` to `pb_input`"""
93
85
  log().info("Adding Agents")
94
86
  for agent in agents:
95
- pb_agent = self._set_agent(pb_input.agent.add(), agent)
87
+ pb_agent = self._set_agent(pb_input.agents.add(), agent)
96
88
  attribute_specs = schema.agent_types[agent.type_name].attributes
97
89
  self._set_attributes(pb_agent, agent.attributes, attribute_specs)
98
- pb_agent.metadata = repr(agent.meta_data)
90
+ pb_agent.metadata = agent.get_metadata_string()
99
91
 
100
92
  @staticmethod
101
93
  def _set_agent(pb_agent: InputData.AgentDao, agent: Agent) -> InputData.AgentDao:
102
94
  """Saves type and id of given `agent` to protobuf `pb_agent` container. Returns given `pb_agent`"""
103
- pb_agent.className = agent.type_name
95
+ pb_agent.class_name = agent.type_name
104
96
  pb_agent.id = agent.id
105
97
  return pb_agent
106
98
 
107
99
  def _set_attributes(
108
100
  self,
109
101
  pb_parent: Union[InputData.AgentDao, NestedField],
110
- attributes: Dict[str, Attribute],
111
- specs: Dict[str, AttributeSpecs],
102
+ attributes: dict[str, Attribute],
103
+ specs: dict[str, AttributeSpecs],
112
104
  ) -> None:
113
105
  """Assigns `attributes` to protobuf fields of given `pb_parent` - cascades for nested Attributes"""
114
106
  values_not_set = [key for key in specs.keys()]
@@ -136,51 +128,51 @@ class ProtoWriter:
136
128
  @staticmethod
137
129
  def _add_field(pb_parent: Union[InputData.AgentDao, NestedField], name: str) -> NestedField:
138
130
  """Returns new field with given `name` that is added to given `pb_parent`"""
139
- pb_field = pb_parent.field.add()
140
- pb_field.fieldName = name
131
+ pb_field = pb_parent.fields.add()
132
+ pb_field.field_name = name
141
133
  return pb_field
142
134
 
143
135
  def _set_attribute(self, pb_field: NestedField, value: Any, attribute_type: AttributeType) -> None:
144
136
  """Sets given `value` to given protobuf `pb_field` depending on specified `attribute_type`"""
145
137
  if attribute_type is AttributeType.INTEGER:
146
- pb_field.intValue.extend(ensure_is_list(value))
138
+ pb_field.int_values.extend(ensure_is_list(value))
147
139
  elif attribute_type is AttributeType.DOUBLE:
148
- pb_field.doubleValue.extend(ensure_is_list(value))
140
+ pb_field.double_values.extend(ensure_is_list(value))
149
141
  elif attribute_type is AttributeType.LONG:
150
- pb_field.longValue.extend(ensure_is_list(value))
142
+ pb_field.long_values.extend(ensure_is_list(value))
151
143
  elif attribute_type is AttributeType.TIME_STAMP:
152
- pb_field.longValue.extend(ensure_is_list(FameTime.convert_string_if_is_datetime(value)))
144
+ pb_field.long_values.extend(ensure_is_list(FameTime.convert_string_if_is_datetime(value)))
153
145
  elif attribute_type in (AttributeType.ENUM, AttributeType.STRING, AttributeType.STRING_SET):
154
- pb_field.stringValue.extend(ensure_is_list(value))
146
+ pb_field.string_values.extend(ensure_is_list(value))
155
147
  elif attribute_type is AttributeType.TIME_SERIES:
156
- pb_field.seriesId = self._time_series_manager.get_series_id_by_identifier(value)
148
+ pb_field.series_id = self._time_series_manager.get_series_id_by_identifier(value)
157
149
  else:
158
- log_error_and_raise(ProtoWriterException(self._TYPE_NOT_IMPLEMENTED.format(attribute_type)))
150
+ log_error_and_raise(ProtoWriterError(self._TYPE_NOT_IMPLEMENTED.format(attribute_type)))
159
151
 
160
152
  @staticmethod
161
- def _add_contracts(pb_input: InputData, contracts: List[Contract]) -> None:
153
+ def _add_contracts(pb_input: InputData, contracts: list[Contract]) -> None:
162
154
  """Triggers setting of `contracts` to `pb_input`"""
163
155
  log().info("Adding Contracts")
164
156
  for contract in contracts:
165
- pb_contract = ProtoWriter._set_contract(pb_input.contract.add(), contract)
157
+ pb_contract = ProtoWriter._set_contract(pb_input.contracts.add(), contract)
166
158
  ProtoWriter._set_contract_attributes(pb_contract, contract.attributes)
167
- pb_contract.metadata = repr(contract.meta_data)
159
+ pb_contract.metadata = contract.get_metadata_string()
168
160
 
169
161
  @staticmethod
170
162
  def _set_contract(pb_contract: ProtoContract, contract: Contract) -> ProtoContract:
171
163
  """Saves given `contract` details to protobuf container `pb_contract`. Returns given `pb_contract`"""
172
- pb_contract.senderId = contract.sender_id
173
- pb_contract.receiverId = contract.receiver_id
174
- pb_contract.productName = contract.product_name
175
- pb_contract.firstDeliveryTime = contract.first_delivery_time
176
- pb_contract.deliveryIntervalInSteps = contract.delivery_interval
164
+ pb_contract.sender_id = contract.sender_id
165
+ pb_contract.receiver_id = contract.receiver_id
166
+ pb_contract.product_name = contract.product_name
167
+ pb_contract.first_delivery_time = contract.first_delivery_time
168
+ pb_contract.delivery_interval_in_steps = contract.delivery_interval
177
169
  if contract.expiration_time:
178
- pb_contract.expirationTime = contract.expiration_time
170
+ pb_contract.expiration_time = contract.expiration_time
179
171
  return pb_contract
180
172
 
181
173
  @staticmethod
182
174
  def _set_contract_attributes(
183
- pb_parent: Union[ProtoContract, NestedField], attributes: Dict[str, Attribute]
175
+ pb_parent: Union[ProtoContract, NestedField], attributes: dict[str, Attribute]
184
176
  ) -> None:
185
177
  """Assign (nested) Attributes to given protobuf container `pb_parent`"""
186
178
  for name, attribute in attributes.items():
@@ -190,13 +182,13 @@ class ProtoWriter:
190
182
  if attribute.has_value:
191
183
  value = attribute.value
192
184
  if isinstance(value, int):
193
- pb_field.intValue.extend([value])
185
+ pb_field.int_values.extend([value])
194
186
  elif isinstance(value, float):
195
- pb_field.doubleValue.extend([value])
187
+ pb_field.double_values.extend([value])
196
188
  elif isinstance(value, str):
197
- pb_field.stringValue.extend([value])
189
+ pb_field.string_values.extend([value])
198
190
  else:
199
- log_error_and_raise(ProtoWriterException(ProtoWriter._CONTRACT_UNSUPPORTED.format(str(attribute))))
191
+ log_error_and_raise(ProtoWriterError(ProtoWriter._CONTRACT_UNSUPPORTED.format(str(attribute))))
200
192
  elif attribute.has_nested:
201
193
  ProtoWriter._set_contract_attributes(pb_field, attribute.nested)
202
194
 
@@ -204,17 +196,11 @@ class ProtoWriter:
204
196
  """Adds all time series from TimeSeriesManager to given `pb_input`"""
205
197
  log().info("Adding TimeSeries")
206
198
  for unique_id, identifier, data in self._time_series_manager.get_all_series():
207
- pb_series = pb_input.timeSeries.add()
208
- pb_series.seriesId = unique_id
209
- pb_series.seriesName = identifier
210
- ProtoWriter._add_rows_to_series(pb_series, data)
211
-
212
- @staticmethod
213
- def _add_rows_to_series(series: InputData.TimeSeriesDao, data_frame) -> None:
214
- for key, value in data_frame.itertuples(index=False):
215
- row = series.row.add()
216
- row.timeStep = int(key)
217
- row.value = value
199
+ pb_series = pb_input.time_series.add()
200
+ pb_series.series_id = unique_id
201
+ pb_series.series_name = identifier
202
+ pb_series.time_steps.extend(list(data[0]))
203
+ pb_series.values.extend(list(data[1]))
218
204
 
219
205
  @staticmethod
220
206
  def _set_schema(pb_input: InputData, schema: Schema) -> None:
@@ -222,13 +208,27 @@ class ProtoWriter:
222
208
  log().info("Adding Schema")
223
209
  pb_input.schema = schema.to_string()
224
210
 
211
+ @staticmethod
212
+ def _set_string_sets(pb_input: InputData, string_sets: dict[str, StringSet]) -> None:
213
+ """Adds the given StringSets to given `pb_input`"""
214
+ for name, string_set in string_sets.items():
215
+ pb_set = pb_input.string_sets.add()
216
+ pb_set.name = name
217
+ for value, specification in string_set.values.items():
218
+ pb_value = pb_set.values.add()
219
+ pb_value.name = value
220
+ if specification.has_metadata():
221
+ pb_value.metadata = specification.get_metadata_string()
222
+ if string_set.has_metadata():
223
+ pb_set.metadata = string_set.get_metadata_string()
224
+
225
225
  @staticmethod
226
226
  def _set_java_package_names(pb_model: ModelData, java_packages: JavaPackages) -> None:
227
227
  """Adds given JavaPackages names to given ModelData section"""
228
- pb_packages = pb_model.packages
229
- pb_packages.agent.extend(java_packages.agents)
230
- pb_packages.dataItem.extend(java_packages.data_items)
231
- pb_packages.portable.extend(java_packages.portables)
228
+ pb_packages = pb_model.package_definition
229
+ pb_packages.agents.extend(java_packages.agents)
230
+ pb_packages.data_items.extend(java_packages.data_items)
231
+ pb_packages.portables.extend(java_packages.portables)
232
232
 
233
233
  def _write_protobuf_to_disk(self, pb_data_storage: DataStorage) -> None:
234
234
  """Writes given `protobuf_input_data` to disk"""
@@ -240,12 +240,12 @@ class ProtoWriter:
240
240
  file.write(len(serialised_data_storage).to_bytes(Reader.BYTES_DEFINING_MESSAGE_LENGTH, byteorder="big"))
241
241
  file.write(serialised_data_storage)
242
242
  except OSError as e:
243
- log_error_and_raise(ProtoWriterException(ProtoWriter._NO_FILE_SPECIFIED.format(self.file_path), e))
243
+ log_error_and_raise(ProtoWriterError(ProtoWriter._NO_FILE_SPECIFIED.format(self.file_path), e))
244
244
  log().info(self._INFO_WRITING_COMPLETED.format(self.file_path))
245
245
 
246
246
  @staticmethod
247
- def _set_execution_versions(pb_versions: ExecutionData.Versions) -> None:
247
+ def _set_execution_versions(pb_version_data: ExecutionData.VersionData) -> None:
248
248
  """Adds version strings for fameio, fameprotobuf, and python to the given Versions message"""
249
- pb_versions.fameProtobuf = metadata.version("fameprotobuf")
250
- pb_versions.fameIo = metadata.version("fameio")
251
- pb_versions.python = sys.version
249
+ pb_version_data.fame_protobuf = metadata.version("fameprotobuf")
250
+ pb_version_data.fame_io = metadata.version("fameio")
251
+ pb_version_data.python = sys.version
@@ -5,7 +5,7 @@
5
5
  import logging as pylog
6
6
  from enum import Enum
7
7
  from pathlib import Path
8
- from typing import NoReturn, Optional, List
8
+ from typing import Optional
9
9
 
10
10
 
11
11
  class LogLevel(Enum):
@@ -20,8 +20,8 @@ class LogLevel(Enum):
20
20
  DEBUG = pylog.DEBUG
21
21
 
22
22
 
23
- _loggers: List[pylog.Logger] = []
24
- _handlers: List[pylog.Handler] = []
23
+ _loggers: list[pylog.Logger] = []
24
+ _handlers: list[pylog.Handler] = []
25
25
 
26
26
  _FORMAT_NORMAL = "%(asctime)s — %(levelname)s — %(message)s" # noqa
27
27
  _FORMAT_DETAILLED = "%(asctime)s.%(msecs)03d — %(levelname)s — %(module)s:%(funcName)s:%(lineno)d — %(message)s" # noqa
@@ -42,14 +42,30 @@ def log() -> pylog.Logger:
42
42
  return _loggers[0]
43
43
 
44
44
 
45
- def log_and_raise_critical(message: str) -> NoReturn:
46
- """Raises a critical error and logs with given `error_message`"""
47
- log().critical(message)
48
- raise Exception(message)
45
+ def log_critical_and_raise(exception: Exception) -> None:
46
+ """
47
+ Raises the specified `exception` and logs a critical error with the exception's message
48
+
49
+ Args:
50
+ exception: to be raised and logged at level `critical`
51
+
52
+ Raises:
53
+ Exception: the given exception
54
+ """
55
+ log().critical(str(exception))
56
+ raise exception
49
57
 
50
58
 
51
- def log_error_and_raise(exception: Exception) -> NoReturn:
52
- """Raises the specified `exception` and logs an error with the same `message`"""
59
+ def log_error_and_raise(exception: Exception) -> None:
60
+ """
61
+ Raises the specified `exception` and logs a critical error with the exception's message
62
+
63
+ Args:
64
+ exception: to be raised and logged at level `error`
65
+
66
+ Raises:
67
+ Exception: the given exception
68
+ """
53
69
  log().error(str(exception))
54
70
  raise exception
55
71
 
@@ -1,10 +1,9 @@
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 typing import Union
4
5
 
5
- from typing import List, Dict, Set, Union, Tuple
6
-
7
- from fameprotobuf.Services_pb2 import Output
6
+ from fameprotobuf.services_pb2 import Output
8
7
 
9
8
 
10
9
  class AgentType:
@@ -13,42 +12,42 @@ class AgentType:
13
12
  def __init__(self, agent_type: Output.AgentType) -> None:
14
13
  self._agent_type = agent_type
15
14
 
16
- def get_simple_column_map(self) -> Dict[int, str]:
15
+ def get_simple_column_map(self) -> dict[int, str]:
17
16
  """Returns dictionary of simple column IDs mapped to their name - ignoring complex columns"""
18
- return {field.fieldId: field.fieldName for field in self._agent_type.field if len(field.indexName) == 0}
17
+ return {field.field_id: field.field_name for field in self._agent_type.fields if len(field.index_names) == 0}
19
18
 
20
- def get_merged_column_map(self) -> Dict[int, str]:
19
+ def get_merged_column_map(self) -> dict[int, str]:
21
20
  """Returns dictionary of all column IDs mapped to their name merged with names of inner complex columns"""
22
21
  column_names = {}
23
- for field in self._agent_type.field:
24
- if len(field.indexName) == 0:
25
- column_names[field.fieldId] = field.fieldName
22
+ for field in self._agent_type.fields:
23
+ if len(field.index_names) == 0:
24
+ column_names[field.field_id] = field.field_name
26
25
  else:
27
- column_names[field.fieldId] = f"{field.fieldName}_({tuple(field.indexName)}, value)"
26
+ column_names[field.field_id] = f"{field.field_name}_({tuple(field.index_names)}, value)"
28
27
  return column_names
29
28
 
30
- def get_simple_column_mask(self) -> List[bool]:
29
+ def get_simple_column_mask(self) -> list[bool]:
31
30
  """Returns list of bool - where an entry is True if the output column with the same index is not complex"""
32
- return [True if len(field.indexName) == 0 else False for field in self._agent_type.field]
31
+ return [True if len(field.index_names) == 0 else False for field in self._agent_type.fields]
33
32
 
34
- def get_complex_column_ids(self) -> Set[int]:
33
+ def get_complex_column_ids(self) -> set[int]:
35
34
  """Returns set of IDs for complex columns, ignoring simple columns"""
36
- return set([field.fieldId for field in self._agent_type.field if len(field.indexName) > 0])
35
+ return set([field.field_id for field in self._agent_type.fields if len(field.index_names) > 0])
37
36
 
38
37
  def get_column_name_for_id(self, column_index: int) -> Union[str, None]:
39
38
  """Returns name of column by given `column_index` or None, if column is not present"""
40
- if 0 <= column_index < len(self._agent_type.field):
41
- return self._agent_type.field[column_index].fieldName
39
+ if 0 <= column_index < len(self._agent_type.fields):
40
+ return self._agent_type.fields[column_index].field_name
42
41
  else:
43
42
  return None
44
43
 
45
- def get_inner_columns(self, column_index: int) -> Tuple[str]:
44
+ def get_inner_columns(self, column_index: int) -> tuple[str, ...]:
46
45
  """Returns tuple of inner column names for complex column with given `column_index`"""
47
- return tuple(self._agent_type.field[column_index].indexName)
46
+ return tuple(self._agent_type.fields[column_index].index_names)
48
47
 
49
48
  def get_class_name(self) -> str:
50
49
  """Returns name of class of wrapped agent type"""
51
- return self._agent_type.className
50
+ return self._agent_type.class_name
52
51
 
53
52
 
54
53
  class AgentTypeLog:
@@ -57,11 +56,11 @@ class AgentTypeLog:
57
56
  _ERR_AGENT_TYPE_MISSING = "Requested AgentType `{}` not found."
58
57
  _ERR_DOUBLE_DEFINITION = "Just one definition allowed per AgentType. Found multiple for {}. File might be corrupt."
59
58
 
60
- def __init__(self, requested_agents: List[str]) -> None:
59
+ def __init__(self, requested_agents: list[str]) -> None:
61
60
  self._requested_agents = [agent.upper() for agent in requested_agents] if requested_agents else None
62
61
  self._requested_agent_types = {}
63
62
 
64
- def update_agents(self, new_types: Dict[str, Output.AgentType]) -> None:
63
+ def update_agents(self, new_types: dict[str, Output.AgentType]) -> None:
65
64
  """Saves new `agent_types` (if any) contained in given `output` if requested for extraction"""
66
65
  if new_types:
67
66
  if self._requested_agents: