fmu-settings 0.3.0__tar.gz → 0.3.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.

Files changed (43) hide show
  1. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/PKG-INFO +1 -1
  2. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_resources/lock_manager.py +13 -3
  3. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_resources/pydantic_resource_manager.py +11 -4
  4. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_version.py +3 -3
  5. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu_settings.egg-info/PKG-INFO +1 -1
  6. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_fmu_dir.py +2 -2
  7. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_resources/test_lock_manager.py +41 -10
  8. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_resources/test_resource_managers.py +56 -0
  9. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.coveragerc +0 -0
  10. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.github/pull_request_template.md +0 -0
  11. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.github/workflows/ci.yml +0 -0
  12. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.github/workflows/codeql.yml +0 -0
  13. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.github/workflows/publish.yml +0 -0
  14. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/.gitignore +0 -0
  15. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/CONTRIBUTING.md +0 -0
  16. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/LICENSE +0 -0
  17. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/README.md +0 -0
  18. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/SECURITY.md +0 -0
  19. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/pyproject.toml +0 -0
  20. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/setup.cfg +0 -0
  21. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/__init__.py +0 -0
  22. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/__init__.py +0 -0
  23. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_fmu_dir.py +0 -0
  24. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_init.py +0 -0
  25. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_logging.py +0 -0
  26. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_resources/__init__.py +0 -0
  27. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/_resources/config_managers.py +0 -0
  28. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/__init__.py +0 -0
  29. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/_enums.py +0 -0
  30. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/_mappings.py +0 -0
  31. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/lock_info.py +0 -0
  32. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/project_config.py +0 -0
  33. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/models/user_config.py +0 -0
  34. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/py.typed +0 -0
  35. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu/settings/types.py +0 -0
  36. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu_settings.egg-info/SOURCES.txt +0 -0
  37. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu_settings.egg-info/dependency_links.txt +0 -0
  38. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu_settings.egg-info/requires.txt +0 -0
  39. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/src/fmu_settings.egg-info/top_level.txt +0 -0
  40. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/conftest.py +0 -0
  41. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_init.py +0 -0
  42. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_resources/test_project_config.py +0 -0
  43. {fmu_settings-0.3.0 → fmu_settings-0.3.2}/tests/test_resources/test_user_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu-settings
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A library for managing FMU settings
5
5
  Author-email: Equinor <fg-fmu_atlas@equinor.com>
6
6
  License: GPL-3.0
@@ -153,7 +153,17 @@ class LockManager(PydanticResourceManager[LockInfo]):
153
153
  temp_path.unlink()
154
154
 
155
155
  def is_locked(self: Self) -> bool:
156
- """Returns whether or not the lock is currently locked."""
156
+ """Returns whether or not the lock is locked by anyone.
157
+
158
+ This does a force load on the lock file.
159
+ """
160
+ lock_info = self._safe_load(force=True)
161
+ if not lock_info:
162
+ return False
163
+ return time.time() < lock_info.expires_at
164
+
165
+ def is_acquired(self: Self) -> bool:
166
+ """Returns whether or not the lock is currently acquired by this instance."""
157
167
  if self._cache is None or self._acquired_at is None:
158
168
  return False
159
169
  return self._is_mine(self._cache) and not self._is_stale()
@@ -219,13 +229,13 @@ class LockManager(PydanticResourceManager[LockInfo]):
219
229
  and lock_info.acquired_at == self._acquired_at
220
230
  )
221
231
 
222
- def _safe_load(self: Self) -> LockInfo | None:
232
+ def _safe_load(self: Self, force: bool = False) -> LockInfo | None:
223
233
  """Load lock info, returning None if corrupted.
224
234
 
225
235
  Because this file does not exist in a static state, wrap around loading it.
226
236
  """
227
237
  try:
228
- return self.load()
238
+ return self.load(force=force)
229
239
  except Exception:
230
240
  return None
231
241
 
@@ -48,11 +48,14 @@ class PydanticResourceManager(Generic[T]):
48
48
  """Returns whether or not the resource exists."""
49
49
  return self.path.exists()
50
50
 
51
- def load(self: Self, force: bool = False) -> T:
52
- """Loads the resources from disk and validates it as a Pydantic model.
51
+ def load(self: Self, force: bool = False, store_cache: bool = True) -> T:
52
+ """Loads the resource from disk and validates it as a Pydantic model.
53
53
 
54
54
  Args:
55
- force: Force a re-read even if the file is already cached
55
+ force: Force a re-read even if the file is already cached.
56
+ store_cache: Whether or not to cache the loaded model internally. This is
57
+ best used with 'force=True' because if a model is already stored in
58
+ _cache it will be returned without re-loading. Default True.
56
59
 
57
60
  Returns:
58
61
  Validated Pydantic model
@@ -71,7 +74,11 @@ class PydanticResourceManager(Generic[T]):
71
74
  try:
