Use TypeAdapter for Json serialization (#4183)
This commit is contained in:
parent
0dddc7308d
commit
1d8352b466
|
|
@ -77,7 +77,7 @@ class ArchConfig:
|
||||||
services: list[str] = field(default_factory=list)
|
services: list[str] = field(default_factory=list)
|
||||||
custom_commands: list[str] = field(default_factory=list)
|
custom_commands: list[str] = field(default_factory=list)
|
||||||
|
|
||||||
def unsafe_json(self) -> dict[str, Any]:
|
def unsafe_config(self) -> dict[str, Any]:
|
||||||
config: dict[str, list[UserSerialization] | str | None] = {}
|
config: dict[str, list[UserSerialization] | str | None] = {}
|
||||||
|
|
||||||
if self.auth_config:
|
if self.auth_config:
|
||||||
|
|
@ -94,7 +94,7 @@ class ArchConfig:
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def safe_json(self) -> dict[str, Any]:
|
def safe_config(self) -> dict[str, Any]:
|
||||||
config: Any = {
|
config: Any = {
|
||||||
'version': self.version,
|
'version': self.version,
|
||||||
'script': self.script,
|
'script': self.script,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@ import json
|
||||||
import readline
|
import readline
|
||||||
import stat
|
import stat
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pydantic import TypeAdapter
|
||||||
|
|
||||||
from archinstall.lib.menu.helpers import Confirmation, Selection
|
from archinstall.lib.menu.helpers import Confirmation, Selection
|
||||||
from archinstall.lib.translationhandler import tr
|
from archinstall.lib.translationhandler import tr
|
||||||
|
|
@ -10,7 +13,6 @@ from archinstall.tui.ui.result import ResultType
|
||||||
|
|
||||||
from .args import ArchConfig
|
from .args import ArchConfig
|
||||||
from .crypt import encrypt
|
from .crypt import encrypt
|
||||||
from .general import JSON, UNSAFE_JSON
|
|
||||||
from .output import debug, logger, warn
|
from .output import debug, logger, warn
|
||||||
from .utils.util import get_password, prompt_dir
|
from .utils.util import get_password, prompt_dir
|
||||||
|
|
||||||
|
|
@ -40,12 +42,18 @@ class ConfigurationOutput:
|
||||||
return self._user_creds_file
|
return self._user_creds_file
|
||||||
|
|
||||||
def user_config_to_json(self) -> str:
|
def user_config_to_json(self) -> str:
|
||||||
out = self._config.safe_json()
|
config = self._config.safe_config()
|
||||||
return json.dumps(out, indent=4, sort_keys=True, cls=JSON)
|
|
||||||
|
adapter = TypeAdapter(dict[str, Any])
|
||||||
|
python_dict = adapter.dump_python(config)
|
||||||
|
return json.dumps(python_dict, indent=4, sort_keys=True)
|
||||||
|
|
||||||
def user_credentials_to_json(self) -> str:
|
def user_credentials_to_json(self) -> str:
|
||||||
out = self._config.unsafe_json()
|
config = self._config.unsafe_config()
|
||||||
return json.dumps(out, indent=4, sort_keys=True, cls=UNSAFE_JSON)
|
|
||||||
|
adapter = TypeAdapter(dict[str, Any])
|
||||||
|
python_dict = adapter.dump_python(config)
|
||||||
|
return json.dumps(python_dict, indent=4, sort_keys=True)
|
||||||
|
|
||||||
def write_debug(self) -> None:
|
def write_debug(self) -> None:
|
||||||
debug(' -- Chosen configuration --')
|
debug(' -- Chosen configuration --')
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
import json
|
|
||||||
from datetime import date, datetime
|
|
||||||
from enum import Enum
|
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, override
|
|
||||||
|
|
||||||
from archinstall.lib.packages.packages import check_package_upgrade
|
from archinstall.lib.packages.packages import check_package_upgrade
|
||||||
|
|
||||||
|
|
@ -35,55 +31,3 @@ def running_from_host() -> bool:
|
||||||
"""
|
"""
|
||||||
is_host = not Path('/run/archiso').exists()
|
is_host = not Path('/run/archiso').exists()
|
||||||
return is_host
|
return is_host
|
||||||
|
|
||||||
|
|
||||||
def jsonify(obj: Any, safe: bool = True) -> Any:
|
|
||||||
"""
|
|
||||||
Converts objects into json.dumps() compatible nested dictionaries.
|
|
||||||
Setting safe to True skips dictionary keys starting with a bang (!)
|
|
||||||
"""
|
|
||||||
|
|
||||||
compatible_types = str, int, float, bool
|
|
||||||
if isinstance(obj, dict):
|
|
||||||
return {
|
|
||||||
key: jsonify(value, safe)
|
|
||||||
for key, value in obj.items()
|
|
||||||
if isinstance(key, compatible_types) and not (isinstance(key, str) and key.startswith('!') and safe)
|
|
||||||
}
|
|
||||||
if isinstance(obj, Enum):
|
|
||||||
return obj.value
|
|
||||||
if hasattr(obj, 'json'):
|
|
||||||
# json() is a friendly name for json-helper, it should return
|
|
||||||
# a dictionary representation of the object so that it can be
|
|
||||||
# processed by the json library.
|
|
||||||
return jsonify(obj.json(), safe)
|
|
||||||
if isinstance(obj, datetime | date):
|
|
||||||
return obj.isoformat()
|
|
||||||
if isinstance(obj, list | set | tuple):
|
|
||||||
return [jsonify(item, safe) for item in obj]
|
|
||||||
if isinstance(obj, Path):
|
|
||||||
return str(obj)
|
|
||||||
if hasattr(obj, '__dict__'):
|
|
||||||
return vars(obj)
|
|
||||||
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
class JSON(json.JSONEncoder, json.JSONDecoder):
|
|
||||||
"""
|
|
||||||
A safe JSON encoder that will omit private information in dicts (starting with !)
|
|
||||||
"""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def encode(self, o: Any) -> str:
|
|
||||||
return super().encode(jsonify(o))
|
|
||||||
|
|
||||||
|
|
||||||
class UNSAFE_JSON(json.JSONEncoder, json.JSONDecoder):
|
|
||||||
"""
|
|
||||||
UNSAFE_JSON will call/encode and keep private information in dicts (starting with !)
|
|
||||||
"""
|
|
||||||
|
|
||||||
@override
|
|
||||||
def encode(self, o: Any) -> str:
|
|
||||||
return super().encode(jsonify(o, safe=False))
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue