fameio 3.2.0__py3-none-any.whl → 3.4.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 (53) hide show
  1. fameio/cli/convert_results.py +4 -6
  2. fameio/cli/make_config.py +3 -5
  3. fameio/cli/options.py +6 -4
  4. fameio/cli/parser.py +53 -29
  5. fameio/cli/reformat.py +58 -0
  6. fameio/input/__init__.py +4 -4
  7. fameio/input/loader/__init__.py +4 -6
  8. fameio/input/loader/controller.py +11 -16
  9. fameio/input/loader/loader.py +11 -9
  10. fameio/input/metadata.py +26 -29
  11. fameio/input/resolver.py +4 -6
  12. fameio/input/scenario/agent.py +18 -16
  13. fameio/input/scenario/attribute.py +85 -31
  14. fameio/input/scenario/contract.py +78 -38
  15. fameio/input/scenario/exception.py +3 -6
  16. fameio/input/scenario/fameiofactory.py +7 -12
  17. fameio/input/scenario/generalproperties.py +7 -8
  18. fameio/input/scenario/scenario.py +14 -18
  19. fameio/input/scenario/stringset.py +5 -6
  20. fameio/input/schema/agenttype.py +8 -10
  21. fameio/input/schema/attribute.py +30 -36
  22. fameio/input/schema/java_packages.py +6 -7
  23. fameio/input/schema/schema.py +9 -11
  24. fameio/input/validator.py +178 -41
  25. fameio/input/writer.py +20 -29
  26. fameio/logs.py +28 -19
  27. fameio/output/agent_type.py +14 -16
  28. fameio/output/conversion.py +9 -12
  29. fameio/output/csv_writer.py +33 -23
  30. fameio/output/data_transformer.py +11 -11
  31. fameio/output/execution_dao.py +170 -0
  32. fameio/output/input_dao.py +16 -19
  33. fameio/output/output_dao.py +7 -7
  34. fameio/output/reader.py +8 -10
  35. fameio/output/yaml_writer.py +2 -3
  36. fameio/scripts/__init__.py +15 -4
  37. fameio/scripts/convert_results.py +18 -17
  38. fameio/scripts/exception.py +1 -1
  39. fameio/scripts/make_config.py +3 -4
  40. fameio/scripts/reformat.py +71 -0
  41. fameio/scripts/reformat.py.license +3 -0
  42. fameio/series.py +78 -47
  43. fameio/time.py +56 -18
  44. fameio/tools.py +42 -4
  45. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/METADATA +64 -40
  46. fameio-3.4.0.dist-info/RECORD +60 -0
  47. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/entry_points.txt +1 -0
  48. fameio-3.2.0.dist-info/RECORD +0 -56
  49. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/LICENSE.txt +0 -0
  50. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/LICENSES/Apache-2.0.txt +0 -0
  51. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/LICENSES/CC-BY-4.0.txt +0 -0
  52. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/LICENSES/CC0-1.0.txt +0 -0
  53. {fameio-3.2.0.dist-info → fameio-3.4.0.dist-info}/WHEEL +0 -0
@@ -10,20 +10,21 @@ from fameio.input.metadata import Metadata
10
10
  from fameio.input.scenario.attribute import Attribute
11
11
  from fameio.logs import log, log_error
12
12
  from fameio.time import FameTime, ConversionError
13
- from fameio.tools import ensure_is_list, keys_to_lower
13
+ from fameio.tools import keys_to_lower
14
14
 
15
15
 
16
16
  class Contract(Metadata):
17
- """Contract between two Agents of a scenario"""
17
+ """Contract between two Agents of a scenario."""
18
18
 
19
19
  class ContractError(InputError):
20
- """An error that occurred while parsing Contract definitions"""
20
+ """An error that occurred while parsing Contract definitions."""
21
21
 
22
22
  KEY_SENDER: Final[str] = "SenderId".lower()
23
23
  KEY_RECEIVER: Final[str] = "ReceiverId".lower()
