Skip to content

Commit

Permalink
feat(config): allow value decoding with only the type info
Browse files Browse the repository at this point in the history
  • Loading branch information
xen0n committed Dec 28, 2024
1 parent 7cb4550 commit 4c7ff9c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 13 deletions.
6 changes: 4 additions & 2 deletions ruyi/config/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ def __repr__(self) -> str:
class InvalidConfigValueError(ValueError):
def __init__(
self,
key: str | Sequence[str],
key: str | Sequence[str] | type,
val: object | None,
) -> None:
super().__init__()
self._key = key
self._val = val

def __str__(self) -> str:
return f"invalid value for config key {self._key}: {self._val}"
if isinstance(self._key, type):
return f"invalid config value for type {self._key}: {self._val}"
return f"invalid config value for key {self._key}: {self._val}"

def __repr__(self) -> str:
return f"InvalidConfigValueError({self._key:!r}, {self._val:!r})"
Expand Down
8 changes: 6 additions & 2 deletions ruyi/config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,17 @@ def encode_value(v: object) -> str:


def decode_value(
key: str | Sequence[str],
key: str | Sequence[str] | type,
val: str,
) -> object:
"""Decodes the given string representation of a config value into a Python
value, directed by type information implied by the config key."""

expected_type = get_expected_type_for_config_key(key)
if isinstance(key, type):
expected_type = key
else:
expected_type = get_expected_type_for_config_key(key)

if expected_type is bool:
if val in ("true", "yes", "1"):
return True
Expand Down
22 changes: 13 additions & 9 deletions tests/config/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,35 @@

def test_decode_value_bool() -> None:
assert decode_value("installation.externally_managed", "true") is True
assert decode_value("installation.externally_managed", "false") is False
assert decode_value("installation.externally_managed", "yes") is True
assert decode_value("installation.externally_managed", "no") is False
assert decode_value("installation.externally_managed", "1") is True
assert decode_value("installation.externally_managed", "0") is False

assert decode_value(bool, "true") is True
assert decode_value(bool, "false") is False
assert decode_value(bool, "yes") is True
assert decode_value(bool, "no") is False
assert decode_value(bool, "1") is True
assert decode_value(bool, "0") is False
with pytest.raises(InvalidConfigValueError):
decode_value("installation.externally_managed", "invalid")
decode_value(bool, "invalid")
with pytest.raises(InvalidConfigValueError):
decode_value("installation.externally_managed", "x")
decode_value(bool, "x")
with pytest.raises(InvalidConfigValueError):
decode_value("installation.externally_managed", "True")
decode_value(bool, "True")


def test_decode_value_str() -> None:
assert decode_value("repo.branch", "main") == "main"
assert decode_value(str, "main") == "main"


def test_decode_value_datetime() -> None:
tz_aware_dt = datetime.datetime(2024, 12, 1, 12, 0, 0, tzinfo=datetime.timezone.utc)
assert (
decode_value("telemetry.upload_consent", "2024-12-01T12:00:00Z") == tz_aware_dt
)
assert decode_value(datetime.datetime, "2024-12-01T12:00:00Z") == tz_aware_dt

# naive datetimes are decoded using the implicit local timezone
decode_value("telemetry.upload_consent", "2024-12-01T12:00:00")
decode_value(datetime.datetime, "2024-12-01T12:00:00")


def test_encode_value_bool() -> None:
Expand Down

0 comments on commit 4c7ff9c

Please sign in to comment.