flood-adapt 0.3.9__py3-none-any.whl → 0.3.11__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.
- flood_adapt/__init__.py +26 -22
- flood_adapt/adapter/__init__.py +9 -9
- flood_adapt/adapter/fiat_adapter.py +1541 -1541
- flood_adapt/adapter/interface/hazard_adapter.py +70 -70
- flood_adapt/adapter/interface/impact_adapter.py +36 -36
- flood_adapt/adapter/interface/model_adapter.py +89 -89
- flood_adapt/adapter/interface/offshore.py +19 -19
- flood_adapt/adapter/sfincs_adapter.py +1853 -1848
- flood_adapt/adapter/sfincs_offshore.py +187 -193
- flood_adapt/config/config.py +248 -248
- flood_adapt/config/fiat.py +219 -219
- flood_adapt/config/gui.py +331 -331
- flood_adapt/config/sfincs.py +481 -336
- flood_adapt/config/site.py +129 -129
- flood_adapt/database_builder/database_builder.py +2210 -2210
- flood_adapt/database_builder/templates/default_units/imperial.toml +9 -9
- flood_adapt/database_builder/templates/default_units/metric.toml +9 -9
- flood_adapt/database_builder/templates/green_infra_table/green_infra_lookup_table.csv +10 -10
- flood_adapt/database_builder/templates/infographics/OSM/config_charts.toml +90 -90
- flood_adapt/database_builder/templates/infographics/OSM/config_people.toml +57 -57
- flood_adapt/database_builder/templates/infographics/OSM/config_risk_charts.toml +121 -121
- flood_adapt/database_builder/templates/infographics/OSM/config_roads.toml +65 -65
- flood_adapt/database_builder/templates/infographics/OSM/styles.css +45 -45
- flood_adapt/database_builder/templates/infographics/US_NSI/config_charts.toml +126 -126
- flood_adapt/database_builder/templates/infographics/US_NSI/config_people.toml +60 -60
- flood_adapt/database_builder/templates/infographics/US_NSI/config_risk_charts.toml +121 -121
- flood_adapt/database_builder/templates/infographics/US_NSI/config_roads.toml +65 -65
- flood_adapt/database_builder/templates/infographics/US_NSI/styles.css +45 -45
- flood_adapt/database_builder/templates/infometrics/OSM/metrics_additional_risk_configs.toml +4 -4
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config.toml +143 -143
- flood_adapt/database_builder/templates/infometrics/OSM/with_SVI/infographic_metrics_config_risk.toml +153 -153
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config.toml +127 -127
- flood_adapt/database_builder/templates/infometrics/OSM/without_SVI/infographic_metrics_config_risk.toml +57 -57
- flood_adapt/database_builder/templates/infometrics/US_NSI/metrics_additional_risk_configs.toml +4 -4
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config.toml +191 -191
- flood_adapt/database_builder/templates/infometrics/US_NSI/with_SVI/infographic_metrics_config_risk.toml +153 -153
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config.toml +178 -178
- flood_adapt/database_builder/templates/infometrics/US_NSI/without_SVI/infographic_metrics_config_risk.toml +57 -57
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config.toml +9 -9
- flood_adapt/database_builder/templates/infometrics/mandatory_metrics_config_risk.toml +65 -65
- flood_adapt/database_builder/templates/output_layers/bin_colors.toml +5 -5
- flood_adapt/database_builder.py +16 -16
- flood_adapt/dbs_classes/__init__.py +21 -21
- flood_adapt/dbs_classes/database.py +533 -684
- flood_adapt/dbs_classes/dbs_benefit.py +77 -76
- flood_adapt/dbs_classes/dbs_event.py +61 -59
- flood_adapt/dbs_classes/dbs_measure.py +112 -111
- flood_adapt/dbs_classes/dbs_projection.py +34 -34
- flood_adapt/dbs_classes/dbs_scenario.py +137 -137
- flood_adapt/dbs_classes/dbs_static.py +274 -273
- flood_adapt/dbs_classes/dbs_strategy.py +130 -129
- flood_adapt/dbs_classes/dbs_template.py +279 -278
- flood_adapt/dbs_classes/interface/database.py +107 -139
- flood_adapt/dbs_classes/interface/element.py +121 -121
- flood_adapt/dbs_classes/interface/static.py +47 -47
- flood_adapt/flood_adapt.py +1229 -1178
- flood_adapt/misc/database_user.py +16 -16
- flood_adapt/misc/exceptions.py +22 -0
- flood_adapt/misc/log.py +183 -183
- flood_adapt/misc/path_builder.py +54 -54
- flood_adapt/misc/utils.py +185 -185
- flood_adapt/objects/__init__.py +82 -82
- flood_adapt/objects/benefits/benefits.py +61 -61
- flood_adapt/objects/events/event_factory.py +135 -135
- flood_adapt/objects/events/event_set.py +88 -84
- flood_adapt/objects/events/events.py +236 -234
- flood_adapt/objects/events/historical.py +58 -58
- flood_adapt/objects/events/hurricane.py +68 -67
- flood_adapt/objects/events/synthetic.py +46 -50
- flood_adapt/objects/forcing/__init__.py +92 -92
- flood_adapt/objects/forcing/csv.py +68 -68
- flood_adapt/objects/forcing/discharge.py +66 -66
- flood_adapt/objects/forcing/forcing.py +150 -150
- flood_adapt/objects/forcing/forcing_factory.py +182 -182
- flood_adapt/objects/forcing/meteo_handler.py +93 -93
- flood_adapt/objects/forcing/netcdf.py +40 -40
- flood_adapt/objects/forcing/plotting.py +453 -429
- flood_adapt/objects/forcing/rainfall.py +98 -98
- flood_adapt/objects/forcing/tide_gauge.py +191 -191
- flood_adapt/objects/forcing/time_frame.py +90 -90
- flood_adapt/objects/forcing/timeseries.py +564 -564
- flood_adapt/objects/forcing/unit_system.py +580 -580
- flood_adapt/objects/forcing/waterlevels.py +108 -108
- flood_adapt/objects/forcing/wind.py +124 -124
- flood_adapt/objects/measures/measure_factory.py +92 -92
- flood_adapt/objects/measures/measures.py +551 -529
- flood_adapt/objects/object_model.py +74 -68
- flood_adapt/objects/projections/projections.py +103 -103
- flood_adapt/objects/scenarios/scenarios.py +22 -22
- flood_adapt/objects/strategies/strategies.py +89 -89
- flood_adapt/workflows/benefit_runner.py +579 -554
- flood_adapt/workflows/floodmap.py +85 -85
- flood_adapt/workflows/impacts_integrator.py +85 -85
- flood_adapt/workflows/scenario_runner.py +70 -70
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/LICENSE +674 -674
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/METADATA +867 -865
- flood_adapt-0.3.11.dist-info/RECORD +140 -0
- flood_adapt-0.3.9.dist-info/RECORD +0 -139
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/WHEEL +0 -0
- {flood_adapt-0.3.9.dist-info → flood_adapt-0.3.11.dist-info}/top_level.txt +0 -0
|
@@ -1,278 +1,279 @@
|
|
|
1
|
-
import shutil
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Any, Optional, TypeVar
|
|
5
|
-
|
|
6
|
-
import tomli
|
|
7
|
-
import tomli_w
|
|
8
|
-
|
|
9
|
-
from flood_adapt.dbs_classes.interface.database import IDatabase
|
|
10
|
-
from flood_adapt.dbs_classes.interface.element import AbstractDatabaseElement
|
|
11
|
-
from flood_adapt.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
self.
|
|
27
|
-
self.
|
|
28
|
-
self.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
copy_object
|
|
78
|
-
copy_object.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
toml_path.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
#
|
|
212
|
-
return
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
"
|
|
244
|
-
"
|
|
245
|
-
"
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
#
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
1
|
+
import shutil
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Optional, TypeVar
|
|
5
|
+
|
|
6
|
+
import tomli
|
|
7
|
+
import tomli_w
|
|
8
|
+
|
|
9
|
+
from flood_adapt.dbs_classes.interface.database import IDatabase
|
|
10
|
+
from flood_adapt.dbs_classes.interface.element import AbstractDatabaseElement
|
|
11
|
+
from flood_adapt.misc.exceptions import DatabaseError
|
|
12
|
+
from flood_adapt.objects.object_model import Object
|
|
13
|
+
|
|
14
|
+
T_OBJECTMODEL = TypeVar("T_OBJECTMODEL", bound=Object)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DbsTemplate(AbstractDatabaseElement[T_OBJECTMODEL]):
|
|
18
|
+
display_name: str
|
|
19
|
+
dir_name: str
|
|
20
|
+
_object_class: type[T_OBJECTMODEL]
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self, database: IDatabase, standard_objects: Optional[list[str]] = None
|
|
24
|
+
):
|
|
25
|
+
"""Initialize any necessary attributes."""
|
|
26
|
+
self._database = database
|
|
27
|
+
self.input_path = database.input_path / self.dir_name
|
|
28
|
+
self.output_path = database.output_path / self.dir_name
|
|
29
|
+
self.standard_objects = standard_objects
|
|
30
|
+
|
|
31
|
+
def get(self, name: str) -> T_OBJECTMODEL:
|
|
32
|
+
"""Return an object of the type of the database with the given name.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
name : str
|
|
37
|
+
name of the object to be returned
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
Object
|
|
42
|
+
object of the type of the specified object model
|
|
43
|
+
"""
|
|
44
|
+
# Make the full path to the object
|
|
45
|
+
full_path = self.input_path / name / f"{name}.toml"
|
|
46
|
+
|
|
47
|
+
# Check if the object exists
|
|
48
|
+
if not Path(full_path).is_file():
|
|
49
|
+
raise DatabaseError(f"{self.display_name}: '{name}' does not exist.")
|
|
50
|
+
|
|
51
|
+
# Load and return the object
|
|
52
|
+
return self._object_class.load_file(full_path)
|
|
53
|
+
|
|
54
|
+
def summarize_objects(self) -> dict[str, list[Any]]:
|
|
55
|
+
"""Return a dictionary with info on the objects that currently exist in the database.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
dict[str, list[Any]]
|
|
60
|
+
A dictionary that contains the keys: `name`, `description`, `path` and `last_modification_date`.
|
|
61
|
+
Each key has a list of the corresponding values, where the index of the values corresponds to the same object.
|
|
62
|
+
"""
|
|
63
|
+
return self._get_object_summary()
|
|
64
|
+
|
|
65
|
+
def copy(self, old_name: str, new_name: str, new_description: str):
|
|
66
|
+
"""Copy (duplicate) an existing object, and give it a new name.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
old_name : str
|
|
71
|
+
name of the existing measure
|
|
72
|
+
new_name : str
|
|
73
|
+
name of the new measure
|
|
74
|
+
new_description : str
|
|
75
|
+
description of the new measure
|
|
76
|
+
"""
|
|
77
|
+
copy_object = self.get(old_name)
|
|
78
|
+
copy_object.name = new_name
|
|
79
|
+
copy_object.description = new_description
|
|
80
|
+
|
|
81
|
+
# After changing the name and description, re-trigger the validators
|
|
82
|
+
copy_object.model_validate(copy_object)
|
|
83
|
+
|
|
84
|
+
# Checking whether the new name is already in use
|
|
85
|
+
self._validate_to_save(copy_object, overwrite=False)
|
|
86
|
+
|
|
87
|
+
# Write only the toml file
|
|
88
|
+
toml_path = self.input_path / new_name / f"{new_name}.toml"
|
|
89
|
+
toml_path.parent.mkdir(parents=True)
|
|
90
|
+
with open(toml_path, "wb") as f:
|
|
91
|
+
tomli_w.dump(copy_object.model_dump(exclude_none=True), f)
|
|
92
|
+
|
|
93
|
+
# Then copy all the accompanied files
|
|
94
|
+
src = self.input_path / old_name
|
|
95
|
+
dest = self.input_path / new_name
|
|
96
|
+
|
|
97
|
+
EXCLUDE = [".spw", ".toml"]
|
|
98
|
+
for file in src.glob("*"):
|
|
99
|
+
if file.suffix in EXCLUDE:
|
|
100
|
+
continue
|
|
101
|
+
if file.is_dir():
|
|
102
|
+
shutil.copytree(file, dest / file.name, dirs_exist_ok=True)
|
|
103
|
+
else:
|
|
104
|
+
shutil.copy2(file, dest / file.name)
|
|
105
|
+
|
|
106
|
+
def save(
|
|
107
|
+
self,
|
|
108
|
+
object_model: T_OBJECTMODEL,
|
|
109
|
+
overwrite: bool = False,
|
|
110
|
+
):
|
|
111
|
+
"""Save an object in the database and all associated files.
|
|
112
|
+
|
|
113
|
+
This saves the toml file and any additional files attached to the object.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
object_model : Object
|
|
118
|
+
object to be saved in the database
|
|
119
|
+
overwrite : bool, optional
|
|
120
|
+
whether to overwrite the object if it already exists in the
|
|
121
|
+
database, by default False
|
|
122
|
+
|
|
123
|
+
Raises
|
|
124
|
+
------
|
|
125
|
+
DatabaseError
|
|
126
|
+
Raise error if name is already in use.
|
|
127
|
+
"""
|
|
128
|
+
self._validate_to_save(object_model, overwrite=overwrite)
|
|
129
|
+
|
|
130
|
+
# If the folder doesnt exist yet, make the folder and save the object
|
|
131
|
+
if not (self.input_path / object_model.name).exists():
|
|
132
|
+
(self.input_path / object_model.name).mkdir()
|
|
133
|
+
|
|
134
|
+
# Save the object and any additional files
|
|
135
|
+
object_model.save(
|
|
136
|
+
self.input_path / object_model.name / f"{object_model.name}.toml",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def delete(self, name: str, toml_only: bool = False):
|
|
140
|
+
"""Delete an already existing object in the database.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
name : str
|
|
145
|
+
name of the object to be deleted
|
|
146
|
+
toml_only : bool, optional
|
|
147
|
+
whether to only delete the toml file or the entire folder. If the folder is empty after deleting the toml,
|
|
148
|
+
it will always be deleted. By default False
|
|
149
|
+
|
|
150
|
+
Raises
|
|
151
|
+
------
|
|
152
|
+
DatabaseError
|
|
153
|
+
Raise error if object to be deleted is already in use.
|
|
154
|
+
"""
|
|
155
|
+
# Check if the object is a standard object. If it is, raise an error
|
|
156
|
+
if self._check_standard_objects(name):
|
|
157
|
+
raise DatabaseError(
|
|
158
|
+
f"'{name}' cannot be deleted/modified since it is a standard {self.display_name}."
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Check if object is used in a higher level object. If it is, raise an error
|
|
162
|
+
if used_in := self.check_higher_level_usage(name):
|
|
163
|
+
raise DatabaseError(
|
|
164
|
+
f"{self.display_name}: '{name}' cannot be deleted/modified since it is already used in: {', '.join(used_in)}"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Once all checks are passed, delete the object
|
|
168
|
+
toml_path = self.input_path / name / f"{name}.toml"
|
|
169
|
+
if toml_only:
|
|
170
|
+
# Only delete the toml file
|
|
171
|
+
toml_path.unlink(missing_ok=True)
|
|
172
|
+
# If the folder is empty, delete the folder
|
|
173
|
+
if not list(toml_path.parent.iterdir()):
|
|
174
|
+
toml_path.parent.rmdir()
|
|
175
|
+
else:
|
|
176
|
+
# Delete the entire folder
|
|
177
|
+
shutil.rmtree(toml_path.parent, ignore_errors=True)
|
|
178
|
+
if (self.output_path / name).exists():
|
|
179
|
+
shutil.rmtree(self.output_path / name, ignore_errors=True)
|
|
180
|
+
|
|
181
|
+
def _check_standard_objects(self, name: str) -> bool:
|
|
182
|
+
"""Check if an object is a standard object.
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
name : str
|
|
187
|
+
name of the object to be checked
|
|
188
|
+
|
|
189
|
+
Returns
|
|
190
|
+
-------
|
|
191
|
+
bool
|
|
192
|
+
True if the object is a standard object, False otherwise
|
|
193
|
+
"""
|
|
194
|
+
if self.standard_objects:
|
|
195
|
+
return name in self.standard_objects
|
|
196
|
+
return False
|
|
197
|
+
|
|
198
|
+
def check_higher_level_usage(self, name: str) -> list[str]:
|
|
199
|
+
"""Check if an object is used in a higher level object.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
name : str
|
|
204
|
+
name of the object to be checked
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
list[str]
|
|
209
|
+
list of higher level objects that use the object
|
|
210
|
+
"""
|
|
211
|
+
# If this function is not implemented for the object type, it cannot be used in a higher
|
|
212
|
+
# level object. By default, return an empty list
|
|
213
|
+
return []
|
|
214
|
+
|
|
215
|
+
def _get_object_summary(self) -> dict[str, list[Any]]:
|
|
216
|
+
"""Get a dictionary with all the toml paths and last modification dates that exist in the database of the given object_type.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
dict[str, Any]
|
|
221
|
+
A dictionary that contains the keys: `name`, `description`, `path` and `last_modification_date`.
|
|
222
|
+
Each key has a list of the corresponding values, where the index of the values corresponds to the same object.
|
|
223
|
+
"""
|
|
224
|
+
# If the toml doesnt exist, we might be in the middle of saving a new object or could be a broken object.
|
|
225
|
+
# In any case, we should not list it in the database
|
|
226
|
+
directories = [
|
|
227
|
+
dir
|
|
228
|
+
for dir in self.input_path.iterdir()
|
|
229
|
+
if (dir / f"{dir.name}.toml").is_file()
|
|
230
|
+
]
|
|
231
|
+
paths = [Path(dir / f"{dir.name}.toml") for dir in directories]
|
|
232
|
+
|
|
233
|
+
names = [self._read_variable_in_toml("name", path) for path in paths]
|
|
234
|
+
descriptions = [
|
|
235
|
+
self._read_variable_in_toml("description", path) for path in paths
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
last_modification_date = [
|
|
239
|
+
datetime.fromtimestamp(file.stat().st_mtime) for file in paths
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
objects = {
|
|
243
|
+
"name": names,
|
|
244
|
+
"description": descriptions,
|
|
245
|
+
"path": paths,
|
|
246
|
+
"last_modification_date": last_modification_date,
|
|
247
|
+
}
|
|
248
|
+
return objects
|
|
249
|
+
|
|
250
|
+
@staticmethod
|
|
251
|
+
def _read_variable_in_toml(variable_name: str, toml_path: Path) -> str:
|
|
252
|
+
with open(toml_path, "rb") as f:
|
|
253
|
+
data = tomli.load(f)
|
|
254
|
+
return data.get(variable_name, "")
|
|
255
|
+
|
|
256
|
+
def _validate_to_save(self, object_model: T_OBJECTMODEL, overwrite: bool) -> None:
|
|
257
|
+
"""Validate if the object can be saved.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
object_model : Object
|
|
262
|
+
object to be validated
|
|
263
|
+
|
|
264
|
+
Raises
|
|
265
|
+
------
|
|
266
|
+
DatabaseError
|
|
267
|
+
Raise error if name is already in use.
|
|
268
|
+
"""
|
|
269
|
+
# Check if the object exists
|
|
270
|
+
object_exists = object_model.name in self.summarize_objects()["name"]
|
|
271
|
+
|
|
272
|
+
# If you want to overwrite the object, and the object already exists, first delete it. If it exists and you
|
|
273
|
+
# don't want to overwrite, raise an error.
|
|
274
|
+
if overwrite and object_exists:
|
|
275
|
+
self.delete(object_model.name, toml_only=True)
|
|
276
|
+
elif not overwrite and object_exists:
|
|
277
|
+
raise DatabaseError(
|
|
278
|
+
f"'{object_model.name}' name is already used by another {self.display_name.lower()}. Choose a different name"
|
|
279
|
+
)
|