nost-tools 2.0.0__py3-none-any.whl → 2.0.2__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.

Potentially problematic release.


This version of nost-tools might be problematic. Click here for more details.

nost_tools/schemas.py CHANGED
@@ -1,426 +1,458 @@
1
- """
2
- Provides object models for common data structures.
3
- """
4
-
5
- from datetime import datetime, timedelta
6
- from typing import Dict, List, Optional
7
-
8
- from pydantic import BaseModel, Field, model_validator
9
-
10
- from .simulator import Mode
11
-
12
-
13
- class InitTaskingParameters(BaseModel):
14
- """
15
- Tasking parameters to initialize an execution.
16
- """
17
-
18
- sim_start_time: datetime = Field(
19
- ..., description="Earliest possible scenario start time.", alias="simStartTime"
20
- )
21
- sim_stop_time: datetime = Field(
22
- ..., description="Latest possible scenario end time.", alias="simStopTime"
23
- )
24
- required_apps: List[str] = Field(
25
- [], description="List of required applications.", alias="requiredApps"
26
- )
27
-
28
-
29
- class InitCommand(BaseModel):
30
- """
31
- Command message to initialize an execution.
32
- """
33
-
34
- tasking_parameters: InitTaskingParameters = Field(
35
- ...,
36
- description="Tasking parameters for the initialize command.",
37
- alias="taskingParameters",
38
- )
39
-
40
-
41
- class StartTaskingParameters(BaseModel):
42
- """
43
- Tasking parameters to start an execution.
44
- """
45
-
46
- start_time: Optional[datetime] = Field(
47
- None,
48
- description="Wallclock time at which to start execution.",
49
- alias="startTime",
50
- )
51
- sim_start_time: Optional[datetime] = Field(
52
- None,
53
- description="Scenario time at which to start execution.",
54
- alias="simStartTime",
55
- )
56
- sim_stop_time: Optional[datetime] = Field(
57
- None,
58
- description="Scenario time at which to stop execution.",
59
- alias="simStopTime",
60
- )
61
- time_scaling_factor: float = Field(
62
- 1.0,
63
- gt=0,
64
- description="Scenario seconds per wallclock second.",
65
- alias="timeScalingFactor",
66
- )
67
-
68
-
69
- class StartCommand(BaseModel):
70
- """
71
- Command message to start an execution.
72
- """
73
-
74
- tasking_parameters: StartTaskingParameters = Field(
75
- ...,
76
- description="Tasking parameters for the start command.",
77
- alias="taskingParameters",
78
- )
79
-
80
-
81
- class StopTaskingParameters(BaseModel):
82
- """
83
- Tasking parameters to stop an execution.
84
- """
85
-
86
- sim_stop_time: datetime = Field(
87
- ...,
88
- description="Scenario time at which to stop execution.",
89
- alias="simStopTime",
90
- )
91
-
92
-
93
- class StopCommand(BaseModel):
94
- """
95
- Command message to stop an execution.
96
- """
97
-
98
- tasking_parameters: StopTaskingParameters = Field(
99
- ...,
100
- description="Tasking parameters for the stop command.",
101
- alias="taskingParameters",
102
- )
103
-
104
-
105
- class UpdateTaskingParameters(BaseModel):
106
- """
107
- Tasking parameters to update an execution.
108
- """
109
-
110
- time_scaling_factor: float = Field(
111
- ...,
112
- gt=0,
113
- description="Time scaling factor (scenario seconds per wallclock second).",
114
- alias="timeScalingFactor",
115
- )
116
- sim_update_time: datetime = Field(
117
- ...,
118
- description="Scenario time at which to update the time scaling factor.",
119
- alias="simUpdateTime",
120
- )
121
-
122
-
123
- class UpdateCommand(BaseModel):
124
- """
125
- Command message to update an execution.
126
- """
127
-
128
- tasking_parameters: UpdateTaskingParameters = Field(
129
- ...,
130
- description="Tasking parameters for the stop command.",
131
- alias="taskingParameters",
132
- )
133
-
134
-
135
- class TimeStatusProperties(BaseModel):
136
- """
137
- Properties to report time status.
138
- """
139
-
140
- sim_time: datetime = Field(
141
- ..., description="Current scenario time.", alias="simTime"
142
- )
143
- time: datetime = Field(..., description="Current wallclock time.")
144
-
145
-
146
- class TimeStatus(BaseModel):
147
- """
148
- Message to report time status.
149
- """
150
-
151
- name: str = Field(
152
- ..., description="Name of the application providing a time status."
153
- )
154
- description: Optional[str] = Field(
155
- None, description="Description of the application providing a ready status."
156
- )
157
- properties: TimeStatusProperties = Field(
158
- ..., description="Properties for the time status."
159
- )
160
-
161
-
162
- class ModeStatusProperties(BaseModel):
163
- """
164
- Properties to report mode status.
165
- """
166
-
167
- mode: Mode = Field(..., description="Current execution mode.")
168
-
169
-
170
- class ModeStatus(BaseModel):
171
- """
172
- Message to report mode status.
173
- """
174
-
175
- name: str = Field(
176
- ..., description="Name of the application providing a mode status."
177
- )
178
- description: Optional[str] = Field(
179
- None, description="Description of the application providing a ready status."
180
- )
181
- properties: ModeStatusProperties = Field(
182
- ..., description="Properties for the mode status."
183
- )
184
-
185
-
186
- class ReadyStatusProperties(BaseModel):
187
- """
188
- Properties to report ready status.
189
- """
190
-
191
- ready: bool = Field(True, description="True, if this application is ready.")
192
-
193
-
194
- class ReadyStatus(BaseModel):
195
- """
196
- Message to report ready status.
197
- """
198
-
199
- name: str = Field(
200
- ..., description="Name of the application providing a ready status."
201
- )
202
- description: Optional[str] = Field(
203
- None, description="Description of the application providing a ready status."
204
- )
205
- properties: ReadyStatusProperties = Field(
206
- ..., description="Properties for the ready status."
207
- )
208
-
209
-
210
- class InfoConfig(BaseModel):
211
- title: Optional[str] = Field(None, description="Title of the simulation.")
212
- version: Optional[str] = Field(None, description="Version of the simulation.")
213
- description: Optional[str] = Field(
214
- None, description="Description of the simulation."
215
- )
216
-
217
-
218
- class RabbitMQConfig(BaseModel):
219
- keycloak_authentication: bool = Field(
220
- False, description="Keycloak authentication for RabbitMQ."
221
- )
222
- host: str = Field("localhost", description="RabbitMQ host.")
223
- port: int = Field(5672, description="RabbitMQ port.")
224
- tls: bool = Field(False, description="RabbitMQ TLS/SSL.")
225
- virtual_host: str = Field("/", description="RabbitMQ virtual host.")
226
- message_expiration: str = Field(
227
- "60000", description="RabbitMQ expiration, in milliseconds."
228
- )
229
- delivery_mode: int = Field(
230
- 2, description="RabbitMQ delivery mode (1: non-persistent, 2: durable)."
231
- )
232
- content_type: str = Field(
233
- "text/plain",
234
- description="RabbitMQ MIME content type (application/json, text/plain, etc.).",
235
- )
236
- heartbeat: int = Field(30, description="RabbitMQ heartbeat interval, in seconds.")
237
- connection_attempts: int = Field(
238
- 3, description="RabbitMQ connection attempts before giving up."
239
- )
240
- retry_delay: int = Field(5, description="RabbitMQ retry delay, in seconds.")
241
-
242
-
243
- class KeycloakConfig(BaseModel):
244
- host: str = Field("localhost", description="Keycloak host.")
245
- port: int = Field(8080, description="Keycloak port.")
246
- realm: str = Field("master", description="Keycloak realm.")
247
- tls: bool = Field(False, description="Keycloak TLS/SSL.")
248
- token_refresh_interval: int = Field(
249
- 60, description="Keycloak token refresh interval, in seconds."
250
- )
251
-
252
-
253
- class ServersConfig(BaseModel):
254
- rabbitmq: RabbitMQConfig = Field(..., description="RabbitMQ configuration.")
255
- keycloak: KeycloakConfig = Field(..., description="Keycloak configuration.")
256
-
257
-
258
- class GeneralConfig(BaseModel):
259
- prefix: str = Field("nost", description="Execution prefix.")
260
-
261
-
262
- class ManagerConfig(BaseModel):
263
- sim_start_time: Optional[datetime] = Field(
264
- None, description="Simulation start time."
265
- )
266
- sim_stop_time: Optional[datetime] = Field(None, description="Simulation stop time.")
267
- start_time: Optional[datetime] = Field(None, description="Execution start time.")
268
- time_step: timedelta = Field(
269
- timedelta(seconds=1),
270
- description="Time step for the simulation.",
271
- )
272
- time_scale_factor: float = Field(1.0, description="Time scale factor.")
273
- time_scale_updates: List[str] = Field(
274
- default_factory=list, description="List of time scale updates."
275
- )
276
- time_status_step: Optional[timedelta] = Field(None, description="Time status step.")
277
- time_status_init: Optional[datetime] = Field(None, description="Time status init.")
278
- command_lead: timedelta = Field(
279
- timedelta(seconds=0), description="Command lead time."
280
- )
281
- required_apps: List[str] = Field(
282
- default_factory=list, description="List of required applications."
283
- )
284
- init_retry_delay_s: int = Field(5, description="Initial retry delay in seconds.")
285
- init_max_retry: int = Field(5, description="Initial maximum retry attempts.")
286
- set_offset: bool = Field(True, description="Set offset.")
287
- shut_down_when_terminated: bool = Field(
288
- False, description="Shut down when terminated."
289
- )
290
-
291
- @model_validator(mode="before")
292
- def scale_time(cls, values):
293
- time_scale_factor = values.get("time_scale_factor", 1.0)
294
-
295
- if "time_status_step" in values:
296
- time_status_step = values["time_status_step"]
297
- if isinstance(time_status_step, str):
298
- time_status_step = timedelta(
299
- seconds=float(time_status_step.split(":")[-1])
300
- )
301
- if isinstance(time_status_step, timedelta):
302
- values["time_status_step"] = timedelta(
303
- seconds=time_status_step.total_seconds() * time_scale_factor
304
- )
305
-
306
- return values
307
-
308
-
309
- class ManagedApplicationConfig(BaseModel):
310
- time_scale_factor: float = Field(1.0, description="Time scale factor.")
311
- time_step: timedelta = Field(
312
- timedelta(seconds=1), description="Time step for swe_change."
313
- )
314
- set_offset: bool = Field(True, description="Set offset.")
315
- time_status_step: timedelta = Field(None, description="Time status step.")
316
- time_status_init: datetime = Field(None, description="Time status init.")
317
- shut_down_when_terminated: bool = Field(
318
- False, description="Shut down when terminated."
319
- )
320
- manager_app_name: str = Field("manager", description="Manager application name.")
321
-
322
- @model_validator(mode="before")
323
- def scale_time(cls, values):
324
- time_scale_factor = values.get("time_scale_factor", 1.0)
325
-
326
- if "time_step" in values:
327
- time_step = values["time_step"]
328
- if isinstance(time_step, str):
329
- time_step = timedelta(seconds=float(time_step.split(":")[-1]))
330
- if isinstance(time_step, timedelta):
331
- values["time_step"] = timedelta(
332
- seconds=time_step.total_seconds() * time_scale_factor
333
- )
334
-
335
- if "time_status_step" in values:
336
- time_status_step = values["time_status_step"]
337
- if isinstance(time_status_step, str):
338
- time_status_step = timedelta(
339
- seconds=float(time_status_step.split(":")[-1])
340
- )
341
- if isinstance(time_status_step, timedelta):
342
- values["time_status_step"] = timedelta(
343
- seconds=time_status_step.total_seconds() * time_scale_factor
344
- )
345
-
346
- return values
347
-
348
-
349
- class LoggerApplicationConfig(BaseModel):
350
- set_offset: Optional[bool] = Field(True, description="Set offset.")
351
- time_scale_factor: Optional[float] = Field(1.0, description="Time scale factor.")
352
- time_step: Optional[timedelta] = Field(
353
- timedelta(seconds=1), description="Time step for swe_change."
354
- )
355
- time_status_step: Optional[timedelta] = Field(
356
- timedelta(seconds=10), description="Time status step."
357
- )
358
- time_status_init: Optional[datetime] = Field(
359
- datetime(2019, 3, 1, 0, 0, 0), description="Time status init."
360
- )
361
- shut_down_when_terminated: Optional[bool] = Field(
362
- False, description="Shut down when terminated."
363
- )
364
- manager_app_name: Optional[str] = Field(
365
- "manager", description="Manager application name."
366
- )
367
-
368
-
369
- class ExecConfig(BaseModel):
370
- general: GeneralConfig
371
- manager: ManagerConfig
372
- managed_application: ManagedApplicationConfig
373
- logger_application: LoggerApplicationConfig
374
-
375
-
376
- class Config(BaseModel):
377
- servers: ServersConfig = Field(..., description="Servers configuration.")
378
- channels: Dict[str, Dict] = Field({}, description="Channels configuration.")
379
- execution: ExecConfig = Field(..., description="Applications configuration.")
380
-
381
-
382
- class ExchangeConfig(BaseModel):
383
- name: str
384
- type: str = "topic"
385
- durable: bool = True
386
- auto_delete: bool = False
387
- vhost: str = "/"
388
-
389
-
390
- class ChannelConfig(BaseModel):
391
- app: str
392
- address: str
393
- exchange: str
394
- durable: bool
395
- auto_delete: bool
396
- vhost: str
397
-
398
-
399
- class Credentials(BaseModel):
400
- username: str = Field(..., description="Username for authentication.")
401
- password: str = Field(..., description="Password for authentication.")
402
- client_id: Optional[str] = Field("", description="Client ID for authentication.")
403
- client_secret_key: Optional[str] = Field(
404
- "", description="Client secret key for authentication."
405
- )
406
-
407
-
408
- class SimulationConfig(BaseModel):
409
- exchanges: Dict[str, Dict] = Field(
410
- default_factory=dict, description="Dictionary of exchanges."
411
- )
412
- queues: List[Dict] = Field(default_factory=list, description="List of channels.")
413
- execution_parameters: ExecConfig = Field(..., description="Execution parameters.")
414
- predefined_exchanges_queues: bool = Field(
415
- False, description="Predefined exchanges and queues."
416
- )
417
-
418
-
419
- class RuntimeConfig(BaseModel):
420
- credentials: Credentials = Field(..., description="Credentials for authentication.")
421
- server_configuration: Config = (
422
- Field(..., description="Simulation configuration."),
423
- )
424
- simulation_configuration: SimulationConfig = Field(
425
- ..., description="Simulation configuration."
426
- )
1
+ """
2
+ Provides object models for common data structures.
3
+ """
4
+
5
+ from datetime import datetime, timedelta
6
+ from typing import Dict, List, Optional
7
+
8
+ from pydantic import BaseModel, Field, model_validator
9
+
10
+ from .simulator import Mode
11
+
12
+
13
+ class InitTaskingParameters(BaseModel):
14
+ """
15
+ Tasking parameters to initialize an execution.
16
+ """
17
+
18
+ sim_start_time: datetime = Field(
19
+ ..., description="Earliest possible scenario start time.", alias="simStartTime"
20
+ )
21
+ sim_stop_time: datetime = Field(
22
+ ..., description="Latest possible scenario end time.", alias="simStopTime"
23
+ )
24
+ required_apps: List[str] = Field(
25
+ [], description="List of required applications.", alias="requiredApps"
26
+ )
27
+
28
+
29
+ class InitCommand(BaseModel):
30
+ """
31
+ Command message to initialize an execution.
32
+ """
33
+
34
+ tasking_parameters: InitTaskingParameters = Field(
35
+ ...,
36
+ description="Tasking parameters for the initialize command.",
37
+ alias="taskingParameters",
38
+ )
39
+
40
+
41
+ class StartTaskingParameters(BaseModel):
42
+ """
43
+ Tasking parameters to start an execution.
44
+ """
45
+
46
+ start_time: Optional[datetime] = Field(
47
+ None,
48
+ description="Wallclock time at which to start execution.",
49
+ alias="startTime",
50
+ )
51
+ sim_start_time: Optional[datetime] = Field(
52
+ None,
53
+ description="Scenario time at which to start execution.",
54
+ alias="simStartTime",
55
+ )
56
+ sim_stop_time: Optional[datetime] = Field(
57
+ None,
58
+ description="Scenario time at which to stop execution.",
59
+ alias="simStopTime",
60
+ )
61
+ time_scaling_factor: float = Field(
62
+ 1.0,
63
+ gt=0,
64
+ description="Scenario seconds per wallclock second.",
65
+ alias="timeScalingFactor",
66
+ )
67
+
68
+
69
+ class StartCommand(BaseModel):
70
+ """
71
+ Command message to start an execution.
72
+ """
73
+
74
+ tasking_parameters: StartTaskingParameters = Field(
75
+ ...,
76
+ description="Tasking parameters for the start command.",
77
+ alias="taskingParameters",
78
+ )
79
+
80
+
81
+ class StopTaskingParameters(BaseModel):
82
+ """
83
+ Tasking parameters to stop an execution.
84
+ """
85
+
86
+ sim_stop_time: datetime = Field(
87
+ ...,
88
+ description="Scenario time at which to stop execution.",
89
+ alias="simStopTime",
90
+ )
91
+
92
+
93
+ class StopCommand(BaseModel):
94
+ """
95
+ Command message to stop an execution.
96
+ """
97
+
98
+ tasking_parameters: StopTaskingParameters = Field(
99
+ ...,
100
+ description="Tasking parameters for the stop command.",
101
+ alias="taskingParameters",
102
+ )
103
+
104
+
105
+ class UpdateTaskingParameters(BaseModel):
106
+ """
107
+ Tasking parameters to update an execution.
108
+ """
109
+
110
+ time_scaling_factor: float = Field(
111
+ ...,
112
+ gt=0,
113
+ description="Time scaling factor (scenario seconds per wallclock second).",
114
+ alias="timeScalingFactor",
115
+ )
116
+ sim_update_time: datetime = Field(
117
+ ...,
118
+ description="Scenario time at which to update the time scaling factor.",
119
+ alias="simUpdateTime",
120
+ )
121
+
122
+
123
+ class UpdateCommand(BaseModel):
124
+ """
125
+ Command message to update an execution.
126
+ """
127
+
128
+ tasking_parameters: UpdateTaskingParameters = Field(
129
+ ...,
130
+ description="Tasking parameters for the stop command.",
131
+ alias="taskingParameters",
132
+ )
133
+
134
+
135
+ class TimeStatusProperties(BaseModel):
136
+ """
137
+ Properties to report time status.
138
+ """
139
+
140
+ sim_time: datetime = Field(
141
+ ..., description="Current scenario time.", alias="simTime"
142
+ )
143
+ time: datetime = Field(..., description="Current wallclock time.")
144
+
145
+
146
+ class TimeStatus(BaseModel):
147
+ """
148
+ Message to report time status.
149
+ """
150
+
151
+ name: str = Field(
152
+ ..., description="Name of the application providing a time status."
153
+ )
154
+ description: Optional[str] = Field(
155
+ None, description="Description of the application providing a ready status."
156
+ )
157
+ properties: TimeStatusProperties = Field(
158
+ ..., description="Properties for the time status."
159
+ )
160
+
161
+
162
+ class ModeStatusProperties(BaseModel):
163
+ """
164
+ Properties to report mode status.
165
+ """
166
+
167
+ mode: Mode = Field(..., description="Current execution mode.")
168
+
169
+
170
+ class ModeStatus(BaseModel):
171
+ """
172
+ Message to report mode status.
173
+ """
174
+
175
+ name: str = Field(
176
+ ..., description="Name of the application providing a mode status."
177
+ )
178
+ description: Optional[str] = Field(
179
+ None, description="Description of the application providing a ready status."
180
+ )
181
+ properties: ModeStatusProperties = Field(
182
+ ..., description="Properties for the mode status."
183
+ )
184
+
185
+
186
+ class ReadyStatusProperties(BaseModel):
187
+ """
188
+ Properties to report ready status.
189
+ """
190
+
191
+ ready: bool = Field(True, description="True, if this application is ready.")
192
+
193
+
194
+ class ReadyStatus(BaseModel):
195
+ """
196
+ Message to report ready status.
197
+ """
198
+
199
+ name: str = Field(
200
+ ..., description="Name of the application providing a ready status."
201
+ )
202
+ description: Optional[str] = Field(
203
+ None, description="Description of the application providing a ready status."
204
+ )
205
+ properties: ReadyStatusProperties = Field(
206
+ ..., description="Properties for the ready status."
207
+ )
208
+
209
+
210
+ class InfoConfig(BaseModel):
211
+ title: Optional[str] = Field(None, description="Title of the simulation.")
212
+ version: Optional[str] = Field(None, description="Version of the simulation.")
213
+ description: Optional[str] = Field(
214
+ None, description="Description of the simulation."
215
+ )
216
+
217
+
218
+ class RabbitMQConfig(BaseModel):
219
+ keycloak_authentication: bool = Field(
220
+ False, description="Keycloak authentication for RabbitMQ."
221
+ )
222
+ host: str = Field("localhost", description="RabbitMQ host.")
223
+ port: int = Field(5672, description="RabbitMQ port.")
224
+ tls: bool = Field(False, description="RabbitMQ TLS/SSL.")
225
+ virtual_host: str = Field("/", description="RabbitMQ virtual host.")
226
+ message_expiration: str = Field(
227
+ None, description="RabbitMQ expiration, in milliseconds."
228
+ )
229
+ delivery_mode: int = Field(
230
+ None, description="RabbitMQ delivery mode (1: non-persistent, 2: durable)."
231
+ )
232
+ content_type: str = Field(
233
+ None,
234
+ description="RabbitMQ MIME content type (application/json, text/plain, etc.).",
235
+ )
236
+ heartbeat: int = Field(None, description="RabbitMQ heartbeat interval, in seconds.")
237
+ connection_attempts: int = Field(
238
+ 1, description="RabbitMQ connection attempts before giving up."
239
+ )
240
+ retry_delay: int = Field(2, description="RabbitMQ retry delay, in seconds.")
241
+ socket_timeout: int = Field(10, description="RabbitMQ socket timeout, in seconds.")
242
+ stack_timeout: int = Field(15, description="RabbitMQ stack timeout, in seconds.")
243
+ locale: str = Field("en_US", description="RabbitMQ locale.")
244
+ blocked_connection_timeout: int = Field(
245
+ None, description="Timeout for blocked connections."
246
+ )
247
+ reconnect_delay: int = Field(10, description="Reconnect delay, in seconds.")
248
+
249
+
250
+ class KeycloakConfig(BaseModel):
251
+ host: str = Field("localhost", description="Keycloak host.")
252
+ port: int = Field(8080, description="Keycloak port.")
253
+ realm: str = Field("master", description="Keycloak realm.")
254
+ tls: bool = Field(False, description="Keycloak TLS/SSL.")
255
+ token_refresh_interval: int = Field(
256
+ 60, description="Keycloak token refresh interval, in seconds."
257
+ )
258
+
259
+
260
+ class ServersConfig(BaseModel):
261
+ rabbitmq: RabbitMQConfig = Field(..., description="RabbitMQ configuration.")
262
+ keycloak: Optional[KeycloakConfig] = Field(
263
+ None, description="Keycloak configuration."
264
+ )
265
+
266
+ @model_validator(mode="before")
267
+ def validate_keycloak_authentication(cls, values):
268
+ rabbitmq_config = values.get("rabbitmq")
269
+ keycloak_config = values.get("keycloak")
270
+
271
+ # Check if rabbitmq_config is a dictionary and validate the keycloak_authentication key
272
+ if (
273
+ isinstance(rabbitmq_config, dict)
274
+ and rabbitmq_config.get("keycloak_authentication", False)
275
+ and not keycloak_config
276
+ ):
277
+ raise ValueError(
278
+ "Keycloak authentication is enabled, but the Keycloak configuration is missing."
279
+ )
280
+ return values
281
+
282
+
283
+ class GeneralConfig(BaseModel):
284
+ prefix: str = Field("nost", description="Execution prefix.")
285
+
286
+
287
+ class ManagerConfig(BaseModel):
288
+ sim_start_time: Optional[datetime] = Field(
289
+ None, description="Simulation start time."
290
+ )
291
+ sim_stop_time: Optional[datetime] = Field(None, description="Simulation stop time.")
292
+ start_time: Optional[datetime] = Field(None, description="Execution start time.")
293
+ time_step: timedelta = Field(
294
+ timedelta(seconds=1),
295
+ description="Time step for the simulation.",
296
+ )
297
+ time_scale_factor: float = Field(1.0, description="Time scale factor.")
298
+ time_scale_updates: List[str] = Field(
299
+ default_factory=list, description="List of time scale updates."
300
+ )
301
+ time_status_step: Optional[timedelta] = Field(None, description="Time status step.")
302
+ time_status_init: Optional[datetime] = Field(None, description="Time status init.")
303
+ command_lead: timedelta = Field(
304
+ timedelta(seconds=0), description="Command lead time."
305
+ )
306
+ required_apps: List[str] = Field(
307
+ default_factory=list, description="List of required applications."
308
+ )
309
+ init_retry_delay_s: int = Field(5, description="Initial retry delay in seconds.")
310
+ init_max_retry: int = Field(5, description="Initial maximum retry attempts.")
311
+ set_offset: bool = Field(True, description="Set offset.")
312
+ shut_down_when_terminated: bool = Field(
313
+ False, description="Shut down when terminated."
314
+ )
315
+
316
+ @model_validator(mode="before")
317
+ def scale_time(cls, values):
318
+ time_scale_factor = values.get("time_scale_factor", 1.0)
319
+
320
+ if "time_status_step" in values:
321
+ time_status_step = values["time_status_step"]
322
+ if isinstance(time_status_step, str):
323
+ hours, minutes, seconds = map(int, time_status_step.split(":"))
324
+ time_status_step = timedelta(
325
+ hours=hours, minutes=minutes, seconds=seconds
326
+ )
327
+ if isinstance(time_status_step, timedelta):
328
+ values["time_status_step"] = timedelta(
329
+ seconds=time_status_step.total_seconds() * time_scale_factor
330
+ )
331
+
332
+ return values
333
+
334
+
335
+ class ManagedApplicationConfig(BaseModel):
336
+ time_scale_factor: float = Field(1.0, description="Time scale factor.")
337
+ time_step: timedelta = Field(
338
+ timedelta(seconds=1), description="Time step for swe_change."
339
+ )
340
+ set_offset: bool = Field(True, description="Set offset.")
341
+ time_status_step: timedelta = Field(None, description="Time status step.")
342
+ time_status_init: datetime = Field(None, description="Time status init.")
343
+ shut_down_when_terminated: bool = Field(
344
+ False, description="Shut down when terminated."
345
+ )
346
+ manager_app_name: str = Field("manager", description="Manager application name.")
347
+
348
+ @model_validator(mode="before")
349
+ def scale_time(cls, values):
350
+ time_scale_factor = values.get("time_scale_factor", 1.0)
351
+
352
+ if "time_step" in values:
353
+ time_step = values["time_step"]
354
+ if isinstance(time_step, str):
355
+ hours, minutes, seconds = map(int, time_step.split(":"))
356
+ time_step = timedelta(hours=hours, minutes=minutes, seconds=seconds)
357
+ if isinstance(time_step, timedelta):
358
+ values["time_step"] = timedelta(
359
+ seconds=time_step.total_seconds() * time_scale_factor
360
+ )
361
+
362
+ if "time_status_step" in values:
363
+ time_status_step = values["time_status_step"]
364
+ if isinstance(time_status_step, str):
365
+ hours, minutes, seconds = map(int, time_status_step.split(":"))
366
+ time_status_step = timedelta(
367
+ hours=hours, minutes=minutes, seconds=seconds
368
+ )
369
+ if isinstance(time_status_step, timedelta):
370
+ values["time_status_step"] = timedelta(
371
+ seconds=time_status_step.total_seconds() * time_scale_factor
372
+ )
373
+
374
+ return values
375
+
376
+
377
+ class LoggerApplicationConfig(BaseModel):
378
+ set_offset: Optional[bool] = Field(True, description="Set offset.")
379
+ time_scale_factor: Optional[float] = Field(1.0, description="Time scale factor.")
380
+ time_step: Optional[timedelta] = Field(
381
+ timedelta(seconds=1), description="Time step for swe_change."
382
+ )
383
+ time_status_step: Optional[timedelta] = Field(
384
+ timedelta(seconds=10), description="Time status step."
385
+ )
386
+ time_status_init: Optional[datetime] = Field(
387
+ datetime(2019, 3, 1, 0, 0, 0), description="Time status init."
388
+ )
389
+ shut_down_when_terminated: Optional[bool] = Field(
390
+ False, description="Shut down when terminated."
391
+ )
392
+ manager_app_name: Optional[str] = Field(
393
+ "manager", description="Manager application name."
394
+ )
395
+
396
+
397
+ class ExecConfig(BaseModel):
398
+ general: GeneralConfig
399
+ manager: Optional[ManagerConfig] = Field(None, description="Manager configuration.")
400
+ managed_application: Optional[ManagedApplicationConfig] = Field(
401
+ None, description="Managed application configuration."
402
+ )
403
+ logger_application: Optional[LoggerApplicationConfig] = Field(
404
+ None, description="Logger application configuration."
405
+ )
406
+
407
+
408
+ class Config(BaseModel):
409
+ servers: ServersConfig = Field(..., description="Servers configuration.")
410
+ channels: Dict[str, Dict] = Field({}, description="Channels configuration.")
411
+ execution: ExecConfig = Field(..., description="Applications configuration.")
412
+
413
+
414
+ class ExchangeConfig(BaseModel):
415
+ name: str
416
+ type: str = "topic"
417
+ durable: bool = True
418
+ auto_delete: bool = False
419
+ vhost: str = "/"
420
+
421
+
422
+ class ChannelConfig(BaseModel):
423
+ app: str
424
+ address: str
425
+ exchange: str
426
+ durable: bool
427
+ auto_delete: bool
428
+ vhost: str
429
+
430
+
431
+ class Credentials(BaseModel):
432
+ username: str = Field(..., description="Username for authentication.")
433
+ password: str = Field(..., description="Password for authentication.")
434
+ client_id: Optional[str] = Field("", description="Client ID for authentication.")
435
+ client_secret_key: Optional[str] = Field(
436
+ "", description="Client secret key for authentication."
437
+ )
438
+
439
+
440
+ class SimulationConfig(BaseModel):
441
+ exchanges: Dict[str, Dict] = Field(
442
+ default_factory=dict, description="Dictionary of exchanges."
443
+ )
444
+ queues: List[Dict] = Field(default_factory=list, description="List of channels.")
445
+ execution_parameters: ExecConfig = Field(..., description="Execution parameters.")
446
+ predefined_exchanges_queues: bool = Field(
447
+ False, description="Predefined exchanges and queues."
448
+ )
449
+
450
+
451
+ class RuntimeConfig(BaseModel):
452
+ credentials: Credentials = Field(..., description="Credentials for authentication.")
453
+ server_configuration: Config = (
454
+ Field(..., description="Simulation configuration."),
455
+ )
456
+ simulation_configuration: SimulationConfig = Field(
457
+ ..., description="Simulation configuration."
458
+ )