policyengine 3.1.8__py3-none-any.whl → 3.1.9__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.
@@ -0,0 +1,56 @@
1
+ import logging
2
+ from collections import OrderedDict
3
+
4
+ import psutil
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ _MEMORY_THRESHOLDS_GB = [8, 16, 32]
9
+ _warned_thresholds: set[int] = set()
10
+
11
+
12
+ class LRUCache[T]:
13
+ """Least-recently-used cache with configurable size limit and memory monitoring."""
14
+
15
+ def __init__(self, max_size: int = 100):
16
+ self._max_size = max_size
17
+ self._cache: OrderedDict[str, T] = OrderedDict()
18
+
19
+ def get(self, key: str) -> T | None:
20
+ """Get item from cache, marking it as recently used."""
21
+ if key not in self._cache:
22
+ return None
23
+ self._cache.move_to_end(key)
24
+ return self._cache[key]
25
+
26
+ def add(self, key: str, value: T) -> None:
27
+ """Add item to cache with LRU eviction when full."""
28
+ if key in self._cache:
29
+ self._cache.move_to_end(key)
30
+ else:
31
+ self._cache[key] = value
32
+ if len(self._cache) > self._max_size:
33
+ self._cache.popitem(last=False)
34
+
35
+ self._check_memory_usage()
36
+
37
+ def clear(self) -> None:
38
+ """Clear all items from cache."""
39
+ self._cache.clear()
40
+ _warned_thresholds.clear()
41
+
42
+ def __len__(self) -> int:
43
+ return len(self._cache)
44
+
45
+ def _check_memory_usage(self) -> None:
46
+ """Check memory usage and warn at threshold crossings."""
47
+ process = psutil.Process()
48
+ memory_gb = process.memory_info().rss / (1024**3)
49
+
50
+ for threshold in _MEMORY_THRESHOLDS_GB:
51
+ if memory_gb >= threshold and threshold not in _warned_thresholds:
52
+ logger.warning(
53
+ f"Memory usage has reached {memory_gb:.2f}GB (threshold: {threshold}GB). "
54
+ f"Cache contains {len(self._cache)} items."
55
+ )
56
+ _warned_thresholds.add(threshold)
@@ -3,11 +3,14 @@ from uuid import uuid4
3
3
 
4
4
  from pydantic import BaseModel, Field
5
5
 
6
+ from .cache import LRUCache
6
7
  from .dataset import Dataset
7
8
  from .dynamic import Dynamic
8
9
  from .policy import Policy
9
10
  from .tax_benefit_model_version import TaxBenefitModelVersion
10
11
 
12
+ _cache: LRUCache["Simulation"] = LRUCache(max_size=100)
13
+
11
14
 
12
15
  class Simulation(BaseModel):
13
16
  id: str = Field(default_factory=lambda: str(uuid4()))
@@ -25,12 +28,17 @@ class Simulation(BaseModel):
25
28
  self.tax_benefit_model_version.run(self)
26
29
 
27
30
  def ensure(self):
31
+ cached_result = _cache.get(self.id)
32
+ if cached_result:
33
+ return cached_result
28
34
  try:
29
35
  self.tax_benefit_model_version.load(self)
30
36
  except Exception:
31
37
  self.run()
32
38
  self.save()
33
39
 
40
+ _cache.add(self.id, self)
41
+
34
42
  def save(self):
35
43
  """Save the simulation's output dataset."""
