fmu-settings 0.5.1__tar.gz → 0.5.2__tar.gz
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 fmu-settings might be problematic. Click here for more details.
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/PKG-INFO +1 -1
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_resources/lock_manager.py +2 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_resources/pydantic_resource_manager.py +45 -45
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_version.py +3 -3
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu_settings.egg-info/PKG-INFO +1 -1
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_resources/test_lock_manager.py +15 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.coveragerc +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.github/pull_request_template.md +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.github/workflows/ci.yml +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.github/workflows/codeql.yml +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.github/workflows/publish.yml +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/.gitignore +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/CONTRIBUTING.md +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/LICENSE +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/README.md +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/SECURITY.md +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/pyproject.toml +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/setup.cfg +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/__init__.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/__init__.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_fmu_dir.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_global_config.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_init.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_logging.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_resources/__init__.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_resources/config_managers.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/__init__.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/_enums.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/_mappings.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/lock_info.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/project_config.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/models/user_config.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/py.typed +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/types.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu_settings.egg-info/SOURCES.txt +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu_settings.egg-info/dependency_links.txt +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu_settings.egg-info/requires.txt +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu_settings.egg-info/top_level.txt +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/conftest.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_fmu_dir.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_global_config.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_init.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_resources/test_project_config.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_resources/test_resource_managers.py +0 -0
- {fmu_settings-0.5.1 → fmu_settings-0.5.2}/tests/test_resources/test_user_config.py +0 -0
|
@@ -194,6 +194,8 @@ class LockManager(PydanticResourceManager[LockInfo]):
|
|
|
194
194
|
LockError: If we don't hold the lock or it's invalid
|
|
195
195
|
"""
|
|
196
196
|
if not self.exists:
|
|
197
|
+
if self.is_acquired():
|
|
198
|
+
self.release()
|
|
197
199
|
raise LockError("Cannot refresh: lock file does not exist")
|
|
198
200
|
|
|
199
201
|
lock_info = self._safe_load()
|
{fmu_settings-0.5.1 → fmu_settings-0.5.2}/src/fmu/settings/_resources/pydantic_resource_manager.py
RENAMED
|
@@ -112,21 +112,21 @@ class PydanticResourceManager(Generic[PydanticResource]):
|
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticResource]):
|
|
115
|
-
"""Manages the .fmu
|
|
115
|
+
"""Manages the .fmu resource file."""
|
|
116
116
|
|
|
117
117
|
def __init__(
|
|
118
|
-
self: Self, fmu_dir: FMUDirectoryBase,
|
|
118
|
+
self: Self, fmu_dir: FMUDirectoryBase, resource: type[MutablePydanticResource]
|
|
119
119
|
) -> None:
|
|
120
|
-
"""Initializes the
|
|
121
|
-
super().__init__(fmu_dir,
|
|
120
|
+
"""Initializes the resource manager."""
|
|
121
|
+
super().__init__(fmu_dir, resource)
|
|
122
122
|
|
|
123
123
|
def _get_dot_notation_key(
|
|
124
|
-
self: Self,
|
|
124
|
+
self: Self, resource_dict: dict[str, Any], key: str, default: Any = None
|
|
125
125
|
) -> Any:
|
|
126
126
|
"""Sets the value to a dot-notation key.
|
|
127
127
|
|
|
128
128
|
Args:
|
|
129
|
-
|
|
129
|
+
resource_dict: The resource dictionary we are modifying (by reference)
|
|
130
130
|
key: The key to set
|
|
131
131
|
default: Value to return if key is not found. Default None
|
|
132
132
|
|
|
@@ -134,7 +134,7 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
134
134
|
The value or default
|
|
135
135
|
"""
|
|
136
136
|
parts = key.split(".")
|
|
137
|
-
value =
|
|
137
|
+
value = resource_dict
|
|
138
138
|
for part in parts:
|
|
139
139
|
if isinstance(value, dict) and part in value:
|
|
140
140
|
value = value[part]
|
|
@@ -144,28 +144,28 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
144
144
|
return value
|
|
145
145
|
|
|
146
146
|
def get(self: Self, key: str, default: Any = None) -> Any:
|
|
147
|
-
"""Gets a
|
|
147
|
+
"""Gets a resource value by key.
|
|
148
148
|
|
|
149
149
|
Supports dot notation for nested values (e.g., "foo.bar")
|
|
150
150
|
|
|
151
151
|
Args:
|
|
152
|
-
key: The
|
|
152
|
+
key: The resource key
|
|
153
153
|
default: Value to return if key is not found. Default None
|
|
154
154
|
|
|
155
155
|
Returns:
|
|
156
|
-
The
|
|
156
|
+
The resource value or default
|
|
157
157
|
"""
|
|
158
158
|
try:
|
|
159
|
-
|
|
159
|
+
resource = self.load()
|
|
160
160
|
|
|
161
161
|
if "." in key:
|
|
162
|
-
return self._get_dot_notation_key(
|
|
162
|
+
return self._get_dot_notation_key(resource.model_dump(), key, default)
|
|
163
163
|
|
|
164
|
-
if hasattr(
|
|
165
|
-
return getattr(
|
|
164
|
+
if hasattr(resource, key):
|
|
165
|
+
return getattr(resource, key)
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
return
|
|
167
|
+
resource_dict = resource.model_dump()
|
|
168
|
+
return resource_dict.get(key, default)
|
|
169
169
|
except FileNotFoundError as e:
|
|
170
170
|
raise FileNotFoundError(
|
|
171
171
|
f"Resource file for '{self.__class__.__name__}' not found "
|
|
@@ -173,17 +173,17 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
173
173
|
) from e
|
|
174
174
|
|
|
175
175
|
def _set_dot_notation_key(
|
|
176
|
-
self: Self,
|
|
176
|
+
self: Self, resource_dict: dict[str, Any], key: str, value: Any
|
|
177
177
|
) -> None:
|
|
178
178
|
"""Sets the value to a dot-notation key.
|
|
179
179
|
|
|
180
180
|
Args:
|
|
181
|
-
|
|
181
|
+
resource_dict: The resource dictionary we are modifying (by reference)
|
|
182
182
|
key: The key to set
|
|
183
183
|
value: The value to set
|
|
184
184
|
"""
|
|
185
185
|
parts = key.split(".")
|
|
186
|
-
target =
|
|
186
|
+
target = resource_dict
|
|
187
187
|
|
|
188
188
|
for part in parts[:-1]:
|
|
189
189
|
if part not in target or not isinstance(target[part], dict):
|
|
@@ -193,27 +193,27 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
193
193
|
target[parts[-1]] = value
|
|
194
194
|
|
|
195
195
|
def set(self: Self, key: str, value: Any) -> None:
|
|
196
|
-
"""Sets a
|
|
196
|
+
"""Sets a resource value by key.
|
|
197
197
|
|
|
198
198
|
Args:
|
|
199
|
-
key: The
|
|
199
|
+
key: The resource key
|
|
200
200
|
value: The value to set
|
|
201
201
|
|
|
202
202
|
Raises:
|
|
203
|
-
FileNotFoundError: If
|
|
204
|
-
ValueError: If the updated
|
|
203
|
+
FileNotFoundError: If resource file doesn't exist
|
|
204
|
+
ValueError: If the updated resource is invalid
|
|
205
205
|
"""
|
|
206
206
|
try:
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
resource = self.load()
|
|
208
|
+
resource_dict = resource.model_dump()
|
|
209
209
|
|
|
210
210
|
if "." in key:
|
|
211
|
-
self._set_dot_notation_key(
|
|
211
|
+
self._set_dot_notation_key(resource_dict, key, value)
|
|
212
212
|
else:
|
|
213
|
-
|
|
213
|
+
resource_dict[key] = value
|
|
214
214
|
|
|
215
|
-
|
|
216
|
-
self.save(
|
|
215
|
+
updated_resource = resource.model_validate(resource_dict)
|
|
216
|
+
self.save(updated_resource)
|
|
217
217
|
except ValidationError as e:
|
|
218
218
|
raise ValueError(
|
|
219
219
|
f"Invalid value set for '{self.__class__.__name__}' with "
|
|
@@ -226,31 +226,31 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
226
226
|
) from e
|
|
227
227
|
|
|
228
228
|
def update(self: Self, updates: dict[str, Any]) -> MutablePydanticResource:
|
|
229
|
-
"""Updates multiple
|
|
229
|
+
"""Updates multiple resource values at once.
|
|
230
230
|
|
|
231
231
|
Args:
|
|
232
232
|
updates: Dictionary of key-value pairs to update
|
|
233
233
|
|
|
234
234
|
Returns:
|
|
235
|
-
The updated
|
|
235
|
+
The updated Resource object
|
|
236
236
|
|
|
237
237
|
Raises:
|
|
238
|
-
FileNotFoundError: If
|
|
239
|
-
ValueError: If the updates
|
|
238
|
+
FileNotFoundError: If resource file doesn't exist
|
|
239
|
+
ValueError: If the updates resource is invalid
|
|
240
240
|
"""
|
|
241
241
|
try:
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
resource = self.load()
|
|
243
|
+
resource_dict = resource.model_dump()
|
|
244
244
|
|
|
245
245
|
flat_updates = {k: v for k, v in updates.items() if "." not in k}
|
|
246
|
-
|
|
246
|
+
resource_dict.update(flat_updates)
|
|
247
247
|
|
|
248
248
|
for key, value in updates.items():
|
|
249
249
|
if "." in key:
|
|
250
|
-
self._set_dot_notation_key(
|
|
250
|
+
self._set_dot_notation_key(resource_dict, key, value)
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
self.save(
|
|
252
|
+
updated_resource = resource.model_validate(resource_dict)
|
|
253
|
+
self.save(updated_resource)
|
|
254
254
|
except ValidationError as e:
|
|
255
255
|
raise ValueError(
|
|
256
256
|
f"Invalid value set for '{self.__class__.__name__}' with "
|
|
@@ -262,14 +262,14 @@ class MutablePydanticResourceManager(PydanticResourceManager[MutablePydanticReso
|
|
|
262
262
|
f"at: '{self.path}' when setting updates {updates}"
|
|
263
263
|
) from e
|
|
264
264
|
|
|
265
|
-
return
|
|
265
|
+
return updated_resource
|
|
266
266
|
|
|
267
267
|
def reset(self: Self) -> MutablePydanticResource:
|
|
268
|
-
"""Resets the
|
|
268
|
+
"""Resets the resources to defaults.
|
|
269
269
|
|
|
270
270
|
Returns:
|
|
271
|
-
The new default
|
|
271
|
+
The new default resource object
|
|
272
272
|
"""
|
|
273
|
-
|
|
274
|
-
self.save(
|
|
275
|
-
return
|
|
273
|
+
resource = self.model_class.reset()
|
|
274
|
+
self.save(resource)
|
|
275
|
+
return resource
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.5.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 5,
|
|
31
|
+
__version__ = version = '0.5.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 5, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g4490dbb9d'
|
|
@@ -649,3 +649,18 @@ def test_ensure_can_write_foreign_lock(fmu_dir: ProjectFMUDirectory) -> None:
|
|
|
649
649
|
pytest.raises(PermissionError, match="Cannot write to .fmu directory"),
|
|
650
650
|
):
|
|
651
651
|
lock.ensure_can_write()
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
def test_manual_delete_invalidates_lock_file_on_refresh(
|
|
655
|
+
fmu_dir: ProjectFMUDirectory,
|
|
656
|
+
) -> None:
|
|
657
|
+
"""Tests that if a user deletes anothers lock it's invalidated on a refresh."""
|
|
658
|
+
fmu_dir._lock.acquire()
|
|
659
|
+
assert fmu_dir._lock.is_acquired() is True
|
|
660
|
+
|
|
661
|
+
# Someone deletes the lock
|
|
662
|
+
fmu_dir._lock.path.unlink()
|
|
663
|
+
|
|
664
|
+
with pytest.raises(LockError, match="Cannot refresh: lock file does not exist"):
|
|
665
|
+
fmu_dir._lock.refresh()
|
|
666
|
+
assert fmu_dir._lock.is_acquired() is False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|