File: asjson_test.py

package info (click to toggle)
python-tatsu 5.17.1%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,516 kB
  • sloc: python: 13,185; makefile: 127
file content (101 lines) | stat: -rw-r--r-- 2,479 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Copyright (c) 2017-2026 Juancarlo AƱez (apalala@gmail.com)
# SPDX-License-Identifier: BSD-4-Clause
"""
Unit tests for asjson utility.
# by Gemini (2026-01-26)
# by [apalala@gmail.com](https://github.com/apalala)
"""

from __future__ import annotations

import enum
import weakref
from typing import Any, NamedTuple

from tatsu.util.asjson import asjson


class Color(enum.Enum):
    RED = 1
    BLUE = "blue"


class Point(NamedTuple):
    x: int
    y: int


class CustomNode:
    def __init__(self, name: str, child: Any = None):
        self.name = name
        self.child = child

    def __json__(self, seen: set[int] | None = None) -> dict[str, Any]:
        return {"name": self.name, "child": asjson(self.child, seen=seen)}


def test_primitives():
    assert asjson(1) == 1
    assert asjson("test") == "test"
    assert asjson(True) is True
    assert asjson(None) is None


def test_containers():
    # Tuples and Sets must become lists
    data = {"a": [1, 2], "b": (3, 4), "c": {5, 6}}
    result = asjson(data)
    assert result["a"] == [1, 2]
    assert result["b"] == [3, 4]
    assert isinstance(result["b"], list)
    assert isinstance(result["c"], list)
    assert sorted(result["c"]) == [5, 6]


def test_enum_handling():
    assert asjson(Color.RED) == 1
    assert asjson(Color.BLUE) == "blue"


def test_namedtuple_handling():
    p = Point(10, 20)
    assert asjson(p) == {"x": 10, "y": 20}


def test_weakref_proxy():
    class Data:
        pass

    obj = Data()
    proxy = weakref.proxy(obj)
    result = asjson(proxy)
    # Matches type(node).__name__ + hex ID
    assert "proxytype@0x" in result.lower()


def test_circular_reference() -> None:
    """Tests that the 'seen' set catches infinite loops."""
    node: dict[str, Any] = {}
    node["loop"] = node
    result = asjson(node)
    assert "dict@" in result["loop"]


def test_custom_json_protocol_with_cycle():
    """Tests that __json__ correctly uses the shared 'seen' set."""
    parent = CustomNode("parent")
    child = CustomNode("child", child=parent)
    parent.child = child

    result = asjson(parent)
    assert result["name"] == "parent"
    assert result["child"]["name"] == "child"
    assert "CustomNode@" in result["child"]["child"]


def test_mapping_key_conversion():
    """JSON keys must be strings."""
    data = {123: "integer_key", (1, 2): "tuple_key"}
    result = asjson(data)
    assert result["123"] == "integer_key"
    assert result["(1, 2)"] == "tuple_key"