72
75
  content = self.fmu_dir.read_text_file(self.relative_path)
73
76
  data = json.loads(content)
74
- self._cache = self.model_class.model_validate(data)
77
+ validated_model = self.model_class.model_validate(data)
78
+ if store_cache:
79
+ self._cache = validated_model
80
+ else:
81
+ return validated_model
75
82
  except ValidationError as e:
76
83
  raise ValueError(
77
84
  f"Invalid content in resource file for '{self.__class__.__name__}: "
@@ -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.3.0'
32
- __version_tuple__ = version_tuple = (0, 3, 0)
31
+ __version__ = version = '0.3.2'
32
+ __version_tuple__ = version_tuple = (0, 3, 2)
33
33
 
34
- __commit_id__ = commit_id = 'g5fa25d14f'
34
+ __commit_id__ = commit_id = 'g9ea88b68f'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu-settings
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A library for managing FMU settings
5
5
  Author-email: Equinor <fg-fmu_atlas@equinor.com>
6
6
  License: GPL-3.0
@@ -333,7 +333,7 @@ def test_acquire_lock_on_project_fmu(
333
333
  ) -> None:
334
334
  """Tests that a lock can be acquired on the project dir."""
335
335
  fmu_dir._lock.acquire()
336
- assert fmu_dir._lock.is_locked()
336
+ assert fmu_dir._lock.is_acquired()
337
337
  assert fmu_dir._lock.exists
338
338
  assert (fmu_dir.path / ".lock").exists()
339
339
 
@@ -343,6 +343,6 @@ def test_acquire_lock_on_user_fmu(
343
343
  ) -> None:
344
344
  """Tests that a lock can be acquired on the user dir."""
345
345
  user_fmu_dir._lock.acquire()
346
- assert user_fmu_dir._lock.is_locked()
346
+ assert user_fmu_dir._lock.is_acquired()
347
347
  assert user_fmu_dir._lock.exists
348
348
  assert (user_fmu_dir.path / ".lock").exists()
@@ -95,6 +95,7 @@ def test_lock_acquire_raises_if_already_acquired(fmu_dir: ProjectFMUDirectory) -
95
95
  lock = LockManager(fmu_dir)
96
96
  lock.acquire()
97
97
  assert lock.is_locked()
98
+ assert lock.is_acquired()
98
99
  with pytest.raises(LockError, match="Lock already acquired"):
99
100
  lock.acquire()
100
101
 
@@ -190,6 +191,7 @@ def test_lock_acquire_over_expired_lock(fmu_dir: ProjectFMUDirectory) -> None:
190
191
  stale_lock = LockManager(fmu_dir, timeout_seconds=-1) # Expired
191
192
  stale_lock.acquire()
192
193
  assert stale_lock.is_locked() is False
194
+ assert stale_lock.is_acquired() is False
193
195
  assert stale_lock._is_stale() is True
194
196
  stale_lock_info = stale_lock.load()
195
197
 
@@ -198,6 +200,7 @@ def test_lock_acquire_over_expired_lock(fmu_dir: ProjectFMUDirectory) -> None:
198
200
  lock_info = lock.load()
199
201
 
200
202
  assert lock.is_locked()
203
+ assert lock.is_acquired()
201
204
  assert stale_lock.path == lock.path
202
205
  assert lock_info != stale_lock_info
203
206
 
@@ -385,27 +388,55 @@ def test_try_acquire_fails_when_linking_temp_file(
385
388
  def test_is_locked_expected(
386
389
  fmu_dir: ProjectFMUDirectory, monkeypatch: MonkeyPatch
387
390
  ) -> None:
388
- """Tests is_locked under expected conditions."""
391
+ """Tests is_locked under expected, simple conditions."""
389
392
  lock = LockManager(fmu_dir)
390
393
  assert lock.is_locked() is False
391
394
  lock.acquire()
392
395
  assert lock.is_locked() is True
396
+ lock.release()
397
+ assert lock.is_locked() is False
393
398
 
394
399
 
395
- def test_is_locked_unexpected_members(
400
+ def test_is_locked_by_other_process(
396
401
  fmu_dir: ProjectFMUDirectory, monkeypatch: MonkeyPatch
397
402
  ) -> None:
398
- """Tests is_locked under expected member conditions."""
403
+ """Tests is_locked when another process has the lock."""
399
404
  lock = LockManager(fmu_dir)
400
405
  assert lock.is_locked() is False
401
- lock.acquire()
406
+ with patch("os.getpid", return_value=-1234):
407
+ lock.acquire()
408
+
402
409
  assert lock.is_locked() is True
410
+
411
+ with patch("os.getpid", return_value=-1234):
412
+ lock.release()
413
+ assert lock.is_locked() is False
414
+
415
+
416
+ def test_is_acquired_expected(
417
+ fmu_dir: ProjectFMUDirectory, monkeypatch: MonkeyPatch
418
+ ) -> None:
419
+ """Tests is_acquired under expected conditions."""
420
+ lock = LockManager(fmu_dir)
421
+ assert lock.is_acquired() is False
422
+ lock.acquire()
423
+ assert lock.is_acquired() is True
424
+
425
+
426
+ def test_is_acquired_unexpected_members(
427
+ fmu_dir: ProjectFMUDirectory, monkeypatch: MonkeyPatch
428
+ ) -> None:
429
+ """Tests is_acquired under expected member conditions."""
430
+ lock = LockManager(fmu_dir)
431
+ assert lock.is_acquired() is False
432
+ lock.acquire()
433
+ assert lock.is_acquired() is True
403
434
  lock_info = lock._cache
404
435
  lock._cache = None
405
- assert lock.is_locked() is False
436
+ assert lock.is_acquired() is False
406
437
  lock._cache = lock_info
407
438
  lock._acquired_at = None
408
- assert lock.is_locked() is False
439
+ assert lock.is_acquired() is False
409
440
 
410
441
 
411
442
  @pytest.mark.parametrize(
@@ -417,23 +448,23 @@ def test_is_locked_unexpected_members(
417
448
  (False, False, False),
418
449
  ],
419
450
  )
420
- def test_is_locked_unexpected_methods(
451
+ def test_is_acquired_unexpected_methods(
421
452
  fmu_dir: ProjectFMUDirectory,
422
453
  monkeypatch: MonkeyPatch,
423
454
  is_mine: bool,
424
455
  is_stale: bool,
425
456
  expected: bool,
426
457
  ) -> None:
427
- """Tests is_locked under expected method conditions."""
458
+ """Tests is_acquired under expected method conditions."""
428
459
  lock = LockManager(fmu_dir)
429
- assert lock.is_locked() is False
460
+ assert lock.is_acquired() is False
430
461
  lock.acquire()
431
462
 
432
463
  with (
433
464
  patch.object(lock, "_is_mine", return_value=is_mine),
434
465
  patch.object(lock, "_is_stale", return_value=is_stale),
435
466
  ):
436
- assert lock.is_locked() is expected
467
+ assert lock.is_acquired() is expected
437
468
 
438
469
 
439
470
  def test_refresh_works_as_expected(
@@ -87,6 +87,62 @@ def test_pydantic_resource_manager_load(fmu_dir: ProjectFMUDirectory) -> None:
87
87
  assert a._cache == a_model
88
88
 
89
89
 
90
+ def test_pydantic_resource_manager_load_force_true(
91
+ fmu_dir: ProjectFMUDirectory,
92
+ ) -> None:
93
+ """Tests loading a Pydantic resource with force=True."""
94
+ a = AManager(fmu_dir)
95
+ a_model = A(foo="bar")
96
+ a.save(a_model)
97
+ assert a.load() == a_model
98
+ assert a._cache == a_model
99
+
100
+ a_shadow = AManager(fmu_dir)
101
+ a_shadow_model = A(foo="baz")
102
+ a_shadow.save(a_shadow_model)
103
+
104
+ assert a_shadow.load() == a_shadow_model
105
+ assert a_shadow._cache == a_shadow_model
106
+
107
+ assert a.load() == a_model
108
+ assert a._cache == a_model
109
+
110
+ assert a.load(force=True) == a_shadow_model
111
+ assert a._cache == a_shadow_model
112
+
113
+
114
+ def test_pydantic_resource_manager_load_cache_false(
115
+ fmu_dir: ProjectFMUDirectory,
116
+ ) -> None:
117
+ """Tests loading a Pydantic resource with cache=False."""
118
+ a = AManager(fmu_dir)
119
+ a_model = A(foo="bar")
120
+ a.save(a_model)
121
+
122
+ a_shadow = AManager(fmu_dir)
123
+ assert a_shadow.load(store_cache=False) == a_model
124
+ assert a_shadow._cache is None
125
+
126
+ assert a_shadow.load(store_cache=True) == a_model
127
+ assert a_shadow._cache == a_model
128
+
129
+
130
+ def test_pydantic_resource_manager_load_force_true_cache_false(
131
+ fmu_dir: ProjectFMUDirectory,
132
+ ) -> None:
133
+ """Tests loading a Pydantic resource with force=True, cache=False."""
134
+ a = AManager(fmu_dir)
135
+ a_model = A(foo="bar")
136
+ a.save(a_model)
137
+
138
+ a_shadow = AManager(fmu_dir)
139
+ a_shadow_model = A(foo="baz")
140
+ a_shadow.save(a_shadow_model)
141
+
142
+ assert a.load(force=True, store_cache=False) == a_shadow_model
143
+ assert a._cache is a_model
144
+
145
+
90
146
  def test_pydantic_resource_manager_loads_invalid_model(
91
147
  fmu_dir: ProjectFMUDirectory,
92
148
  ) -> None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes