dependency-cache 0.1.0__tar.gz → 0.1.1__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.
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/.github/workflows/Test.yml +2 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/PKG-INFO +12 -4
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/README.md +10 -2
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/pyproject.toml +2 -2
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/dependency_cache/dependency_cache.pyi +4 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/test_python.py +47 -10
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/test_python_automagic.py +9 -9
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/decorator.rs +1 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/decorator_factory.rs +37 -2
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/dependency_cache_base.rs +55 -3
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/uv.lock +1 -1
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/.github/workflows/CI.yml +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/.gitignore +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/Cargo.lock +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/Cargo.toml +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/LICENSE +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/dependency_cache/__init__.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/dependency_cache/plot_dependency_graph.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/automagic_dependency_example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/function_calls_example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/inheritance_example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/manual_dependency_example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/use_cache_example.py +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/dependency_graph.rs +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/lib.rs +0 -0
- {dependency_cache-0.1.0 → dependency_cache-0.1.1}/src/normalise_method_args.rs +0 -0
|
@@ -5,6 +5,7 @@ on:
|
|
|
5
5
|
branches: [ "master" ]
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [ "master" ]
|
|
8
|
+
types: [ opened, synchronize, reopened, ready_for_review ]
|
|
8
9
|
|
|
9
10
|
env:
|
|
10
11
|
CARGO_TERM_COLOR: always
|
|
@@ -12,6 +13,7 @@ env:
|
|
|
12
13
|
jobs:
|
|
13
14
|
build:
|
|
14
15
|
runs-on: ubuntu-latest
|
|
16
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
|
|
15
17
|
|
|
16
18
|
steps:
|
|
17
19
|
- uses: actions/checkout@v4
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dependency_cache
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
7
|
Requires-Dist: matplotlib>=3.7.5
|
|
8
8
|
Requires-Dist: networkx>=3.1
|
|
9
9
|
License-File: LICENSE
|
|
10
|
-
Summary: A caching system
|
|
10
|
+
Summary: A caching system for object methods that utilises a dependency graph to track relationships and trigger invalidation
|
|
11
11
|
Keywords: caching,dependency-graph,invalidation
|
|
12
12
|
License: MIT
|
|
13
13
|
Requires-Python: >=3.8
|
|
@@ -24,13 +24,21 @@ A library for managing the caching of an object's methods with cache invalidatio
|
|
|
24
24
|
Instead of recomputing expensive, deeply nested calculations on every call, Dependency Cache stores the result and only invalidates (and recalculates) it when one of its dependencies actually changes.
|
|
25
25
|
This project is written in rust, with [pyo3](https://github.com/PyO3/pyo3), and compiled using [maturin](https://github.com/PyO3/maturin).
|
|
26
26
|
|
|
27
|
+
### Installation
|
|
28
|
+
|
|
29
|
+
Install the latest stable version from [PyPI](https://pypi.org/project/dependency-cache/):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install dependency-cache
|
|
33
|
+
```
|
|
34
|
+
|
|
27
35
|
### API Overview
|
|
28
36
|
|
|
29
37
|
| Export | What it's for |
|
|
30
38
|
|---|---|
|
|
31
39
|
| `DependencyCacheBase` | Base class to inherit from. Gives your instance a cache and a dependency graph. |
|
|
32
|
-
| `dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=False)` | A footgun-enabled
|
|
33
|
-
| `automagically_dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=True)` | A decorator which **automagically infers** the direct dependencies
|
|
40
|
+
| `dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=False)` | A footgun-enabled decorator for a method where you **explicitly declare** all direct dependencies. |
|
|
41
|
+
| `automagically_dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=True)` | A decorator which **automagically infers** the direct dependencies. Optionally override the defaults and inference using the `dependencies` parameter. |
|
|
34
42
|
| `plot_dependency_graph(obj, **kwargs)` | Visualizes an instance's dependency graph, for inspection/debugging. |
|
|
35
43
|
|
|
36
44
|
### Setup
|
|
@@ -6,13 +6,21 @@ A library for managing the caching of an object's methods with cache invalidatio
|
|
|
6
6
|
Instead of recomputing expensive, deeply nested calculations on every call, Dependency Cache stores the result and only invalidates (and recalculates) it when one of its dependencies actually changes.
|
|
7
7
|
This project is written in rust, with [pyo3](https://github.com/PyO3/pyo3), and compiled using [maturin](https://github.com/PyO3/maturin).
|
|
8
8
|
|
|
9
|
+
### Installation
|
|
10
|
+
|
|
11
|
+
Install the latest stable version from [PyPI](https://pypi.org/project/dependency-cache/):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install dependency-cache
|
|
15
|
+
```
|
|
16
|
+
|
|
9
17
|
### API Overview
|
|
10
18
|
|
|
11
19
|
| Export | What it's for |
|
|
12
20
|
|---|---|
|
|
13
21
|
| `DependencyCacheBase` | Base class to inherit from. Gives your instance a cache and a dependency graph. |
|
|
14
|
-
| `dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=False)` | A footgun-enabled
|
|
15
|
-
| `automagically_dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=True)` | A decorator which **automagically infers** the direct dependencies
|
|
22
|
+
| `dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=False)` | A footgun-enabled decorator for a method where you **explicitly declare** all direct dependencies. |
|
|
23
|
+
| `automagically_dependency_cached(use_cache=True, dependencies=[...], track_runtime_dependencies=True)` | A decorator which **automagically infers** the direct dependencies. Optionally override the defaults and inference using the `dependencies` parameter. |
|
|
16
24
|
| `plot_dependency_graph(obj, **kwargs)` | Visualizes an instance's dependency graph, for inspection/debugging. |
|
|
17
25
|
|
|
18
26
|
### Setup
|
|
@@ -11,8 +11,8 @@ classifiers = [
|
|
|
11
11
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
12
12
|
]
|
|
13
13
|
keywords = ["caching", "dependency-graph", "invalidation"]
|
|
14
|
-
version = "0.1.
|
|
15
|
-
description = "A caching system
|
|
14
|
+
version = "0.1.1"
|
|
15
|
+
description = "A caching system for object methods that utilises a dependency graph to track relationships and trigger invalidation"
|
|
16
16
|
readme = "README.md"
|
|
17
17
|
license = { text = "MIT" }
|
|
18
18
|
dependencies = [
|
{dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/dependency_cache/dependency_cache.pyi
RENAMED
|
@@ -3,11 +3,13 @@ from typing import Any, final
|
|
|
3
3
|
class DependencyCacheBase:
|
|
4
4
|
def __new__(cls, /, *_args, **_kwargs) -> DependencyCacheBase: ...
|
|
5
5
|
def clear_cache(self, /) -> None: ...
|
|
6
|
+
def dump_cache(self, /) -> dict: ...
|
|
6
7
|
def get_cached_value(self, /, method_name: str, **kwargs) -> Any | None: ...
|
|
7
8
|
def get_cached_value_by_hash(self, /, hash: int) -> Any | None: ...
|
|
8
9
|
def get_cached_values(self, /) -> dict: ...
|
|
9
10
|
def get_dependency_graph(self, /) -> dict: ...
|
|
10
11
|
def get_validation_state(self, /) -> dict: ...
|
|
12
|
+
def load_cache(self, /, data: dict) -> None: ...
|
|
11
13
|
def update_cached_value(
|
|
12
14
|
self, /, method_name: str, value: Any, **kwargs
|
|
13
15
|
) -> None: ...
|
|
@@ -21,6 +23,7 @@ class automagically_dependency_cached:
|
|
|
21
23
|
use_cache: bool = True,
|
|
22
24
|
dependencies: Any | None = None,
|
|
23
25
|
track_runtime_dependencies: bool = True,
|
|
26
|
+
serialisable: bool = False,
|
|
24
27
|
) -> automagically_dependency_cached: ...
|
|
25
28
|
|
|
26
29
|
@final
|
|
@@ -32,4 +35,5 @@ class dependency_cached:
|
|
|
32
35
|
use_cache: bool = True,
|
|
33
36
|
dependencies: Any | None = None,
|
|
34
37
|
track_runtime_dependencies: bool = False,
|
|
38
|
+
serialisable: bool = False,
|
|
35
39
|
) -> dependency_cached: ...
|
|
@@ -11,15 +11,6 @@ class IncorrectInheritance:
|
|
|
11
11
|
return 1
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class IncorrectMethod(DependencyCacheBase):
|
|
15
|
-
def __init__(self):
|
|
16
|
-
super().__init__()
|
|
17
|
-
|
|
18
|
-
@dependency_cached()
|
|
19
|
-
def A():
|
|
20
|
-
return 1
|
|
21
|
-
|
|
22
|
-
|
|
23
14
|
class SimpleTestObj(DependencyCacheBase):
|
|
24
15
|
def __init__(self, x, y):
|
|
25
16
|
super().__init__()
|
|
@@ -130,14 +121,41 @@ class FunctionCallObj(DependencyCacheBase):
|
|
|
130
121
|
return total
|
|
131
122
|
|
|
132
123
|
|
|
124
|
+
class SerialisableObj(DependencyCacheBase):
|
|
125
|
+
@dependency_cached(serialisable=True)
|
|
126
|
+
def A(self):
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
@dependency_cached(serialisable=True)
|
|
130
|
+
def B(self):
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
@dependency_cached(dependencies=["A", "B"])
|
|
134
|
+
def C(self):
|
|
135
|
+
a = self.A()
|
|
136
|
+
b = self.B()
|
|
137
|
+
if a and b:
|
|
138
|
+
return a + b
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
133
142
|
def test_raises_typeerror():
|
|
134
|
-
c = IncorrectInheritance()
|
|
135
143
|
with pytest.raises(TypeError):
|
|
144
|
+
c = IncorrectInheritance()
|
|
136
145
|
c.A()
|
|
137
146
|
|
|
138
147
|
|
|
139
148
|
def test_incorrect_method_raises_valueerror():
|
|
140
149
|
with pytest.raises(TypeError):
|
|
150
|
+
|
|
151
|
+
class IncorrectMethod(DependencyCacheBase):
|
|
152
|
+
def __init__(self):
|
|
153
|
+
super().__init__()
|
|
154
|
+
|
|
155
|
+
@dependency_cached()
|
|
156
|
+
def A():
|
|
157
|
+
return 1
|
|
158
|
+
|
|
141
159
|
c = IncorrectMethod()
|
|
142
160
|
c.A()
|
|
143
161
|
|
|
@@ -308,3 +326,22 @@ def test_incorrect_decorator_format():
|
|
|
308
326
|
@dependency_cached()
|
|
309
327
|
def B(self):
|
|
310
328
|
return 2
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
@pytest.mark.parametrize(
|
|
332
|
+
("data", "result"),
|
|
333
|
+
[
|
|
334
|
+
({"A": 1, "B": 2}, 3),
|
|
335
|
+
({"A": 1.45, "B": 2.55}, 4.0),
|
|
336
|
+
({"A": "1", "B": "2"}, "12"),
|
|
337
|
+
({"A": [1], "B": [2]}, [1, 2]),
|
|
338
|
+
],
|
|
339
|
+
)
|
|
340
|
+
def test_serialising_data(data, result):
|
|
341
|
+
obj = SerialisableObj()
|
|
342
|
+
|
|
343
|
+
obj.load_cache(data)
|
|
344
|
+
|
|
345
|
+
assert obj.C() is not None
|
|
346
|
+
|
|
347
|
+
assert obj.C() == result
|
|
@@ -11,15 +11,6 @@ class IncorrectInheritance:
|
|
|
11
11
|
return 1
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class IncorrectMethod(DependencyCacheBase):
|
|
15
|
-
def __init__(self):
|
|
16
|
-
super().__init__()
|
|
17
|
-
|
|
18
|
-
@automagically_dependency_cached()
|
|
19
|
-
def A():
|
|
20
|
-
return 1
|
|
21
|
-
|
|
22
|
-
|
|
23
14
|
class SimpleTestObj(DependencyCacheBase):
|
|
24
15
|
def __init__(self, x, y):
|
|
25
16
|
super().__init__()
|
|
@@ -138,6 +129,15 @@ def test_raises_typeerror():
|
|
|
138
129
|
|
|
139
130
|
def test_incorrect_method_raises_valueerror():
|
|
140
131
|
with pytest.raises(TypeError):
|
|
132
|
+
|
|
133
|
+
class IncorrectMethod(DependencyCacheBase):
|
|
134
|
+
def __init__(self):
|
|
135
|
+
super().__init__()
|
|
136
|
+
|
|
137
|
+
@automagically_dependency_cached()
|
|
138
|
+
def A():
|
|
139
|
+
return 1
|
|
140
|
+
|
|
141
141
|
c = IncorrectMethod()
|
|
142
142
|
c.A()
|
|
143
143
|
|
|
@@ -6,6 +6,26 @@ use crate::decorator::DependencyCacheDecorator;
|
|
|
6
6
|
use crate::normalise_method_args::normalise_and_hash_method;
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
pub fn validate_self_only_method(py: Python<'_>, func: &Bound<'_, PyAny>) -> PyResult<()> {
|
|
10
|
+
let inspect = py.import("inspect")?;
|
|
11
|
+
let builtins = py.import("builtins")?;
|
|
12
|
+
let signature = inspect.call_method1("signature", (func,))?;
|
|
13
|
+
// really ugly, but the inspect.Signature type is not extractable
|
|
14
|
+
let parameters = signature.getattr("parameters")?;
|
|
15
|
+
let list_obj = builtins.call_method1("list", (parameters,))?;
|
|
16
|
+
let param_names: Vec<String> = list_obj.extract()?;
|
|
17
|
+
|
|
18
|
+
if param_names.len() != 1 || param_names[0] != "self" {
|
|
19
|
+
let msg = format!(
|
|
20
|
+
"Serialisable method must have exactly one parameter named 'self', got: {:?}",
|
|
21
|
+
param_names
|
|
22
|
+
);
|
|
23
|
+
return Err(PyValueError::new_err(msg));
|
|
24
|
+
}
|
|
25
|
+
Ok(())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
9
29
|
fn parse_dependencies(py: Python<'_>, dep_list: &Bound<'_, PyAny>) -> PyResult<Vec<(String, Py<PyDict>)>> {
|
|
10
30
|
let list = dep_list.cast::<PyList>()?;
|
|
11
31
|
let mut parsed = Vec::with_capacity(list.len());
|
|
@@ -40,17 +60,20 @@ pub struct ManualDependencyCacheDecoratorFactory {
|
|
|
40
60
|
use_cache: bool,
|
|
41
61
|
dependencies: Vec<(String, Py<PyDict>)>,
|
|
42
62
|
track_runtime_dependencies: bool,
|
|
63
|
+
serialisable: bool,
|
|
43
64
|
}
|
|
44
65
|
|
|
45
66
|
#[pymethods]
|
|
46
67
|
impl ManualDependencyCacheDecoratorFactory {
|
|
68
|
+
|
|
47
69
|
#[new]
|
|
48
|
-
#[pyo3(signature = (use_cache=true, dependencies=None, track_runtime_dependencies=false))]
|
|
70
|
+
#[pyo3(signature = (use_cache=true, dependencies=None, track_runtime_dependencies=false, serialisable=false))]
|
|
49
71
|
fn new(
|
|
50
72
|
py: Python<'_>,
|
|
51
73
|
use_cache: bool,
|
|
52
74
|
dependencies: Option<&Bound<'_, PyAny>>,
|
|
53
75
|
track_runtime_dependencies: bool,
|
|
76
|
+
serialisable: bool,
|
|
54
77
|
) -> PyResult<Self> {
|
|
55
78
|
let parsed_deps = if let Some(list) = dependencies {
|
|
56
79
|
parse_dependencies(py, list)?
|
|
@@ -61,6 +84,7 @@ impl ManualDependencyCacheDecoratorFactory {
|
|
|
61
84
|
use_cache,
|
|
62
85
|
dependencies: parsed_deps,
|
|
63
86
|
track_runtime_dependencies,
|
|
87
|
+
serialisable,
|
|
64
88
|
});
|
|
65
89
|
}
|
|
66
90
|
|
|
@@ -81,12 +105,16 @@ impl ManualDependencyCacheDecoratorFactory {
|
|
|
81
105
|
Ok(hash)
|
|
82
106
|
})
|
|
83
107
|
.collect::<PyResult<Vec<_>>>()?;
|
|
108
|
+
if self.serialisable {
|
|
109
|
+
validate_self_only_method(py, func.bind(py))?;
|
|
110
|
+
}
|
|
84
111
|
return Ok(DependencyCacheDecorator {
|
|
85
112
|
func,
|
|
86
113
|
use_cache: self.use_cache,
|
|
87
114
|
dependencies: hashed_dependencies,
|
|
88
115
|
method_name,
|
|
89
116
|
track_runtime_dependencies: self.track_runtime_dependencies,
|
|
117
|
+
serialisable: self.serialisable,
|
|
90
118
|
});
|
|
91
119
|
}
|
|
92
120
|
}
|
|
@@ -96,17 +124,19 @@ pub struct AutomagicDependencyCacheDecoratorFactory {
|
|
|
96
124
|
use_cache: bool,
|
|
97
125
|
dependencies: Vec<(String, Py<PyDict>)>,
|
|
98
126
|
track_runtime_dependencies: bool,
|
|
127
|
+
serialisable: bool,
|
|
99
128
|
}
|
|
100
129
|
|
|
101
130
|
#[pymethods]
|
|
102
131
|
impl AutomagicDependencyCacheDecoratorFactory {
|
|
103
132
|
#[new]
|
|
104
|
-
#[pyo3(signature = (use_cache=true, dependencies=None, track_runtime_dependencies=true))]
|
|
133
|
+
#[pyo3(signature = (use_cache=true, dependencies=None, track_runtime_dependencies=true, serialisable=false))]
|
|
105
134
|
fn new(
|
|
106
135
|
py: Python<'_>,
|
|
107
136
|
use_cache: bool,
|
|
108
137
|
dependencies: Option<&Bound<'_, PyAny>>,
|
|
109
138
|
track_runtime_dependencies: bool,
|
|
139
|
+
serialisable: bool,
|
|
110
140
|
) -> PyResult<Self> {
|
|
111
141
|
let parsed_deps = if let Some(list) = dependencies {
|
|
112
142
|
parse_dependencies(py, list)?
|
|
@@ -117,6 +147,7 @@ impl AutomagicDependencyCacheDecoratorFactory {
|
|
|
117
147
|
use_cache,
|
|
118
148
|
dependencies: parsed_deps,
|
|
119
149
|
track_runtime_dependencies,
|
|
150
|
+
serialisable,
|
|
120
151
|
});
|
|
121
152
|
}
|
|
122
153
|
|
|
@@ -137,12 +168,16 @@ impl AutomagicDependencyCacheDecoratorFactory {
|
|
|
137
168
|
Ok(hash)
|
|
138
169
|
})
|
|
139
170
|
.collect::<PyResult<Vec<_>>>()?;
|
|
171
|
+
if self.serialisable {
|
|
172
|
+
validate_self_only_method(py, func.bind(py))?;
|
|
173
|
+
}
|
|
140
174
|
return Ok(DependencyCacheDecorator {
|
|
141
175
|
func,
|
|
142
176
|
use_cache: self.use_cache,
|
|
143
177
|
dependencies: hashed_dependencies,
|
|
144
178
|
method_name,
|
|
145
179
|
track_runtime_dependencies: self.track_runtime_dependencies,
|
|
180
|
+
serialisable: self.serialisable,
|
|
146
181
|
});
|
|
147
182
|
}
|
|
148
183
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
use pyo3::prelude::*;
|
|
2
|
-
use pyo3::types::{PyDict, PyTuple, PyString, PySet};
|
|
2
|
+
use pyo3::types::{PyDict, PyTuple, PyString, PySet, PyType};
|
|
3
|
+
use pyo3::exceptions::PyValueError;
|
|
3
4
|
|
|
4
|
-
use std::collections::{HashMap};
|
|
5
|
+
use std::collections::{HashMap, HashSet};
|
|
5
6
|
|
|
6
7
|
use crate::dependency_graph::{MethodDependencyGraph, ValidationState};
|
|
7
8
|
use crate::normalise_method_args::normalise_and_hash_method;
|
|
8
|
-
|
|
9
|
+
use crate::decorator::DependencyCacheDecorator;
|
|
9
10
|
|
|
10
11
|
#[pyclass(subclass)]
|
|
11
12
|
pub struct DependencyCacheBase {
|
|
@@ -269,4 +270,55 @@ impl DependencyCacheBase {
|
|
|
269
270
|
}
|
|
270
271
|
Ok(dict)
|
|
271
272
|
}
|
|
273
|
+
|
|
274
|
+
pub fn dump_cache<'py>(slf: &Bound<'py, Self>, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
|
|
275
|
+
let cls = slf.get_type();
|
|
276
|
+
|
|
277
|
+
let mut visited = HashSet::new();
|
|
278
|
+
let mut serialisable_methods = Vec::new();
|
|
279
|
+
|
|
280
|
+
for mro_class in cls.mro().iter() {
|
|
281
|
+
let mro_class: Bound<'_, PyType> = mro_class.extract()?;
|
|
282
|
+
let namespace = mro_class.getattr("__dict__")?;
|
|
283
|
+
for item in namespace.call_method0("items")?.try_iter()? {
|
|
284
|
+
let (name, value): (String, Bound<'_, PyAny>) = item?.extract()?;
|
|
285
|
+
if name.starts_with("__") || !visited.insert(name.clone()) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
if let Ok(decorator) = value.cast::<DependencyCacheDecorator>() {
|
|
289
|
+
if decorator.borrow().serialisable {
|
|
290
|
+
serialisable_methods.push(name);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
let result = PyDict::new(py);
|
|
297
|
+
for method_name in serialisable_methods {
|
|
298
|
+
let value = slf.call_method(&method_name, (), None)?;
|
|
299
|
+
result.set_item(method_name, value)?;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Ok(result)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
pub fn load_cache<'py>(
|
|
306
|
+
slf: &Bound<'_, Self>,
|
|
307
|
+
py: Python<'py>,
|
|
308
|
+
data: Bound<'py, PyDict>,
|
|
309
|
+
) -> PyResult<()> {
|
|
310
|
+
for (key, loaded_value) in data.iter() {
|
|
311
|
+
let method_name: String = key.extract()?;
|
|
312
|
+
|
|
313
|
+
let _ = slf.call_method(&method_name, (), None)?;
|
|
314
|
+
|
|
315
|
+
let empty_args = PyTuple::empty(py);
|
|
316
|
+
let (hash, _) = normalise_and_hash_method(py, &method_name, None, &empty_args, None)
|
|
317
|
+
.map_err(|e| PyValueError::new_err(format!("Failed to hash '{}': {}", method_name, e)))?;
|
|
318
|
+
|
|
319
|
+
slf.borrow_mut().cache.insert(hash, loaded_value.unbind());
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
Ok(())
|
|
323
|
+
}
|
|
272
324
|
}
|
|
@@ -329,7 +329,7 @@ wheels = [
|
|
|
329
329
|
|
|
330
330
|
[[package]]
|
|
331
331
|
name = "dependency-cache"
|
|
332
|
-
version = "0.1.
|
|
332
|
+
version = "0.1.1"
|
|
333
333
|
source = { editable = "." }
|
|
334
334
|
dependencies = [
|
|
335
335
|
{ name = "matplotlib", version = "3.7.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/dependency_cache/plot_dependency_graph.py
RENAMED
|
File without changes
|
{dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/automagic_dependency_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dependency_cache-0.1.0 → dependency_cache-0.1.1}/python/examples/manual_dependency_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|