bagofholding 0.0.3__tar.gz → 0.1.0__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.
- {bagofholding-0.0.3 → bagofholding-0.1.0}/PKG-INFO +52 -48
- {bagofholding-0.0.3/cached-miniforge/my-env/lib/python3.1/site-packages → bagofholding-0.1.0}/bagofholding/__init__.py +1 -1
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/_version.py +2 -2
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/content.py +10 -0
- {bagofholding-0.0.3/cached-miniforge/my-env/lib/python3.1/site-packages → bagofholding-0.1.0}/bagofholding/exceptions.py +1 -1
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/retrieve.py +2 -2
- {bagofholding-0.0.3/cached-miniforge/my-env/lib/python3.1/site-packages → bagofholding-0.1.0}/bagofholding/trie.py +6 -3
- {bagofholding-0.0.3 → bagofholding-0.1.0/cached-miniforge/my-env/lib/python3.1/site-packages}/bagofholding/__init__.py +1 -1
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/_version.py +2 -2
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/content.py +10 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0/cached-miniforge/my-env/lib/python3.1/site-packages}/bagofholding/exceptions.py +1 -1
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/retrieve.py +2 -2
- {bagofholding-0.0.3 → bagofholding-0.1.0/cached-miniforge/my-env/lib/python3.1/site-packages}/bagofholding/trie.py +6 -3
- {bagofholding-0.0.3 → bagofholding-0.1.0}/docs/README.md +49 -45
- {bagofholding-0.0.3 → bagofholding-0.1.0}/pyproject.toml +2 -2
- {bagofholding-0.0.3 → bagofholding-0.1.0}/.gitignore +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/LICENSE +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/bag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/__init__.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/bag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/content.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/context.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/dtypes.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/h5/triebag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/metadata.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/bagofholding/widget.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/bag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/__init__.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/bag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/content.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/context.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/dtypes.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/h5/triebag.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/metadata.py +0 -0
- {bagofholding-0.0.3 → bagofholding-0.1.0}/cached-miniforge/my-env/lib/python3.1/site-packages/bagofholding/widget.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bagofholding
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: bagofholding - browsable, partially-reloadable serialization for pickleable python objects.
|
|
5
5
|
Project-URL: Homepage, https://pyiron.org/
|
|
6
6
|
Project-URL: Documentation, https://bagofholding.readthedocs.io
|
|
@@ -36,14 +36,14 @@ License: BSD 3-Clause License
|
|
|
36
36
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
37
37
|
License-File: LICENSE
|
|
38
38
|
Keywords: pyiron
|
|
39
|
-
Classifier: Development Status ::
|
|
39
|
+
Classifier: Development Status :: 4 - Beta
|
|
40
40
|
Classifier: Intended Audience :: Science/Research
|
|
41
41
|
Classifier: License :: OSI Approved :: BSD License
|
|
42
42
|
Classifier: Operating System :: OS Independent
|
|
43
43
|
Classifier: Programming Language :: Python :: 3.12
|
|
44
44
|
Classifier: Programming Language :: Python :: 3.13
|
|
45
45
|
Classifier: Topic :: Scientific/Engineering
|
|
46
|
-
Requires-Python: <3.14,>=3.
|
|
46
|
+
Requires-Python: <3.14,>=3.11
|
|
47
47
|
Requires-Dist: bidict==0.23.1
|
|
48
48
|
Requires-Dist: h5py<3.15.0,>=3.14.0
|
|
49
49
|
Requires-Dist: mpi4py<4.1.0,>=4.0.1
|
|
@@ -57,12 +57,24 @@ Description-Content-Type: text/markdown
|
|
|
57
57
|
|
|
58
58
|
# bagofholding
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
<img src="_static/bagofholding_logo.png" alt="Logo" width="190"/>
|
|
61
|
+
|
|
62
|
+
[](https://mybinder.org/v2/gh/pyiron/bagofholding/HEAD)
|
|
63
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
64
|
+
[](https://codecov.io/gh/pyiron/bagofholding)
|
|
65
|
+
[](https://bagofholding.readthedocs.io/en/latest/?badge=latest)
|
|
66
|
+
|
|
67
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
68
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
69
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
70
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
71
|
+
|
|
72
|
+
`bagofholding` is designed to be an easy stand-in for `pickle` serialization for python objects that is transparent, flexible, and suitable for long-term storage.
|
|
61
73
|
|
|
62
74
|
## Advantages
|
|
63
75
|
### Drop-in replacement
|
|
64
76
|
|
|
65
|
-
`bagofholding` stores
|
|
77
|
+
`bagofholding` stores `pickle`-able python objects, and can be easily used as a drop-in replacement for `pickle` serialization:
|
|
66
78
|
|
|
67
79
|
```python
|
|
68
80
|
>>> import bagofholding as boh
|
|
@@ -76,7 +88,7 @@ Description-Content-Type: text/markdown
|
|
|
76
88
|
|
|
77
89
|
### Browseable
|
|
78
90
|
|
|
79
|
-
The contents of stored objects can be browsed without
|
|
91
|
+
The contents of stored objects can be browsed without re-instantiating any of the stored data.
|
|
80
92
|
In the example above, we saw that saving is a class-method, while loading is an instance method.
|
|
81
93
|
We can grab the "bag" instance and use it to peek at what's inside!
|
|
82
94
|
|
|
@@ -130,53 +142,32 @@ With only `bagofholding` and `numpy` installed, the end user can browse through
|
|
|
130
142
|
|
|
131
143
|
### Version control
|
|
132
144
|
|
|
133
|
-
In the examples above, we saw that version (and of course package) information is part of the stored metadata.
|
|
134
|
-
This is useful post-facto for knowing what packages need to be installed to properly load your serialized data.
|
|
135
|
-
You can also specify at load-time how strict or relaxed `bagofholding` should be in re-instantiating data if a stored version does not match the currently installed version,
|
|
145
|
+
In the examples above, we saw that version (and of course package) information is part of the automatically-scraped and stored metadata.
|
|
146
|
+
This is useful post-facto for knowing what packages need to be installed to properly load your serialized data, and allows us to fail in clean and helpful ways if the loading environment does not match the saving environment.
|
|
147
|
+
You can also specify at load-time how strict or relaxed `bagofholding` should be in re-instantiating data if a stored version does not match the currently installed version, giving flexible protection from flawed re-instantiations.
|
|
136
148
|
|
|
137
149
|
`bagofholding` also provides tools to act on this data a-priori.
|
|
138
150
|
To increase the likelihood that stored data will be accessible in the future, you can outlaw any (sub)objects coming from particular modules:
|
|
139
151
|
|
|
140
152
|
```python
|
|
141
|
-
import bagofholding
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
boh.
|
|
145
|
-
...
|
|
146
|
-
|
|
147
|
-
print(e)
|
|
148
|
-
Module
|
|
149
|
-
'__main__' is forbidden as a
|
|
150
|
-
source
|
|
151
|
-
of
|
|
152
|
-
stored
|
|
153
|
-
objects.Change
|
|
154
|
-
the
|
|
155
|
-
`forbidden_modules` or move
|
|
156
|
-
this
|
|
157
|
-
object
|
|
158
|
-
to
|
|
159
|
-
an
|
|
160
|
-
allowed
|
|
161
|
-
module.
|
|
153
|
+
import bagofholding as boh
|
|
154
|
+
>>> try:
|
|
155
|
+
... boh.H5Bag.save(something, "will_fail.h5", forbidden_modules=("__main__",))
|
|
156
|
+
... except boh.ModuleForbiddenError as e:
|
|
157
|
+
... print(e)
|
|
158
|
+
Module '__main__' is forbidden as a source of stored objects. Change the `forbidden_modules` or move this object to an allowed module.
|
|
162
159
|
|
|
163
160
|
```
|
|
164
161
|
|
|
165
|
-
And/or demand that all objects have an identifiable version
|
|
162
|
+
And/or demand that all objects have an identifiable version:
|
|
166
163
|
|
|
167
164
|
```python
|
|
168
|
-
import bagofholding
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
boh.
|
|
172
|
-
...
|
|
173
|
-
|
|
174
|
-
print(e)
|
|
175
|
-
Could
|
|
176
|
-
not find
|
|
177
|
-
a
|
|
178
|
-
version
|
|
179
|
-
for __main__.Either disable `require_versions`, use `version_scraping` to find an existing version for this package, or add versioning to the unversioned package.
|
|
165
|
+
import bagofholding as boh
|
|
166
|
+
>>> try:
|
|
167
|
+
... boh.H5Bag.save(something, "will_fail.h5", require_versions=True)
|
|
168
|
+
... except boh.NoVersionError as e:
|
|
169
|
+
... print(e)
|
|
170
|
+
Could not find a version for __main__. Either disable `require_versions`, use `version_scraping` to find an existing version for this package, or add versioning to the unversioned package.
|
|
180
171
|
|
|
181
172
|
```
|
|
182
173
|
|
|
@@ -195,8 +186,21 @@ H5Info(qualname='H5Bag', module='bagofholding.h5.bag', version='...', libver_str
|
|
|
195
186
|
|
|
196
187
|
For a more in-depth look at the above features and to explore other aspects of `bagofholding`, check out [the tutorial notebook](../notebooks/tutorial.ipynb).
|
|
197
188
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
|
|
190
|
+
## Object requirements
|
|
191
|
+
|
|
192
|
+
Under-the-hood, we follow the same patterns as `pickle` by explicitly invoking many of the same method (`__reduce__`, `__setstate__`, etc).
|
|
193
|
+
_Almost_ and object which can be pickled can be stored using `bagofholding`.
|
|
194
|
+
Our requirements are that the object...
|
|
195
|
+
|
|
196
|
+
- Must be pickleable
|
|
197
|
+
- You can use the `pickle_check` method on bag classes to quickly assess this
|
|
198
|
+
- Must not depend on `pickle` protocol >4
|
|
199
|
+
- Must have a valid boolean response to `hasattr` for each of the following, and they must conform to python and `abc.collections` norms if present:
|
|
200
|
+
- `__setstate__`
|
|
201
|
+
- `__setitem__`
|
|
202
|
+
- `append`
|
|
203
|
+
- `extend`
|
|
204
|
+
- Must have a valid boolean response to `hasattr` for `__metadata__`, and this attribute must be castable to a string if present
|
|
205
|
+
|
|
206
|
+
If your object satisfies these conditions and fails to "bag", please raise a bug report on the issues page!
|
|
@@ -19,7 +19,7 @@ from bagofholding.exceptions import NotAGroupError as NotAGroupError
|
|
|
19
19
|
from bagofholding.exceptions import NoVersionError as NoVersionError
|
|
20
20
|
from bagofholding.exceptions import PickleProtocolError as PickleProtocolError
|
|
21
21
|
from bagofholding.exceptions import (
|
|
22
|
-
|
|
22
|
+
StringNotImportableError as StringNotImportableError,
|
|
23
23
|
)
|
|
24
24
|
from bagofholding.h5.bag import H5Bag as H5Bag
|
|
25
25
|
from bagofholding.h5.triebag import TrieH5Bag as TrieH5Bag
|
|
@@ -35,6 +35,7 @@ from bagofholding.exceptions import (
|
|
|
35
35
|
ModuleForbiddenError,
|
|
36
36
|
NoVersionError,
|
|
37
37
|
PickleProtocolError,
|
|
38
|
+
StringNotImportableError,
|
|
38
39
|
)
|
|
39
40
|
from bagofholding.metadata import (
|
|
40
41
|
Metadata,
|
|
@@ -237,6 +238,15 @@ class Global(Item[GlobalType, Any, Packer]):
|
|
|
237
238
|
value = "builtins." + obj if "." not in obj else obj
|
|
238
239
|
else:
|
|
239
240
|
value = obj.__module__ + "." + obj.__qualname__
|
|
241
|
+
|
|
242
|
+
if "<lambda>" in value:
|
|
243
|
+
raise StringNotImportableError(
|
|
244
|
+
f"Lambda functions are not re-importable, can't pack {obj}"
|
|
245
|
+
)
|
|
246
|
+
elif "<locals>" in value:
|
|
247
|
+
raise StringNotImportableError(
|
|
248
|
+
f"Local functions are not re-importable, can't pack {obj}"
|
|
249
|
+
)
|
|
240
250
|
packer.pack_string(value, path)
|
|
241
251
|
|
|
242
252
|
@classmethod
|
|
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
from importlib import import_module
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
|
-
from bagofholding.exceptions import
|
|
10
|
+
from bagofholding.exceptions import StringNotImportableError
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def import_from_string(library_path: str) -> Any:
|
|
@@ -44,7 +44,7 @@ def get_importable_string_from_string_reduction(
|
|
|
44
44
|
try:
|
|
45
45
|
import_from_string(importable)
|
|
46
46
|
except (ModuleNotFoundError, AttributeError) as e:
|
|
47
|
-
raise
|
|
47
|
+
raise StringNotImportableError(
|
|
48
48
|
f"Couldn't import {string_reduction} after scoping it as {importable}. "
|
|
49
49
|
f"Please contact the developers so we can figure out how to handle "
|
|
50
50
|
f"this edge case."
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import random
|
|
2
|
-
from typing import cast
|
|
2
|
+
from typing import TypeVar, cast
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pygtrie
|
|
6
6
|
|
|
7
|
+
ValueType = TypeVar("ValueType") # python <3.12 compatibility
|
|
8
|
+
# def not_allowed_to_have_inline[FunctionGenerics](in_python=3.12):
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
def decompose_stringtrie(
|
|
9
12
|
trie: pygtrie.StringTrie, null_value: ValueType
|
|
10
13
|
) -> tuple[list[str], list[int], list[ValueType]]:
|
|
11
14
|
"""
|
|
@@ -63,7 +66,7 @@ def decompose_stringtrie[ValueType](
|
|
|
63
66
|
return segments, parents, values
|
|
64
67
|
|
|
65
68
|
|
|
66
|
-
def reconstruct_stringtrie
|
|
69
|
+
def reconstruct_stringtrie(
|
|
67
70
|
segments: list[str],
|
|
68
71
|
parents: list[int],
|
|
69
72
|
values: list[ValueType],
|
|
@@ -19,7 +19,7 @@ from bagofholding.exceptions import NotAGroupError as NotAGroupError
|
|
|
19
19
|
from bagofholding.exceptions import NoVersionError as NoVersionError
|
|
20
20
|
from bagofholding.exceptions import PickleProtocolError as PickleProtocolError
|
|
21
21
|
from bagofholding.exceptions import (
|
|
22
|
-
|
|
22
|
+
StringNotImportableError as StringNotImportableError,
|
|
23
23
|
)
|
|
24
24
|
from bagofholding.h5.bag import H5Bag as H5Bag
|
|
25
25
|
from bagofholding.h5.triebag import TrieH5Bag as TrieH5Bag
|
|
@@ -35,6 +35,7 @@ from bagofholding.exceptions import (
|
|
|
35
35
|
ModuleForbiddenError,
|
|
36
36
|
NoVersionError,
|
|
37
37
|
PickleProtocolError,
|
|
38
|
+
StringNotImportableError,
|
|
38
39
|
)
|
|
39
40
|
from bagofholding.metadata import (
|
|
40
41
|
Metadata,
|
|
@@ -237,6 +238,15 @@ class Global(Item[GlobalType, Any, Packer]):
|
|
|
237
238
|
value = "builtins." + obj if "." not in obj else obj
|
|
238
239
|
else:
|
|
239
240
|
value = obj.__module__ + "." + obj.__qualname__
|
|
241
|
+
|
|
242
|
+
if "<lambda>" in value:
|
|
243
|
+
raise StringNotImportableError(
|
|
244
|
+
f"Lambda functions are not re-importable, can't pack {obj}"
|
|
245
|
+
)
|
|
246
|
+
elif "<locals>" in value:
|
|
247
|
+
raise StringNotImportableError(
|
|
248
|
+
f"Local functions are not re-importable, can't pack {obj}"
|
|
249
|
+
)
|
|
240
250
|
packer.pack_string(value, path)
|
|
241
251
|
|
|
242
252
|
@classmethod
|
|
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
from importlib import import_module
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
|
-
from bagofholding.exceptions import
|
|
10
|
+
from bagofholding.exceptions import StringNotImportableError
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def import_from_string(library_path: str) -> Any:
|
|
@@ -44,7 +44,7 @@ def get_importable_string_from_string_reduction(
|
|
|
44
44
|
try:
|
|
45
45
|
import_from_string(importable)
|
|
46
46
|
except (ModuleNotFoundError, AttributeError) as e:
|
|
47
|
-
raise
|
|
47
|
+
raise StringNotImportableError(
|
|
48
48
|
f"Couldn't import {string_reduction} after scoping it as {importable}. "
|
|
49
49
|
f"Please contact the developers so we can figure out how to handle "
|
|
50
50
|
f"this edge case."
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import random
|
|
2
|
-
from typing import cast
|
|
2
|
+
from typing import TypeVar, cast
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pygtrie
|
|
6
6
|
|
|
7
|
+
ValueType = TypeVar("ValueType") # python <3.12 compatibility
|
|
8
|
+
# def not_allowed_to_have_inline[FunctionGenerics](in_python=3.12):
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
def decompose_stringtrie(
|
|
9
12
|
trie: pygtrie.StringTrie, null_value: ValueType
|
|
10
13
|
) -> tuple[list[str], list[int], list[ValueType]]:
|
|
11
14
|
"""
|
|
@@ -63,7 +66,7 @@ def decompose_stringtrie[ValueType](
|
|
|
63
66
|
return segments, parents, values
|
|
64
67
|
|
|
65
68
|
|
|
66
|
-
def reconstruct_stringtrie
|
|
69
|
+
def reconstruct_stringtrie(
|
|
67
70
|
segments: list[str],
|
|
68
71
|
parents: list[int],
|
|
69
72
|
values: list[ValueType],
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
# bagofholding
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<img src="_static/bagofholding_logo.png" alt="Logo" width="190"/>
|
|
4
|
+
|
|
5
|
+
[](https://mybinder.org/v2/gh/pyiron/bagofholding/HEAD)
|
|
6
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
7
|
+
[](https://codecov.io/gh/pyiron/bagofholding)
|
|
8
|
+
[](https://bagofholding.readthedocs.io/en/latest/?badge=latest)
|
|
9
|
+
|
|
10
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
11
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
12
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
13
|
+
[](https://anaconda.org/conda-forge/bagofholding)
|
|
14
|
+
|
|
15
|
+
`bagofholding` is designed to be an easy stand-in for `pickle` serialization for python objects that is transparent, flexible, and suitable for long-term storage.
|
|
4
16
|
|
|
5
17
|
## Advantages
|
|
6
18
|
### Drop-in replacement
|
|
7
19
|
|
|
8
|
-
`bagofholding` stores
|
|
20
|
+
`bagofholding` stores `pickle`-able python objects, and can be easily used as a drop-in replacement for `pickle` serialization:
|
|
9
21
|
|
|
10
22
|
```python
|
|
11
23
|
>>> import bagofholding as boh
|
|
@@ -19,7 +31,7 @@
|
|
|
19
31
|
|
|
20
32
|
### Browseable
|
|
21
33
|
|
|
22
|
-
The contents of stored objects can be browsed without
|
|
34
|
+
The contents of stored objects can be browsed without re-instantiating any of the stored data.
|
|
23
35
|
In the example above, we saw that saving is a class-method, while loading is an instance method.
|
|
24
36
|
We can grab the "bag" instance and use it to peek at what's inside!
|
|
25
37
|
|
|
@@ -73,53 +85,32 @@ With only `bagofholding` and `numpy` installed, the end user can browse through
|
|
|
73
85
|
|
|
74
86
|
### Version control
|
|
75
87
|
|
|
76
|
-
In the examples above, we saw that version (and of course package) information is part of the stored metadata.
|
|
77
|
-
This is useful post-facto for knowing what packages need to be installed to properly load your serialized data.
|
|
78
|
-
You can also specify at load-time how strict or relaxed `bagofholding` should be in re-instantiating data if a stored version does not match the currently installed version,
|
|
88
|
+
In the examples above, we saw that version (and of course package) information is part of the automatically-scraped and stored metadata.
|
|
89
|
+
This is useful post-facto for knowing what packages need to be installed to properly load your serialized data, and allows us to fail in clean and helpful ways if the loading environment does not match the saving environment.
|
|
90
|
+
You can also specify at load-time how strict or relaxed `bagofholding` should be in re-instantiating data if a stored version does not match the currently installed version, giving flexible protection from flawed re-instantiations.
|
|
79
91
|
|
|
80
92
|
`bagofholding` also provides tools to act on this data a-priori.
|
|
81
93
|
To increase the likelihood that stored data will be accessible in the future, you can outlaw any (sub)objects coming from particular modules:
|
|
82
94
|
|
|
83
95
|
```python
|
|
84
|
-
import bagofholding
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
boh.
|
|
88
|
-
...
|
|
89
|
-
|
|
90
|
-
print(e)
|
|
91
|
-
Module
|
|
92
|
-
'__main__' is forbidden as a
|
|
93
|
-
source
|
|
94
|
-
of
|
|
95
|
-
stored
|
|
96
|
-
objects.Change
|
|
97
|
-
the
|
|
98
|
-
`forbidden_modules` or move
|
|
99
|
-
this
|
|
100
|
-
object
|
|
101
|
-
to
|
|
102
|
-
an
|
|
103
|
-
allowed
|
|
104
|
-
module.
|
|
96
|
+
import bagofholding as boh
|
|
97
|
+
>>> try:
|
|
98
|
+
... boh.H5Bag.save(something, "will_fail.h5", forbidden_modules=("__main__",))
|
|
99
|
+
... except boh.ModuleForbiddenError as e:
|
|
100
|
+
... print(e)
|
|
101
|
+
Module '__main__' is forbidden as a source of stored objects. Change the `forbidden_modules` or move this object to an allowed module.
|
|
105
102
|
|
|
106
103
|
```
|
|
107
104
|
|
|
108
|
-
And/or demand that all objects have an identifiable version
|
|
105
|
+
And/or demand that all objects have an identifiable version:
|
|
109
106
|
|
|
110
107
|
```python
|
|
111
|
-
import bagofholding
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
boh.
|
|
115
|
-
...
|
|
116
|
-
|
|
117
|
-
print(e)
|
|
118
|
-
Could
|
|
119
|
-
not find
|
|
120
|
-
a
|
|
121
|
-
version
|
|
122
|
-
for __main__.Either disable `require_versions`, use `version_scraping` to find an existing version for this package, or add versioning to the unversioned package.
|
|
108
|
+
import bagofholding as boh
|
|
109
|
+
>>> try:
|
|
110
|
+
... boh.H5Bag.save(something, "will_fail.h5", require_versions=True)
|
|
111
|
+
... except boh.NoVersionError as e:
|
|
112
|
+
... print(e)
|
|
113
|
+
Could not find a version for __main__. Either disable `require_versions`, use `version_scraping` to find an existing version for this package, or add versioning to the unversioned package.
|
|
123
114
|
|
|
124
115
|
```
|
|
125
116
|
|
|
@@ -138,8 +129,21 @@ H5Info(qualname='H5Bag', module='bagofholding.h5.bag', version='...', libver_str
|
|
|
138
129
|
|
|
139
130
|
For a more in-depth look at the above features and to explore other aspects of `bagofholding`, check out [the tutorial notebook](../notebooks/tutorial.ipynb).
|
|
140
131
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
132
|
+
|
|
133
|
+
## Object requirements
|
|
134
|
+
|
|
135
|
+
Under-the-hood, we follow the same patterns as `pickle` by explicitly invoking many of the same method (`__reduce__`, `__setstate__`, etc).
|
|
136
|
+
_Almost_ and object which can be pickled can be stored using `bagofholding`.
|
|
137
|
+
Our requirements are that the object...
|
|
138
|
+
|
|
139
|
+
- Must be pickleable
|
|
140
|
+
- You can use the `pickle_check` method on bag classes to quickly assess this
|
|
141
|
+
- Must not depend on `pickle` protocol >4
|
|
142
|
+
- Must have a valid boolean response to `hasattr` for each of the following, and they must conform to python and `abc.collections` norms if present:
|
|
143
|
+
- `__setstate__`
|
|
144
|
+
- `__setitem__`
|
|
145
|
+
- `append`
|
|
146
|
+
- `extend`
|
|
147
|
+
- Must have a valid boolean response to `hasattr` for `__metadata__`, and this attribute must be castable to a string if present
|
|
148
|
+
|
|
149
|
+
If your object satisfies these conditions and fails to "bag", please raise a bug report on the issues page!
|
|
@@ -7,8 +7,8 @@ name = "bagofholding"
|
|
|
7
7
|
description = "bagofholding - browsable, partially-reloadable serialization for pickleable python objects."
|
|
8
8
|
readme = "docs/README.md"
|
|
9
9
|
keywords = [ "pyiron",]
|
|
10
|
-
requires-python = ">=3.
|
|
11
|
-
classifiers = [ "Development Status ::
|
|
10
|
+
requires-python = ">=3.11, <3.14"
|
|
11
|
+
classifiers = [ "Development Status :: 4 - Beta", "Topic :: Scientific/Engineering", "License :: OSI Approved :: BSD License", "Intended Audience :: Science/Research", "Operating System :: OS Independent", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13",]
|
|
12
12
|
dependencies = [ "bidict==0.23.1", "h5py>=3.14.0,<3.15.0", "mpi4py>=4.0.1,<4.1.0", "numpy>=2.3.0,<2.4.0", "pygtrie>=2.5.0,<2.6.0", "pyiron_snippets==0.2.0",]
|
|
13
13
|
dynamic = [ "version",]
|
|
14
14
|
[[project.authors]]
|
|
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
|