feat(types): add JsonPrimitive + JsonValue TypeAliases (t0_3)
Phase 0 of any_type_componentization_20260621. Extends src/type_aliases.py
with two recursive-friendly TypeAliases for JSON wire format (used by
Phase 5 api_hooks WebSocketMessage):
- JsonPrimitive: str | int | float | bool | None
- JsonValue: JsonPrimitive | list['JsonValue'] | dict[str, 'JsonValue']
The forward-ref 'JsonValue' strings work because from __future__ import
annotations is at the top of the module (PEP 563 + PEP 613 TypeAlias).
Tests added (4 new, 14 total):
- test_json_primitive_alias_resolves_to_union: hints exposes JsonPrimitive
- test_json_value_alias_resolves_to_recursive_union: hints exposes JsonValue
- test_json_value_accepts_primitive_dict: dict[str, JsonValue] runtime use
- test_json_value_accepts_nested_structures: nested dict+list round-trip
Verification:
uv run pytest tests/test_type_aliases.py --timeout=30
14 passed in 2.97s
This commit is contained in:
@@ -18,6 +18,9 @@ ToolCall: TypeAlias = Metadata
|
||||
|
||||
CommsLogCallback: TypeAlias = Callable[[CommsLogEntry], None]
|
||||
|
||||
JsonPrimitive: TypeAlias = str | int | float | bool | None
|
||||
JsonValue: TypeAlias = JsonPrimitive | list["JsonValue"] | dict[str, "JsonValue"]
|
||||
|
||||
|
||||
class FileItemsDiff(NamedTuple):
|
||||
refreshed: FileItems
|
||||
|
||||
@@ -49,4 +49,36 @@ def test_file_items_diff_named_tuple_has_two_fields() -> None:
|
||||
def test_result_with_file_items_alias_composes() -> None:
|
||||
r: result_types.Result[type_aliases.FileItems] = result_types.Result(data=[])
|
||||
assert r.ok is True
|
||||
assert isinstance(r.data, list)
|
||||
assert isinstance(r.data, list)
|
||||
|
||||
|
||||
def test_json_primitive_alias_resolves_to_union() -> None:
|
||||
assert hasattr(type_aliases, "JsonPrimitive")
|
||||
hints = get_type_hints(type_aliases)
|
||||
assert "JsonPrimitive" in hints
|
||||
|
||||
|
||||
def test_json_value_alias_resolves_to_recursive_union() -> None:
|
||||
assert hasattr(type_aliases, "JsonValue")
|
||||
hints = get_type_hints(type_aliases)
|
||||
assert "JsonValue" in hints
|
||||
jv = hints["JsonValue"]
|
||||
assert jv is not None
|
||||
|
||||
|
||||
def test_json_value_accepts_primitive_dict() -> None:
|
||||
payload: type_aliases.JsonValue = {"key": "value", "count": 42, "active": True, "nothing": None}
|
||||
assert payload["key"] == "value"
|
||||
assert payload["count"] == 42
|
||||
assert payload["active"] is True
|
||||
assert payload["nothing"] is None
|
||||
|
||||
|
||||
def test_json_value_accepts_nested_structures() -> None:
|
||||
payload: type_aliases.JsonValue = {
|
||||
"users": [{"name": "alice", "age": 30}, {"name": "bob", "age": 25}],
|
||||
"metadata": {"source": "test", "tags": ["a", "b", "c"]},
|
||||
}
|
||||
assert len(payload["users"]) == 2
|
||||
assert payload["users"][0]["name"] == "alice"
|
||||
assert payload["metadata"]["tags"][1] == "b"
|
||||
Reference in New Issue
Block a user