From: Joerg Behrmann Date: Wed, 27 Sep 2023 08:38:49 +0000 (+0200) Subject: json: make JSON readable from dicts and files as well es strings X-Git-Tag: v18~13^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c21154d5a9d85fe6bb8a6714224c0269f0874d4b;p=thirdparty%2Fmkosi.git json: make JSON readable from dicts and files as well es strings --- diff --git a/mkosi/config.py b/mkosi/config.py index fbdc2e29e..9b778570c 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -30,7 +30,7 @@ from mkosi.distributions import Distribution, detect_distribution from mkosi.log import ARG_DEBUG, ARG_DEBUG_SHELL, Style, die from mkosi.pager import page from mkosi.run import run -from mkosi.types import PathString +from mkosi.types import PathString, SupportsRead from mkosi.util import ( InvokingUser, StrEnum, @@ -673,8 +673,16 @@ class MkosiArgs: return json.dumps(dataclasses.asdict(self), cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys) @classmethod - def from_json(cls, s: str) -> "MkosiArgs": - j = json.loads(s) + def from_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> "MkosiArgs": + if isinstance(s, str): + j = json.loads(s) + elif isinstance(s, dict): + j = s + elif hasattr(s, "read"): + j = json.load(s) + else: + raise ValueError(f"{cls.__name__} can only be constructed from JSON from strings, dictionaries and files.") + transformer = json_type_transformer(cls) tj = {k: transformer(k, v) for k, v in j.items()} return cls(**tj) @@ -892,8 +900,16 @@ class MkosiConfig: return json.dumps(dataclasses.asdict(self), cls=MkosiJsonEncoder, indent=indent, sort_keys=sort_keys) @classmethod - def from_json(cls, s: str) -> "MkosiConfig": - j = json.loads(s) + def from_json(cls, s: Union[str, dict[str, Any], SupportsRead[str], SupportsRead[bytes]]) -> "MkosiConfig": + if isinstance(s, str): + j = json.loads(s) + elif isinstance(s, dict): + j = s + elif hasattr(s, "read"): + j = json.load(s) + else: + raise ValueError(f"{cls.__name__} can only be constructed from JSON from strings, dictionaries and files.") + transformer = json_type_transformer(cls) tj = {k: transformer(k, v) for k, v in j.items()} return cls(**tj) diff --git a/mkosi/types.py b/mkosi/types.py index a2a3643b5..c6621855c 100644 --- a/mkosi/types.py +++ b/mkosi/types.py @@ -2,7 +2,7 @@ import subprocess from pathlib import Path -from typing import IO, TYPE_CHECKING, Any, Union +from typing import IO, TYPE_CHECKING, Any, Protocol, TypeVar, Union # These types are only generic during type checking and not at runtime, leading # to a TypeError during compilation. @@ -17,3 +17,12 @@ else: # Borrowed from https://github.com/python/typeshed/blob/3d14016085aed8bcf0cf67e9e5a70790ce1ad8ea/stdlib/3/subprocess.pyi#L24 _FILE = Union[None, int, IO[Any]] PathString = Union[Path, str] + +# Borrowed from +# https://github.com/python/typeshed/blob/ec52bf1adde1d3183d0595d2ba982589df48dff1/stdlib/_typeshed/__init__.pyi#L19 +# and +# https://github.com/python/typeshed/blob/ec52bf1adde1d3183d0595d2ba982589df48dff1/stdlib/_typeshed/__init__.pyi#L224 +_T_co = TypeVar("_T_co", covariant=True) + +class SupportsRead(Protocol[_T_co]): + def read(self, __length: int = ...) -> _T_co: ...