24
24
  KEY_PRODUCT: Final[str] = "ProductName".lower()
25
25
  KEY_FIRST_DELIVERY: Final[str] = "FirstDeliveryTime".lower()
26
26
  KEY_INTERVAL: Final[str] = "DeliveryIntervalInSteps".lower()
27
+ KEY_EVERY: Final[str] = "Every".lower()
27
28
  KEY_EXPIRE: Final[str] = "ExpirationTime".lower()
28
29
  KEY_ATTRIBUTES: Final[str] = "Attributes".lower()
29
30
 
@@ -33,7 +34,8 @@ class Contract(Metadata):
33
34
  "or N-to-N sender-to-receiver numbers. Found M-to-N pairing in Contract with "
34
35
  "Senders: {} and Receivers: {}."
35
36
  )
36
- _ERR_INTERVAL_NOT_POSITIVE = "Contract delivery interval must be a positive integer but was: {}"
37
+ _ERR_XOR_KEYS = "Contract expects exactly one of the keys '{}' or '{}'. Found either both or none."
38
+ _ERR_INTERVAL_INVALID = "Contract delivery interval must be a positive integer but was: {}"
37
39
  _ERR_SENDER_IS_RECEIVER = "Contract sender and receiver have the same id: {}"
38
40
  _ERR_DOUBLE_ATTRIBUTE = "Cannot add attribute '{}' to contract because it already exists."
39
41
  _ERR_TIME_CONVERSION = "Contract item '{}' is an ill-formatted time: '{}'"
@@ -50,8 +52,7 @@ class Contract(Metadata):
50
52
  expiration_time: int | None = None,
51
53
  metadata: dict | None = None,
52
54
  ) -> None:
53
- """
54
- Constructs a new Contract
55
+ """Constructs a new Contract.
55
56
 
56
57
  Args:
57
58
  sender_id: unique id of sender
@@ -74,7 +75,7 @@ class Contract(Metadata):
74
75
  if sender_id == receiver_id:
75
76
  log().warning(self._ERR_SENDER_IS_RECEIVER.format(sender_id))
76
77
  if delivery_interval <= 0:
77
- raise log_error(self.ContractError(self._ERR_INTERVAL_NOT_POSITIVE.format(delivery_interval)))
78
+ raise log_error(self.ContractError(self._ERR_INTERVAL_INVALID.format(delivery_interval)))
78
79
  self._sender_id = sender_id
79
80
  self._receiver_id = receiver_id
80
81
  self._product_name = product_name
@@ -84,56 +85,55 @@ class Contract(Metadata):
84
85
  self._attributes: dict = {}
85
86
 
86
87
  def _notify_data_changed(self):
87
- """Placeholder method used to signal data changes to derived types"""
88
+ """Placeholder method used to signal data changes to derived types."""
88
89
 
89
90
  @property
90
91
  def product_name(self) -> str:
91
- """Returns the product name of the contract"""
92
+ """Returns the product name of the contract."""
92
93
  return self._product_name
93
94
 
94
95
  @property
95
96
  def sender_id(self) -> int:
96
- """Returns the sender ID of the contract"""
97
+ """Returns the sender ID of the contract."""
97
98
  return self._sender_id
98
99
 
99
100
  @property
100
101
  def display_sender_id(self) -> str:
101
- """Returns the sender ID of the contract as a string for display purposes"""
102
+ """Returns the sender ID of the contract as a string for display purposes."""
102
103
  return f"#{self._sender_id}"
103
104
 
104
105
  @property
105
106
  def receiver_id(self) -> int:
106
- """Returns the receiver ID of the contract"""
107
+ """Returns the receiver ID of the contract."""
107
108
  return self._receiver_id
108
109
 
109
110
  @property
110
111
  def display_receiver_id(self) -> str:
111
- """Returns the receiver ID of the contract as a string for display purposes"""
112
+ """Returns the receiver ID of the contract as a string for display purposes."""
112
113
  return f"#{self._receiver_id}"
113
114
 
