Coverage for python/lsst/daf/butler/json.py: 52%
27 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-05 11:07 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-05 11:07 +0000
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28from __future__ import annotations
30__all__ = ("to_json_generic", "from_json_generic", "to_json_pydantic", "from_json_pydantic")
32import json
33from typing import TYPE_CHECKING, Any, Protocol, Type
35if TYPE_CHECKING:
36 from .dimensions import DimensionUniverse
37 from .registry import Registry
40class SupportsSimple(Protocol):
41 """Protocol defining the methods required to support the standard
42 serialization using "simple" methods names.
43 """
45 _serializedType: Type
47 def to_simple(self, minimal: bool) -> Any:
48 ...
50 @classmethod
51 def from_simple(
52 cls, simple: Any, universe: DimensionUniverse | None = None, registry: Registry | None = None
53 ) -> SupportsSimple:
54 ...
57def to_json_pydantic(self: SupportsSimple, minimal: bool = False) -> str:
58 """Convert this class to JSON assuming that the ``to_simple()`` returns
59 a pydantic model.
61 """
62 return self.to_simple(minimal=minimal).model_dump_json(exclude_defaults=True, exclude_unset=True)
65def from_json_pydantic(
66 cls: type[SupportsSimple],
67 json_str: str,
68 universe: DimensionUniverse | None = None,
69 registry: Registry | None = None,
70) -> SupportsSimple:
71 """Convert from JSON to a pydantic model."""
72 simple = cls._serializedType.model_validate_json(json_str)
73 try:
74 return cls.from_simple(simple, universe=universe, registry=registry)
75 except AttributeError as e:
76 raise AttributeError(f"JSON deserialization requires {cls} has a from_simple() class method") from e
79def to_json_generic(self: SupportsSimple, minimal: bool = False) -> str:
80 """Convert this class to JSON form.
82 The class type is not recorded in the JSON so the JSON decoder
83 must know which class is represented.
85 Parameters
86 ----------
87 minimal : `bool`, optional
88 Use minimal serialization. Requires Registry to convert
89 back to a full type.
91 Returns
92 -------
93 json : `str`
94 The class in JSON string format.
95 """
96 # For now use the core json library to convert a dict to JSON
97 # for us.
98 return json.dumps(self.to_simple(minimal=minimal))
101def from_json_generic(
102 cls: type[SupportsSimple],
103 json_str: str,
104 universe: DimensionUniverse | None = None,
105 registry: Registry | None = None,
106) -> SupportsSimple:
107 """Return new class from JSON string.
109 Converts a JSON string created by `to_json` and return
110 something of the supplied class.
112 Parameters
113 ----------
114 json_str : `str`
115 Representation of the dimensions in JSON format as created
116 by `to_json()`.
117 universe : `DimensionUniverse`, optional
118 The special graph of all known dimensions. Passed directly
119 to `from_simple()`.
120 registry : `lsst.daf.butler.Registry`, optional
121 Registry to use to convert simple name of a DatasetType to
122 a full `DatasetType`. Passed directly to `from_simple()`.
124 Returns
125 -------
126 constructed : Any
127 Newly-constructed object.
128 """
129 simple = json.loads(json_str)
130 try:
131 return cls.from_simple(simple, universe=universe, registry=registry)
132 except AttributeError as e:
133 raise AttributeError(f"JSON deserialization requires {cls} has a from_simple() class method") from e