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.
Files changed (139) hide show
  1. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/PKG-INFO +4 -1
  2. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/_version.py +2 -2
  3. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/conda-envs/environment-test.yml +2 -0
  4. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/api_reference.rst +26 -0
  5. pymc_extras-0.2.7/pymc_extras/deserialize.py +224 -0
  6. pymc_extras-0.2.7/pymc_extras/prior.py +1356 -0
  7. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pyproject.toml +4 -1
  8. pymc_extras-0.2.7/tests/test_deserialize.py +59 -0
  9. pymc_extras-0.2.7/tests/test_prior.py +1143 -0
  10. pymc_extras-0.2.6/pymc_extras/utils/pivoted_cholesky.py +0 -69
  11. pymc_extras-0.2.6/tests/test_pivoted_cholesky.py +0 -24
  12. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.gitignore +0 -0
  13. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.gitpod.yml +0 -0
  14. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.pre-commit-config.yaml +0 -0
  15. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/.readthedocs.yaml +0 -0
  16. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/CODE_OF_CONDUCT.md +0 -0
  17. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/CONTRIBUTING.md +0 -0
  18. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/LICENSE +0 -0
  19. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/README.md +0 -0
  20. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/codecov.yml +0 -0
  21. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/.nojekyll +0 -0
  22. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/Makefile +0 -0
  23. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/_templates/autosummary/base.rst +0 -0
  24. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/_templates/autosummary/class.rst +0 -0
  25. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/conf.py +0 -0
  26. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/index.rst +0 -0
  27. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/make.bat +0 -0
  28. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/core.rst +0 -0
  29. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/filters.rst +0 -0
  30. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/models/structural.rst +0 -0
  31. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/docs/statespace/models.rst +0 -0
  32. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/__init__.py +0 -0
  33. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/__init__.py +0 -0
  34. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/continuous.py +0 -0
  35. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/discrete.py +0 -0
  36. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/histogram_utils.py +0 -0
  37. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/multivariate/__init__.py +0 -0
  38. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/multivariate/r2d2m2cp.py +0 -0
  39. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/timeseries.py +0 -0
  40. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/transforms/__init__.py +0 -0
  41. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/distributions/transforms/partial_order.py +0 -0
  42. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/gp/__init__.py +0 -0
  43. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/gp/latent_approx.py +0 -0
  44. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/__init__.py +0 -0
  45. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/find_map.py +0 -0
  46. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/fit.py +0 -0
  47. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/laplace.py +0 -0
  48. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/__init__.py +0 -0
  49. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/importance_sampling.py +0 -0
  50. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/lbfgs.py +0 -0
  51. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/pathfinder/pathfinder.py +0 -0
  52. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/smc/__init__.py +0 -0
  53. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/inference/smc/sampling.py +0 -0
  54. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/linearmodel.py +0 -0
  55. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/__init__.py +0 -0
  56. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/__init__.py +0 -0
  57. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/distributions.py +0 -0
  58. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/graph_analysis.py +0 -0
  59. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/marginal/marginal_model.py +0 -0
  60. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/model_api.py +0 -0
  61. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/transforms/__init__.py +0 -0
  62. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model/transforms/autoreparam.py +0 -0
  63. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/model_builder.py +0 -0
  64. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/preprocessing/__init__.py +0 -0
  65. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/preprocessing/standard_scaler.py +0 -0
  66. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/printing.py +0 -0
  67. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/__init__.py +0 -0
  68. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/__init__.py +0 -0
  69. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/compile.py +0 -0
  70. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/representation.py +0 -0
  71. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/core/statespace.py +0 -0
  72. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/__init__.py +0 -0
  73. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/distributions.py +0 -0
  74. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/kalman_filter.py +0 -0
  75. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/kalman_smoother.py +0 -0
  76. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/filters/utilities.py +0 -0
  77. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/ETS.py +0 -0
  78. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/SARIMAX.py +0 -0
  79. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/VARMAX.py +0 -0
  80. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/__init__.py +0 -0
  81. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/structural.py +0 -0
  82. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/models/utilities.py +0 -0
  83. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/__init__.py +0 -0
  84. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/constants.py +0 -0
  85. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/coord_tools.py +0 -0
  86. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/statespace/utils/data_tools.py +0 -0
  87. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/__init__.py +0 -0
  88. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/linear_cg.py +0 -0
  89. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/model_equivalence.py +0 -0
  90. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/prior.py +0 -0
  91. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/pymc_extras/utils/spline.py +0 -0
  92. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/__init__.py +0 -0
  93. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/conftest.py +0 -0
  94. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/__init__.py +0 -0
  95. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_continuous.py +0 -0
  96. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_discrete.py +0 -0
  97. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_discrete_markov_chain.py +0 -0
  98. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_multivariate.py +0 -0
  99. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/distributions/test_transform.py +0 -0
  100. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/__init__.py +0 -0
  101. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/__init__.py +0 -0
  102. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_distributions.py +0 -0
  103. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_graph_analysis.py +0 -0
  104. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/marginal/test_marginal_model.py +0 -0
  105. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/test_model_api.py +0 -0
  106. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/model/transforms/test_autoreparam.py +0 -0
  107. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/__init__.py +0 -0
  108. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/airpass.csv +0 -0
  109. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/airpassangers.csv +0 -0
  110. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/nile.csv +0 -0
  111. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/_data/statsmodels_macrodata_processed.csv +0 -0
  112. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/__init__.py +0 -0
  113. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_representation.py +0 -0
  114. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_statespace.py +0 -0
  115. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/core/test_statespace_JAX.py +0 -0
  116. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/__init__.py +0 -0
  117. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/test_distributions.py +0 -0
  118. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/filters/test_kalman_filter.py +0 -0
  119. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/__init__.py +0 -0
  120. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_ETS.py +0 -0
  121. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_SARIMAX.py +0 -0
  122. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_VARMAX.py +0 -0
  123. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/models/test_structural.py +0 -0
  124. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/shared_fixtures.py +0 -0
  125. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/statsmodel_local_level.py +0 -0
  126. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/test_utilities.py +0 -0
  127. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/utils/__init__.py +0 -0
  128. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/statespace/utils/test_coord_assignment.py +0 -0
  129. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_blackjax_smc.py +0 -0
  130. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_find_map.py +0 -0
  131. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_histogram_approximation.py +0 -0
  132. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_laplace.py +0 -0
  133. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_linearmodel.py +0 -0
  134. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_model_builder.py +0 -0
  135. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_pathfinder.py +0 -0
  136. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_printing.py +0 -0
  137. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_prior_from_trace.py +0 -0
  138. {pymc_extras-0.2.6 → pymc_extras-0.2.7}/tests/test_splines.py +0 -0
  139. {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.6
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
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.6'
21
- __version_tuple__ = version_tuple = (0, 2, 6)
20
+ __version__ = version = '0.2.7'
21
+ __version_tuple__ = version_tuple = (0, 2, 7)
@@ -13,6 +13,8 @@ dependencies:
13
13
  - pytest
14
14
  - pytest-cov
15
15
  - libgcc<15
16
+ - pydantic>=2.0.0
17
+ - preliz
16
18
  - pip
17
19
  - pip:
18
20
  - jax
@@ -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)