114
115
  @property
115
116
  def delivery_interval(self) -> int:
116
- """Returns the delivery interval of the contract (in steps)"""
117
+ """Returns the delivery interval of the contract (in steps)."""
117
118
  return self._delivery_interval
118
119
 
119
120
  @property
120
121
  def first_delivery_time(self) -> int:
121
- """Returns the first delivery time of the contract"""
122
+ """Returns the first delivery time of the contract."""
122
123
  return self._first_delivery_time
123
124
 
124
125
  @property
125
126
  def expiration_time(self) -> int | None:
126
- """Returns the expiration time of the contract if available, None otherwise"""
127
+ """Returns the expiration time of the contract if available, None otherwise."""
127
128
  return self._expiration_time
128
129
 
129
130
  @property
130
131
  def attributes(self) -> dict[str, Attribute]:
131
- """Returns dictionary of all Attributes of the contract"""
132
+ """Returns dictionary of all Attributes of the contract."""
132
133
  return self._attributes
133
134
 
134
135
  def add_attribute(self, name: str, value: Attribute) -> None:
135
- """
136
- Adds a new attribute to the Contract
136
+ """Adds a new attribute to the Contract.
137
137
 
138
138
  Args:
139
139
  name: of the attribute
@@ -149,8 +149,7 @@ class Contract(Metadata):
149
149
 
150
150
  @classmethod
151
151
  def from_dict(cls, definitions: dict) -> Contract:
152
- """
153
- Parses contract from given `definitions`
152
+ """Parses contract from given `definitions`.
154
153
 
155
154
  Args:
156
155
  definitions: dictionary representation of a contract
@@ -167,7 +166,7 @@ class Contract(Metadata):
167
166
  product_name = Contract._get_or_raise(definitions, Contract.KEY_PRODUCT, Contract._ERR_MISSING_KEY)
168
167
 
169
168
  first_delivery_time = Contract._get_time(definitions, Contract.KEY_FIRST_DELIVERY)
170
- delivery_interval = Contract._get_or_raise(definitions, Contract.KEY_INTERVAL, Contract._ERR_MISSING_KEY)
169
+ delivery_interval = Contract._get_interval(definitions)
171
170
  expiration_time = Contract._get_time(definitions, Contract.KEY_EXPIRE, mandatory=False)
172
171
 
173
172
  contract = cls(sender_id, receiver_id, product_name, delivery_interval, first_delivery_time, expiration_time)
@@ -177,8 +176,7 @@ class Contract(Metadata):
177
176
 
178
177
  @staticmethod
179
178
  def _get_or_raise(dictionary: dict, key: str, error_message: str) -> Any:
180
- """
181
- Returns value associated with `key` in given `dictionary`, or raises exception if key or value is missing
179
+ """Returns value associated with `key` in given `dictionary`, or raises exception if key or value is missing.
182
180
 
183
181
  Args:
184
182
  dictionary: to search the key in
@@ -205,8 +203,7 @@ class Contract(Metadata):
205
203
 
206
204
  @staticmethod
207
205
  def _get_time(definitions: dict, key: str, mandatory: bool = True) -> int | None:
208
- """
209
- Extract time representation value at given key, and, if present, convert to integer, else return None
206
+ """Extract time representation value at given key, and, if present, convert to integer, else return None.
210
207
 
211
208
  Args:
212
209
  definitions: to search given key in
@@ -229,9 +226,45 @@ class Contract(Metadata):
229
226
  raise log_error(Contract.ContractError(Contract._ERR_MISSING_KEY.format(key)))
230
227
  return None
231
228
 
232
- def _init_attributes_from_dict(self, attributes: dict[str, Any]) -> None:
229
+ @staticmethod
230
+ def _get_interval(definitions: dict) -> int:
231
+ """Extract delivery interval from Contract definition, or raise an error if not present or ill formatted.
232
+
233
+ Args:
234
+ definitions: to extract the delivery interval from
235
+
236
+ Returns:
237
+ the delivery interval in fame time steps
238
+
239
+ Raises:
240
+ ContractError: if delivery interval is not defined or invalid, logged with level "ERROR"
233
241
  """
