pymc-extras 0.2.6__tar.gz → 0.2.7__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.
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/PKG-INFO +4 -1
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/_version.py +2 -2
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/conda-envs/environment-test.yml +2 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/api_reference.rst +26 -0
- pymc_extras-0.2.7/pymc_extras/deserialize.py +224 -0
- pymc_extras-0.2.7/pymc_extras/prior.py +1356 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pyproject.toml +4 -1
- pymc_extras-0.2.7/tests/test_deserialize.py +59 -0
- pymc_extras-0.2.7/tests/test_prior.py +1143 -0
- pymc_extras-0.2.6/pymc_extras/utils/pivoted_cholesky.py +0 -69
- pymc_extras-0.2.6/tests/test_pivoted_cholesky.py +0 -24
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.gitignore +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.gitpod.yml +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.pre-commit-config.yaml +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.readthedocs.yaml +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/CODE_OF_CONDUCT.md +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/CONTRIBUTING.md +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/LICENSE +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/README.md +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/codecov.yml +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/.nojekyll +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/Makefile +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/_templates/autosummary/base.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/_templates/autosummary/class.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/conf.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/index.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/make.bat +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/core.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/filters.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/models/structural.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/models.rst +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/continuous.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/discrete.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/histogram_utils.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/multivariate/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/multivariate/r2d2m2cp.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/timeseries.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/transforms/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/transforms/partial_order.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/gp/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/gp/latent_approx.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/find_map.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/fit.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/laplace.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/importance_sampling.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/lbfgs.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/pathfinder.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/smc/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/smc/sampling.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/linearmodel.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/distributions.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/graph_analysis.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/marginal_model.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/model_api.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/transforms/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/transforms/autoreparam.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model_builder.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/preprocessing/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/preprocessing/standard_scaler.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/printing.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/compile.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/representation.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/statespace.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/distributions.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/kalman_filter.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/kalman_smoother.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/utilities.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/ETS.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/SARIMAX.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/VARMAX.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/structural.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/utilities.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/constants.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/coord_tools.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/data_tools.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/linear_cg.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/model_equivalence.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/prior.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/spline.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/conftest.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_continuous.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_discrete.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_discrete_markov_chain.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_multivariate.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_transform.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_distributions.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_graph_analysis.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_marginal_model.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/test_model_api.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/transforms/test_autoreparam.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/airpass.csv +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/airpassangers.csv +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/nile.csv +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/statsmodels_macrodata_processed.csv +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_representation.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_statespace.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_statespace_JAX.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/test_distributions.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/test_kalman_filter.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_ETS.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_SARIMAX.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_VARMAX.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_structural.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/shared_fixtures.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/statsmodel_local_level.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/test_utilities.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/utils/__init__.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/utils/test_coord_assignment.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_blackjax_smc.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_find_map.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_histogram_approximation.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_laplace.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_linearmodel.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_model_builder.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_pathfinder.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_printing.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_prior_from_trace.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_splines.py +0 -0
- {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymc-extras
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: A home for new additions to PyMC, which may include unusual probability distribitions, advanced model fitting algorithms, or any code that may be inappropriate to include in the pymc repository, but may want to be made available to users.
|
|
5
5
|
Project-URL: Documentation, https://pymc-extras.readthedocs.io/
|
|
6
6
|
Project-URL: Repository, https://github.com/pymc-devs/pymc-extras.git
|
|
@@ -234,6 +234,8 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
234
234
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
235
235
|
Requires-Python: >=3.10
|
|
236
236
|
Requires-Dist: better-optimize>=0.1.2
|
|
237
|
+
Requires-Dist: preliz
|
|
238
|
+
Requires-Dist: pydantic>=2.0.0
|
|
237
239
|
Requires-Dist: pymc>=5.21.1
|
|
238
240
|
Requires-Dist: scikit-learn
|
|
239
241
|
Provides-Extra: complete
|
|
@@ -245,6 +247,7 @@ Requires-Dist: xhistogram; extra == 'dask-histogram'
|
|
|
245
247
|
Provides-Extra: dev
|
|
246
248
|
Requires-Dist: blackjax; extra == 'dev'
|
|
247
249
|
Requires-Dist: dask[all]<2025.1.1; extra == 'dev'
|
|
250
|
+
Requires-Dist: pytest-mock; extra == 'dev'
|
|
248
251
|
Requires-Dist: pytest>=6.0; extra == 'dev'
|
|
249
252
|
Requires-Dist: statsmodels; extra == 'dev'
|
|
250
253
|
Provides-Extra: docs
|
|
@@ -46,6 +46,32 @@ Distributions
|
|
|
46
46
|
Skellam
|
|
47
47
|
histogram_approximation
|
|
48
48
|
|
|
49
|
+
Prior
|
|
50
|
+
=====
|
|
51
|
+
|
|
52
|
+
.. currentmodule:: pymc_extras.prior
|
|
53
|
+
.. autosummary::
|
|
54
|
+
:toctree: generated/
|
|
55
|
+
|
|
56
|
+
create_dim_handler
|
|
57
|
+
handle_dims
|
|
58
|
+
Prior
|
|
59
|
+
VariableFactory
|
|
60
|
+
sample_prior
|
|
61
|
+
Censored
|
|
62
|
+
Scaled
|
|
63
|
+
|
|
64
|
+
Deserialize
|
|
65
|
+
===========
|
|
66
|
+
|
|
67
|
+
.. currentmodule:: pymc_extras.deserialize
|
|
68
|
+
.. autosummary::
|
|
69
|
+
:toctree: generated/
|
|
70
|
+
|
|
71
|
+
deserialize
|
|
72
|
+
register_deserialization
|
|
73
|
+
Deserializer
|
|
74
|
+
|
|
49
75
|
|
|
50
76
|
Transforms
|
|
51
77
|
==========
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"""Deserialize dictionaries into Python objects.
|
|
2
|
+
|
|
3
|
+
This is a two step process:
|
|
4
|
+
|
|
5
|
+
1. Determine if the data is of the correct type.
|
|
6
|
+
2. Deserialize the data into a python object.
|
|
7
|
+
|
|
8
|
+
Examples
|
|
9
|
+
--------
|
|
10
|
+
Make use of the already registered deserializers:
|
|
11
|
+
|
|
12
|
+
.. code-block:: python
|
|
13
|
+
|
|
14
|
+
from pymc_extras.deserialize import deserialize
|
|
15
|
+
|
|
16
|
+
prior_class_data = {
|
|
17
|
+
"dist": "Normal",
|
|
18
|
+
"kwargs": {"mu": 0, "sigma": 1}
|
|
19
|
+
}
|
|
20
|
+
prior = deserialize(prior_class_data)
|
|
21
|
+
# Prior("Normal", mu=0, sigma=1)
|
|
22
|
+
|
|
23
|
+
Register custom class deserialization:
|
|
24
|
+
|
|
25
|
+
.. code-block:: python
|
|
26
|
+
|
|
27
|
+
from pymc_extras.deserialize import register_deserialization
|
|
28
|
+
|
|
29
|
+
class MyClass:
|
|
30
|
+
def __init__(self, value: int):
|
|
31
|
+
self.value = value
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict:
|
|
34
|
+
# Example of what the to_dict method might look like.
|
|
35
|
+
return {"value": self.value}
|
|
36
|
+
|
|
37
|
+
register_deserialization(
|
|
38
|
+
is_type=lambda data: data.keys() == {"value"} and isinstance(data["value"], int),
|
|
39
|
+
deserialize=lambda data: MyClass(value=data["value"]),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
Deserialize data into that custom class:
|
|
43
|
+
|
|
44
|
+
.. code-block:: python
|
|
45
|
+
|
|
46
|
+
from pymc_extras.deserialize import deserialize
|
|
47
|
+
|
|
48
|
+
data = {"value": 42}
|
|
49
|
+
obj = deserialize(data)
|
|
50
|
+
assert isinstance(obj, MyClass)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
from collections.abc import Callable
|
|
56
|
+
from dataclasses import dataclass
|
|
57
|
+
from typing import Any
|
|
58
|
+
|
|
59
|
+
IsType = Callable[[Any], bool]
|
|
60
|
+
Deserialize = Callable[[Any], Any]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class Deserializer:
|
|
65
|
+
"""Object to store information required for deserialization.
|
|
66
|
+
|
|
67
|
+
All deserializers should be stored via the :func:`register_deserialization` function
|
|
68
|
+
instead of creating this object directly.
|
|
69
|
+
|
|
70
|
+
Attributes
|
|
71
|
+
----------
|
|
72
|
+
is_type : IsType
|
|
73
|
+
Function to determine if the data is of the correct type.
|
|
74
|
+
deserialize : Deserialize
|
|
75
|
+
Function to deserialize the data.
|
|
76
|
+
|
|
77
|
+
Examples
|
|
78
|
+
--------
|
|
79
|
+
.. code-block:: python
|
|
80
|
+
|
|
81
|
+
from typing import Any
|
|
82
|
+
|
|
83
|
+
class MyClass:
|
|
84
|
+
def __init__(self, value: int):
|
|
85
|
+
self.value = value
|
|
86
|
+
|
|
87
|
+
from pymc_extras.deserialize import Deserializer
|
|
88
|
+
|
|
89
|
+
def is_type(data: Any) -> bool:
|
|
90
|
+
return data.keys() == {"value"} and isinstance(data["value"], int)
|
|
91
|
+
|
|
92
|
+
def deserialize(data: dict) -> MyClass:
|
|
93
|
+
return MyClass(value=data["value"])
|
|
94
|
+
|
|
95
|
+
deserialize_logic = Deserializer(is_type=is_type, deserialize=deserialize)
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
is_type: IsType
|
|
100
|
+
deserialize: Deserialize
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
DESERIALIZERS: list[Deserializer] = []
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class DeserializableError(Exception):
|
|
107
|
+
"""Error raised when data cannot be deserialized."""
|
|
108
|
+
|
|
109
|
+
def __init__(self, data: Any):
|
|
110
|
+
self.data = data
|
|
111
|
+
super().__init__(
|
|
112
|
+
f"Couldn't deserialize {data}. Use register_deserialization to add a deserialization mapping."
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def deserialize(data: Any) -> Any:
|
|
117
|
+
"""Deserialize a dictionary into a Python object.
|
|
118
|
+
|
|
119
|
+
Use the :func:`register_deserialization` function to add custom deserializations.
|
|
120
|
+
|
|
121
|
+
Deserialization is a two step process due to the dynamic nature of the data:
|
|
122
|
+
|
|
123
|
+
1. Determine if the data is of the correct type.
|
|
124
|
+
2. Deserialize the data into a Python object.
|
|
125
|
+
|
|
126
|
+
Each registered deserialization is checked in order until one is found that can
|
|
127
|
+
deserialize the data. If no deserialization is found, a :class:`DeserializableError` is raised.
|
|
128
|
+
|
|
129
|
+
A :class:`DeserializableError` is raised when the data fails to be deserialized
|
|
130
|
+
by any of the registered deserializers.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
data : Any
|
|
135
|
+
The data to deserialize.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
Any
|
|
140
|
+
The deserialized object.
|
|
141
|
+
|
|
142
|
+
Raises
|
|
143
|
+
------
|
|
144
|
+
DeserializableError
|
|
145
|
+
Raised when the data doesn't match any registered deserializations
|
|
146
|
+
or fails to be deserialized.
|
|
147
|
+
|
|
148
|
+
Examples
|
|
149
|
+
--------
|
|
150
|
+
Deserialize a :class:`pymc_extras.prior.Prior` object:
|
|
151
|
+
|
|
152
|
+
.. code-block:: python
|
|
153
|
+
|
|
154
|
+
from pymc_extras.deserialize import deserialize
|
|
155
|
+
|
|
156
|
+
data = {"dist": "Normal", "kwargs": {"mu": 0, "sigma": 1}}
|
|
157
|
+
prior = deserialize(data)
|
|
158
|
+
# Prior("Normal", mu=0, sigma=1)
|
|
159
|
+
|
|
160
|
+
"""
|
|
161
|
+
for mapping in DESERIALIZERS:
|
|
162
|
+
try:
|
|
163
|
+
is_type = mapping.is_type(data)
|
|
164
|
+
except Exception:
|
|
165
|
+
is_type = False
|
|
166
|
+
|
|
167
|
+
if not is_type:
|
|
168
|
+
continue
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
return mapping.deserialize(data)
|
|
172
|
+
except Exception as e:
|
|
173
|
+
raise DeserializableError(data) from e
|
|
174
|
+
else:
|
|
175
|
+
raise DeserializableError(data)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def register_deserialization(is_type: IsType, deserialize: Deserialize) -> None:
|
|
179
|
+
"""Register an arbitrary deserialization.
|
|
180
|
+
|
|
181
|
+
Use the :func:`deserialize` function to then deserialize data using all registered
|
|
182
|
+
deserialize functions.
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
is_type : Callable[[Any], bool]
|
|
187
|
+
Function to determine if the data is of the correct type.
|
|
188
|
+
deserialize : Callable[[dict], Any]
|
|
189
|
+
Function to deserialize the data of that type.
|
|
190
|
+
|
|
191
|
+
Examples
|
|
192
|
+
--------
|
|
193
|
+
Register a custom class deserialization:
|
|
194
|
+
|
|
195
|
+
.. code-block:: python
|
|
196
|
+
|
|
197
|
+
from pymc_extras.deserialize import register_deserialization
|
|
198
|
+
|
|
199
|
+
class MyClass:
|
|
200
|
+
def __init__(self, value: int):
|
|
201
|
+
self.value = value
|
|
202
|
+
|
|
203
|
+
def to_dict(self) -> dict:
|
|
204
|
+
# Example of what the to_dict method might look like.
|
|
205
|
+
return {"value": self.value}
|
|
206
|
+
|
|
207
|
+
register_deserialization(
|
|
208
|
+
is_type=lambda data: data.keys() == {"value"} and isinstance(data["value"], int),
|
|
209
|
+
deserialize=lambda data: MyClass(value=data["value"]),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
Use that custom class deserialization:
|
|
213
|
+
|
|
214
|
+
.. code-block:: python
|
|
215
|
+
|
|
216
|
+
from pymc_extras.deserialize import deserialize
|
|
217
|
+
|
|
218
|
+
data = {"value": 42}
|
|
219
|
+
obj = deserialize(data)
|
|
220
|
+
assert isinstance(obj, MyClass)
|
|
221
|
+
|
|
222
|
+
"""
|
|
223
|
+
mapping = Deserializer(is_type=is_type, deserialize=deserialize)
|
|
224
|
+
DESERIALIZERS.append(mapping)
|