turbo_broccoli.custom.external
External data. Embeds data from another file (decodable using
turbo_broccoli.native.load
) into a JSON document. The data is wrapped in a
ExternalData
objects. Note that the path of a ExternalData
is relative to
the path of the JSON file containing it. Therefore, it is not possible to
serialize/deserialize a ExternalData
object without a context that points to
an actual JSON file.
Warning:
The data is read-only. Modifying ExternalData.data
will not affect the
data file.
1""" 2External data. Embeds data from another file (decodable using 3`turbo_broccoli.native.load`) into a JSON document. The data is wrapped in a 4`ExternalData` objects. Note that the path of a `ExternalData` is relative to 5the path of the JSON file containing it. Therefore, it is not possible to 6serialize/deserialize a `ExternalData` object without a context that points to 7an actual JSON file. 8 9Warning: 10 The data is read-only. Modifying `ExternalData.data` will not affect the 11 data file. 12""" 13 14# pylint: disable=cyclic-import 15# pylint: disable=import-outside-toplevel # to avoid actual circular imports 16 17 18from pathlib import Path 19from typing import Any 20 21from turbo_broccoli.context import Context 22from turbo_broccoli.exceptions import DeserializationError, TypeNotSupported 23 24 25class ExternalData: 26 """Encapsulate the data of a file""" 27 28 path: Path 29 data: Any 30 31 def __init__(self, path: Path | str, ctx: Context) -> None: 32 """ 33 Args: 34 path (Path | str): Path of the data file. Either absolute or 35 relative to `ctx.file_path` 36 ctx (Context): 37 """ 38 from turbo_broccoli.native import load as native_load 39 40 if ctx.file_path is None: 41 raise ValueError("Context must have a file path") 42 path = Path(path) if isinstance(path, str) else path 43 if path.is_absolute(): 44 self.path = Path(path).relative_to(ctx.file_path.parent.absolute()) 45 else: 46 self.path = path 47 self.data = native_load(ctx.file_path.parent / self.path) 48 49 50def _json_to_externaldata(dct: dict, ctx: Context) -> ExternalData: 51 decoders = { 52 1: _json_to_externaldata_v1, 53 2: _json_to_externaldata_v2, 54 } 55 return decoders[dct["__version__"]](dct, ctx) 56 57 58def _json_to_externaldata_v1(dct: dict, ctx: Context) -> ExternalData: 59 return ExternalData(dct["path"], ctx) 60 61 62def _json_to_externaldata_v2(dct: dict, ctx: Context) -> ExternalData: 63 ctx.raise_if_nodecode("pathlib.path") 64 return ExternalData(dct["path"], ctx) 65 66 67# pylint: disable=missing-function-docstring 68def from_json(dct: dict, ctx: Context) -> ExternalData: 69 decoders = { 70 "external": _json_to_externaldata, 71 } 72 try: 73 type_name = dct["__type__"] 74 return decoders[type_name](dct, ctx) 75 except KeyError as exc: 76 raise DeserializationError() from exc 77 78 79def to_json(obj: Any, ctx: Context) -> dict: 80 """ 81 Serializes an `ExternalData` object into JSON. The return dict has the 82 following structure 83 84 ```py 85 { 86 "__type__": "external", 87 "__version__": 2, 88 "path": {...} 89 } 90 ``` 91 92 where `path` is a (serialized) `pathlib.Path` object, and relative to the 93 path of the input/output JSON file. 94 """ 95 if not isinstance(obj, ExternalData): 96 raise TypeNotSupported() 97 return {"__type__": "external", "__version__": 2, "path": obj.path}
26class ExternalData: 27 """Encapsulate the data of a file""" 28 29 path: Path 30 data: Any 31 32 def __init__(self, path: Path | str, ctx: Context) -> None: 33 """ 34 Args: 35 path (Path | str): Path of the data file. Either absolute or 36 relative to `ctx.file_path` 37 ctx (Context): 38 """ 39 from turbo_broccoli.native import load as native_load 40 41 if ctx.file_path is None: 42 raise ValueError("Context must have a file path") 43 path = Path(path) if isinstance(path, str) else path 44 if path.is_absolute(): 45 self.path = Path(path).relative_to(ctx.file_path.parent.absolute()) 46 else: 47 self.path = path 48 self.data = native_load(ctx.file_path.parent / self.path)
Encapsulate the data of a file
32 def __init__(self, path: Path | str, ctx: Context) -> None: 33 """ 34 Args: 35 path (Path | str): Path of the data file. Either absolute or 36 relative to `ctx.file_path` 37 ctx (Context): 38 """ 39 from turbo_broccoli.native import load as native_load 40 41 if ctx.file_path is None: 42 raise ValueError("Context must have a file path") 43 path = Path(path) if isinstance(path, str) else path 44 if path.is_absolute(): 45 self.path = Path(path).relative_to(ctx.file_path.parent.absolute()) 46 else: 47 self.path = path 48 self.data = native_load(ctx.file_path.parent / self.path)
Args:
path (Path | str): Path of the data file. Either absolute or
relative to ctx.file_path
ctx (Context):
80def to_json(obj: Any, ctx: Context) -> dict: 81 """ 82 Serializes an `ExternalData` object into JSON. The return dict has the 83 following structure 84 85 ```py 86 { 87 "__type__": "external", 88 "__version__": 2, 89 "path": {...} 90 } 91 ``` 92 93 where `path` is a (serialized) `pathlib.Path` object, and relative to the 94 path of the input/output JSON file. 95 """ 96 if not isinstance(obj, ExternalData): 97 raise TypeNotSupported() 98 return {"__type__": "external", "__version__": 2, "path": obj.path}
Serializes an ExternalData
object into JSON. The return dict has the
following structure
{
"__type__": "external",
"__version__": 2,
"path": {...}
}
where path
is a (serialized) pathlib.Path
object, and relative to the
path of the input/output JSON file.