234
- Resets Contract `attributes` from dict
242
+ has_interval = Contract.KEY_INTERVAL in definitions
243
+ has_every = Contract.KEY_EVERY in definitions
244
+
245
+ if has_interval and not has_every:
246
+ value = definitions[Contract.KEY_INTERVAL]
247
+ if isinstance(value, int):
248
+ return value
249
+ raise log_error(Contract.ContractError(Contract._ERR_INTERVAL_INVALID.format(value)))
250
+ if has_every and not has_interval:
251
+ value = definitions[Contract.KEY_EVERY]
252
+ if isinstance(value, int):
253
+ return value
254
+ if isinstance(value, str):
255
+ try:
256
+ return FameTime.convert_text_to_time_span(value)
257
+ except ConversionError as e:
258
+ raise log_error(
259
+ Contract.ContractError(Contract._ERR_TIME_CONVERSION.format(Contract.KEY_EVERY, value))
260
+ ) from e
261
+ raise log_error(Contract.ContractError(Contract._ERR_TIME_CONVERSION.format(Contract.KEY_EVERY, value)))
262
+ raise log_error(
263
+ Contract.ContractError(Contract._ERR_XOR_KEYS.format(Contract.KEY_INTERVAL, Contract.KEY_EVERY))
264
+ )
265
+
266
+ def _init_attributes_from_dict(self, attributes: dict[str, Any]) -> None:
267
+ """Resets Contract `attributes` from dict.
235
268
 
236
269
  Args:
237
270
  attributes: key-value pairs of attributes to be set
@@ -244,7 +277,7 @@ class Contract(Metadata):
244
277
  self.add_attribute(name, Attribute(full_name, value))
245
278
 
246
279
  def _to_dict(self) -> dict:
247
- """Serializes the Contract content to a dict"""
280
+ """Serializes the Contract content to a dict."""
248
281
  result = {
249
282
  self.KEY_SENDER: self.sender_id,
250
283
  self.KEY_RECEIVER: self.receiver_id,
@@ -262,9 +295,10 @@ class Contract(Metadata):
262
295
 
263
296
  @staticmethod
264
297
  def split_contract_definitions(multi_definition: dict) -> list[dict]:
265
- """
298
+ """Split given M:N `multi_definition` of contracts to multiple 1:1 contracts.
299
+
266
300
  Splits given dictionary of contracts with potentially more than ore sender and/or receiver into a list
267
- of individual contract definitions with one sender and one receiver
301
+ of individual contract definitions with one sender and one receiver.
268
302
 
269
303
  Args:
270
304
  multi_definition: contract definitions with potentially more than ore sender and/or receiver
@@ -285,15 +319,14 @@ class Contract(Metadata):
285
319
  Contract.KEY_EXPIRE,
286
320
  Contract.KEY_METADATA,
287
321
  Contract.KEY_ATTRIBUTES,
322
+ Contract.KEY_EVERY,
288
323
  ]:
289
324
  if key in multi_definition:
290
325
  base_data[key] = multi_definition[key]
291
- senders = ensure_is_list(
292
- Contract._get_or_raise(multi_definition, Contract.KEY_SENDER, Contract._ERR_MISSING_KEY)
293
- )
294
- receivers = ensure_is_list(
295
- Contract._get_or_raise(multi_definition, Contract.KEY_RECEIVER, Contract._ERR_MISSING_KEY)
296
- )
326
+ sender_value = Contract._get_or_raise(multi_definition, Contract.KEY_SENDER, Contract._ERR_MISSING_KEY)
327
+ senders = Contract._unpack_list(sender_value)
328
+ receiver_value = Contract._get_or_raise(multi_definition, Contract.KEY_RECEIVER, Contract._ERR_MISSING_KEY)
329
+ receivers = Contract._unpack_list(receiver_value)
297
330
  if len(senders) > 1 and len(receivers) == 1:
298
331
  for index, sender in enumerate(senders):
299
332
  contracts.append(Contract._copy_contract(sender, receivers[0], base_data))
@@ -307,9 +340,16 @@ class Contract(Metadata):
307
340
  raise log_error(Contract.ContractError(Contract._ERR_MULTI_CONTRACT_CORRUPT.format(senders, receivers)))
308
341
  return contracts
309
342
 
343
+ @staticmethod
344
+ def _unpack_list(obj: Any | list) -> list[Any]:
345
+ """Returns the given value as a flat list - unpacks potential nested list(s)"""
346
+ if isinstance(obj, list):
347
+ return [item for element in obj for item in Contract._unpack_list(element)]
348
+ return [obj]
349
+
310
350
  @staticmethod
311
351
  def _copy_contract(sender: int, receiver: int, base_data: dict) -> dict:
312
- """Returns a new contract definition dictionary, with given `sender` and `receiver` and copied `base_data`"""
352
+ """Returns a new contract definition dictionary, with given `sender` and `receiver` and copied `base_data`."""
313
353
  contract = {
314
354
  Contract.KEY_SENDER: sender,
315
355
  Contract.KEY_RECEIVER: receiver,
@@ -12,8 +12,7 @@ _DEFAULT_USED = "Using default value '{}' for missing key '{}'"
12
12
 
13
13
 
14
14
  def log_scenario_error(message: str) -> ScenarioError:
15
- """
16
- Creates exception with given `message`, logs it on level "Error" and returns it
15
+ """Creates exception with given `message`, logs it on level "Error" and returns it.
17
16
 
18
17
  Args:
19
18
  message: to be logged and included in the exception if key is missing
@@ -27,8 +26,7 @@ def log_scenario_error(message: str) -> ScenarioError:
27
26
 
28
27
 
29
28
  def get_or_raise(dictionary: dict, key: str, error_message: str) -> Any:
30
- """
31
- Returns value associated with `key` in given `dictionary`, or raises exception if key or value is missing
29
+ """Returns value associated with `key` in given `dictionary`, or raises exception if key or value is missing.
32
30
 
33
31
  Args:
34
32
  dictionary: to search the key in
@@ -47,8 +45,7 @@ def get_or_raise(dictionary: dict, key: str, error_message: str) -> Any:
47
45
 
48
46
 
49
47
  def assert_or_raise(assertion: bool, error_message: str) -> None:
50
- """
51
- Raises exception with given `msg` if `assertion` is False
48
+ """Raises exception with given `error_message` if `assertion` is False.
52
49
 
53
50
  Args:
54
51
  assertion: expression that must be True, else an exception is raised
@@ -9,15 +9,14 @@ from .stringset import StringSet
9
9
 
10
10
 
11
11
  class FameIOFactory:
12
- """
13
- Factory used to instantiate the types defined in a scenario file.
12
+ """Factory used to instantiate the types defined in a scenario file.
13
+
14
14
  This allows a client to subclass some types in order to extend what a scenario can contain.
15
15
  """