36
44
  self.tax_benefit_model_version.save(self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine
3
- Version: 3.1.8
3
+ Version: 3.1.9
4
4
  Summary: A package to conduct policy analysis using PolicyEngine tax-benefit models.
5
5
  Author-email: PolicyEngine <hello@policyengine.org>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -673,6 +673,7 @@ Requires-Dist: pandas>=2.0.0
673
673
  Requires-Dist: microdf_python
674
674
  Requires-Dist: plotly>=5.0.0
675
675
  Requires-Dist: requests>=2.31.0
676
+ Requires-Dist: psutil>=5.9.0
676
677
  Provides-Extra: uk
677
678
  Requires-Dist: policyengine_core>=3.10; extra == "uk"
678
679
  Requires-Dist: policyengine-uk>=2.51.0; extra == "uk"
@@ -1,6 +1,7 @@
1
1
  policyengine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- policyengine/__pycache__/__init__.cpython-313.pyc,sha256=LQBTMmPPnJo-w-7_mvuE542bVf07bu1ONsDcLBRHLH8,175
2
+ policyengine/__pycache__/__init__.cpython-313.pyc,sha256=W_AvDMmqtW4p3mYpguIKS3z3ko3AZldZ8QOmrZNnYl4,175
3
3
  policyengine/core/__init__.py,sha256=KBVhkqzkvjWLDDwk96vquQKL63ZFuLen5AzBOBnO9pg,912
4
+ policyengine/core/cache.py,sha256=DcVVFaCt7k9PmqwlhXoNDMtJ8sF4neYP1uRqWik5QYg,1812
4
5
  policyengine/core/dataset.py,sha256=iJr9-J6w11uMRYy3EEJO9Gveku1m71AA1yzeo-0SiCs,16094
5
6
  policyengine/core/dataset_version.py,sha256=6KeFCRGQto_Yyl4QY4Vo2JFythjaXrNAOHQiwRGESyM,378
6
7
  policyengine/core/dynamic.py,sha256=ng9BjDzxdwjJ0e7zoqXFmq33E1SRbaaPYfW7pjRSSzI,1641
@@ -8,7 +9,7 @@ policyengine/core/output.py,sha256=cCW4vbzkLdQaT_nJTyDJBl7Hubm7nZeRuR7aVG1dKvg,6
8
9
  policyengine/core/parameter.py,sha256=8RKKuGCDW1OoHPoXI9vF3JY6COc1qhUtMolXTUxPoEs,626
9
10
  policyengine/core/parameter_value.py,sha256=ZRBZWFYtaY9TqdgjrCymzOZNmuKOBZsrWBET24DIJ_Q,434
10
11
  policyengine/core/policy.py,sha256=ExMrUDMvNk_uuOL0cSm0UCzDyGka0t_yk6x4U0Kp6Ww,1635
11
- policyengine/core/simulation.py,sha256=yvvved75XMcGP3Bj9E2tmKRxvI-DQVZv7k4uTETwBm0,1134
12
+ policyengine/core/simulation.py,sha256=_drlY5C41I8_V6RibtdDIdl1lJ757akIeIdViFMizbA,1357
12
13
  policyengine/core/tax_benefit_model.py,sha256=2Yc1RlQrUG7djDMZbJOQH4Ns86_lOnLeISCGR4-9zMo,176
13
14
  policyengine/core/tax_benefit_model_version.py,sha256=V1CGft5Y6YflMASx0wR3V73jr-WqQu2R8N5QVMRm9yw,2752
14
15
  policyengine/core/variable.py,sha256=AjSImORlRkh05xhYxyeT6GFMOfViRzYg0qRQAIj-mxo,350
@@ -32,8 +33,8 @@ policyengine/utils/__init__.py,sha256=1X-VYAWLyB9A0YRHwsGWrqQHns1WfeZ7ISC6DMU5my
32
33
  policyengine/utils/dates.py,sha256=HnAqyl8S8EOYp8ibsnMTmECYoDWCSqwL-7A2_qKgxSc,1510
33
34
  policyengine/utils/parametric_reforms.py,sha256=4P3U39-4pYTU4BN6JjgmVLUkCkBhRfZJ6UIWTlsjyQE,1155
34
35
  policyengine/utils/plotting.py,sha256=ZAzTWz38vIaW0c3Nt4Un1kfrNoXLyHCDd1pEJIlsRg4,5335
35
- policyengine-3.1.8.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
36
- policyengine-3.1.8.dist-info/METADATA,sha256=h0r-m8cflbRqVtwajLnbgxmrKmowdeWUpXHVwLRLIGw,45889
37
- policyengine-3.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- policyengine-3.1.8.dist-info/top_level.txt,sha256=_23UPobfkneHQkpJ0e0OmDJfhCUfoXj_F2sTckCGOH4,13
39
- policyengine-3.1.8.dist-info/RECORD,,
36
+ policyengine-3.1.9.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
37
+ policyengine-3.1.9.dist-info/METADATA,sha256=x-6iT0pQLAvHjgtIeZvyauWML0sZGJJ3oeIKQoc-3aU,45918
38
+ policyengine-3.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
39
+ policyengine-3.1.9.dist-info/top_level.txt,sha256=_23UPobfkneHQkpJ0e0OmDJfhCUfoXj_F2sTckCGOH4,13
40
+ policyengine-3.1.9.dist-info/RECORD,,