16
16
 
17
17
  @staticmethod
18
18
  def new_schema_from_dict(definitions: dict) -> Schema:
19
- """
20
- Load given dictionary `definitions` into a new schema
19
+ """Loads given dictionary `definitions` into a new schema.
21
20
 
22
21
  Args:
23
22
  definitions: dictionary representation of schema
@@ -32,8 +31,7 @@ class FameIOFactory:
32
31
 
33
32
  @staticmethod
34
33
  def new_general_properties_from_dict(definitions: dict) -> GeneralProperties:
35
- """
36
- Parse general properties from provided `definitions`
34
+ """Parses general properties from provided `definitions`.
37
35
 
38
36
  Args:
39
37
  definitions: dictionary representation of general properties
@@ -48,8 +46,7 @@ class FameIOFactory:
48
46
 
49
47
  @staticmethod
50
48
  def new_agent_from_dict(definitions: dict) -> Agent:
51
- """
52
- Parses an agent from provided `definitions`
49
+ """Parses an agent from provided `definitions`.
53
50
 
54
51
  Args:
55
52
  definitions: dictionary representation of an agent
@@ -64,8 +61,7 @@ class FameIOFactory:
64
61
 
65
62
  @staticmethod
66
63
  def new_contract_from_dict(definitions: dict) -> Contract:
67
- """
68
- Parses contract from given `definitions`
64
+ """Parses contract from given `definitions`.
69
65
 
70
66
  Args:
71
67
  definitions: dictionary representation of a contract
@@ -80,8 +76,7 @@ class FameIOFactory:
80
76
 
81
77
  @staticmethod
82
78
  def new_string_set_from_dict(definition: StringSet.StringSetType) -> StringSet:
83
- """
84
- Returns string set initialised from `definition`
79
+ """Returns string set initialised from `definition`.
85
80
 
86
81
  Args:
87
82
  definition: dictionary representation of string set
@@ -12,7 +12,7 @@ from .exception import get_or_raise
12
12
 
13
13
 
14
14
  class GeneralProperties:
15
- """Hosts general properties of a scenario"""
15
+ """Hosts general properties of a scenario."""
16
16
 
17
17
  KEY_RUN: Final[str] = "RunId".lower()
18
18
  KEY_SIMULATION = "Simulation".lower()
@@ -39,8 +39,7 @@ class GeneralProperties:
39
39
 
40
40
  @classmethod
41
41
  def from_dict(cls, definitions: dict) -> GeneralProperties:
42
- """
43
- Parse general properties from provided `definitions`
42
+ """Parses general properties from provided `definitions`.
44
43
 
45
44
  Args:
46
45
  definitions: dictionary representation of general properties
@@ -79,7 +78,7 @@ class GeneralProperties:
79
78
  return cls(run_id, start_time, stop_time, random_seed)
80
79
 
81
80
  def to_dict(self) -> dict:
82
- """Serializes the general properties to a dict"""
81
+ """Serializes the general properties to a dict."""
83
82
  result: dict = {self.KEY_RUN: self._run_id}
84
83
  simulation_dict = {
85
84
  self.KEY_START: self.simulation_start_time,
@@ -91,20 +90,20 @@ class GeneralProperties:
91
90
 
92
91
  @property
93
92
  def run_id(self) -> int:
94
- """Returns the run ID"""
93
+ """Returns the run ID."""
95
94
  return self._run_id
96
95
 
97
96
  @property
98
97
  def simulation_start_time(self) -> int:
99
- """Returns the simulation start time"""
98
+ """Returns the simulation start time."""
100
99
  return self._simulation_start_time
101
100
 
102
101
  @property
103
102
  def simulation_stop_time(self) -> int:
104
- """Returns the simulation stop time"""
103
+ """Returns the simulation stop time."""
105
104
  return self._simulation_stop_time
106
105
 
107
106
  @property
108
107
  def simulation_random_seed(self) -> int:
109
- """Returns the simulation random seed"""
108
+ """Returns the simulation random seed."""
110
109
  return self._simulation_random_seed
@@ -18,7 +18,7 @@ from fameio.tools import keys_to_lower
18
18
 
19
19
 
20
20
  class Scenario(Metadata):
21
- """Definition of a scenario"""
21
+ """Definition of a scenario."""
22
22
 
23
23
  KEY_SCHEMA: Final[str] = "Schema".lower()
24
24
  KEY_GENERAL: Final[str] = "GeneralProperties".lower()
@@ -42,8 +42,7 @@ class Scenario(Metadata):
42
42
 
43
43
  @classmethod
44
44
  def from_dict(cls, definitions: dict, factory: FameIOFactory = FameIOFactory()) -> Scenario:
45
- """
46
- Parse scenario from provided `definitions` using given `factory`
45
+ """Parses scenario from provided `definitions` using given `factory`.
47
46
 
48
47
  Args:
49
48
  definitions: dictionary representation of scenario
@@ -73,8 +72,7 @@ class Scenario(Metadata):
73
72
 
74
73
  @staticmethod
75
74
  def _extract_schema(definitions: dict, factory: FameIOFactory) -> Schema:
76
- """
77
- Extract schema from given definitions and create Schema from it
75
+ """Extracts schema from given definitions and creates Schema from it.
78
76
 
79
77
  Args:
80
78
  definitions: dictionary representation of scenario
@@ -94,8 +92,7 @@ class Scenario(Metadata):
94
92
 
95
93
  @staticmethod
96
94
  def _extract_string_sets(definitions: dict, factory: FameIOFactory) -> dict[str, StringSet]:
97
- """
98
- Extract string sets from given definitions and create dictionary from it
95
+ """Extracts string sets from given definitions and creates dictionary from it.
99
96
 
100
97
  Args:
101
98
  definitions: dictionary representation of scenario
@@ -117,8 +114,7 @@ class Scenario(Metadata):
117
114
 
118
115
  @staticmethod
119
116
  def _extract_contracts(definitions: dict, factory: FameIOFactory) -> list[Contract]:
120
- """
121
- Extract contracts from given definitions
117
+ """Extracts contracts from given definitions.
122
118
 
123
119
  Args:
124
120
  definitions: dictionary representation of scenario
@@ -143,7 +139,7 @@ class Scenario(Metadata):
143
139
  return contracts
144
140
 
145
141
  def _to_dict(self) -> dict:
146
- """Serializes the scenario content to a dict"""
142
+ """Serializes the scenario content to a dict."""
147
143
  result: dict[str, Any] = {
148
144
  Scenario.KEY_GENERAL: self.general_properties.to_dict(),
149
145
  Scenario.KEY_SCHEMA: self.schema.to_dict(),
@@ -164,37 +160,37 @@ class Scenario(Metadata):
164
160
 
165
161
  @property
166
162
  def agents(self) -> list[Agent]:
167
- """Returns all the agents of this scenario as a list"""
163
+ """Returns all the agents of this scenario as a list."""
168
164
  return self._agents
169
165
 
170
166
  def add_agent(self, agent: Agent) -> None:
171
- """Adds a new agent to this scenario"""
167
+ """Adds a new agent to this scenario."""
172
168
  self._agents.append(agent)
173
169
 
174
170
  @property
175
171
  def contracts(self) -> list[Contract]:
176
- """Returns all the contracts of this scenario as a list"""
172
+ """Returns all the contracts of this scenario as a list."""
177
173
  return self._contracts
178
174
 
179
175
  def add_contract(self, contract: Contract) -> None:
180
- """Adds a new contract to this scenario"""
176
+ """Adds a new contract to this scenario."""
181
177
  self._contracts.append(contract)
182
178
 
183
179
  @property
184
180
  def schema(self) -> Schema:
185
- """Returns Schema associated with this scenario"""
181
+ """Returns Schema associated with this scenario."""
186
182
  return self._schema
187
183
 
188
184
  @property
189
185
  def general_properties(self) -> GeneralProperties:
190
- """Returns General properties of this scenario"""
186
+ """Returns General properties of this scenario."""
191
187
  return self._general_props
192
188
 
193
189
  @property
194
190
  def string_sets(self) -> dict[str, StringSet]:
195
- """Returns StringSets of this scenario"""
191
+ """Returns StringSets of this scenario."""
196
192
  return self._string_sets
197
193
 
198
194
  def add_string_set(self, name: str, string_set: StringSet) -> None:
199
- """Adds `string_set` with `name`"""
195
+ """Adds `string_set` with `name`."""
200
196
  self._string_sets[name] = string_set
@@ -12,10 +12,10 @@ from fameio.tools import keys_to_lower
12
12
 
13
13
 
14
14
  class StringSet(Metadata):
15
- """Hosts a StringSet in the given format"""
15
+ """Hosts a StringSet in the given format."""
16
16
 
17
17
  class StringSetError(InputError):
18
- """An error that occurred while parsing a StringSet definition"""
18
+ """An error that occurred while parsing a StringSet definition."""
19
19
 
20
20
  KEY_VALUES: Final[str] = "Values".lower()
21
21
 
@@ -31,8 +31,7 @@ class StringSet(Metadata):
31
31
 
32
32
  @classmethod
33
33
  def from_dict(cls, definition: StringSetType) -> StringSet:
34
- """
35
- Returns StringSet initialised from `definition`
34
+ """Returns StringSet initialised from `definition`.
36
35
 
37
36
  Args:
38
37
  definition: dictionary representation of string set
@@ -59,9 +58,9 @@ class StringSet(Metadata):
59
58
 
60
59
  @property
61
60
  def values(self) -> dict[str, MetadataComponent]:
62
- """Returns values and their associated MetadataComponent"""
61
+ """Returns values and their associated MetadataComponent."""
63
62
  return self._value_container.values
64
63
 
65
64
  def is_in_set(self, key: Any) -> bool:
66
- """Returns True if `key` is a valid name in this StringSet"""
65
+ """Returns True if `key` is a valid name in this StringSet."""
67
66
  return self._value_container.has_value(key)
@@ -13,7 +13,7 @@ from .attribute import AttributeSpecs
13
13
 
14
14
 
15
15
  class AgentType(Metadata):
16
- """Schema definitions for an Agent type"""
16
+ """Schema definitions for an Agent type."""
17
17
 
18
18
  KEY_ATTRIBUTES: Final[str] = "Attributes".lower()
19
19
  KEY_PRODUCTS: Final[str] = "Products".lower()
@@ -47,8 +47,7 @@ class AgentType(Metadata):
47
47
 
48
48
  @classmethod
49
49
  def from_dict(cls, name: str, definitions: dict) -> AgentType:
50
- """
51
- Creates AgentType with given `name` from specified dictionary
50
+ """Creates AgentType with given `name` from specified dictionary.
52
51
 
53
52
  Args:
54
53
  name: of the agent type
@@ -89,8 +88,7 @@ class AgentType(Metadata):
89
88
 
90
89
  @staticmethod
91
90
  def _read_values(section: str, agent_type: str, values: Any) -> ValueContainer:
92
- """
93
- Returns ValueContainer for `section` of in specifications of `agent_type` extracted from given `values`
91
+ """Returns ValueContainer for `section` in specifications of `agent_type` extracted from given `values`.
94
92
 
95
93
  Args:
96
94
  section: key of the section that contains the values
@@ -113,26 +111,26 @@ class AgentType(Metadata):
113
111
 
114
112
  @property
115
113
  def name(self) -> str:
116
- """Returns the agent type name"""
114
+ """Returns the agent type name."""
117
115
  return self._name
118
116
 
119
117
  @property
120
118
  def products(self) -> dict[str, MetadataComponent]:
121
- """Returns dict of products or an empty dict if no products are defined"""
119
+ """Returns dict of products or an empty dict if no products are defined."""
122
120
  return self._products.values
123
121
 
124
122
  def get_product_names(self) -> list[str]:
125
- """Returns list of product names or an empty list if no products are defined"""
123
+ """Returns list of product names or an empty list if no products are defined."""
126
124
  return self._products.as_list()
127
125
 
128
126
  @property
129
127
  def attributes(self) -> dict[str, AttributeSpecs]:
130
- """Returns list of Attributes of this agent or an empty list if no attributes are defined"""
128
+ """Returns list of Attributes of this agent or an empty list if no attributes are defined."""
131
129
  return self._attributes
132
130
 
133
131
  @property
134
132
  def outputs(self) -> dict[str, MetadataComponent]:
135
- """Returns list of outputs or an empty list if no outputs are defined"""
133
+ """Returns list of outputs or an empty list if no outputs are defined."""
136
134
  return self._outputs.values
137
135
 
138
136
  def _to_dict(self) -> dict: