| 899 | |
| 900 | |
| 901 | def test_json_datetime_serialization(): |
| 902 | class InputSchema(pw.Schema): |
| 903 | a: pw.Json |
| 904 | b: pw.PyObjectWrapper[dict] |
| 905 | c: pw.PyObjectWrapper[dict] |
| 906 | |
| 907 | @pw.udf |
| 908 | def to_json(obj: pw.PyObjectWrapper[dict]) -> pw.Json: |
| 909 | return pw.Json(obj.value) |
| 910 | |
| 911 | @pw.udf |
| 912 | def to_json_wrapped(obj) -> pw.Json: |
| 913 | return pw.Json({k: pw.Json(v) for k, v in obj.value.items()}) |
| 914 | |
| 915 | obj = { |
| 916 | "dtn": datetime.datetime(2025, 3, 14, 10, 13), |
| 917 | "dt": datetime.datetime( |
| 918 | 2025, 3, 14, 10, 13, microsecond=123456, tzinfo=datetime.timezone.utc |
| 919 | ), |
| 920 | "pdn": pd.Timestamp("2025-03-14"), |
| 921 | "pd": pd.Timestamp("2025-03-14T00:00+00:00"), |
| 922 | "pwn": pw.DateTimeNaive("2025-03-14T10:13:00.123456789"), |
| 923 | "pw": pw.DateTimeUtc("2025-03-14T10:13:00.123456000+00:00"), |
| 924 | "dur": pd.Timedelta("4 days 2 microseconds"), |
| 925 | } |
| 926 | |
| 927 | rows = [{"a": obj, "b": pw.wrap_py_object(obj), "c": pw.wrap_py_object(obj)}] |
| 928 | |
| 929 | table = pw.debug.table_from_rows( |
| 930 | InputSchema, |
| 931 | [tuple(row.values()) for row in rows], |
| 932 | ).select(a=pw.this.a, b=to_json(pw.this.b), c=to_json_wrapped(pw.this.c)) |
| 933 | |
| 934 | expected = { |
| 935 | "dtn": "2025-03-14T10:13:00.000000000", |
| 936 | "dt": "2025-03-14T10:13:00.123456000+00:00", |
| 937 | "pdn": "2025-03-14T00:00:00.000000000", |
| 938 | "pd": "2025-03-14T00:00:00.000000000+00:00", |
| 939 | "pwn": "2025-03-14T10:13:00.123456789", |
| 940 | "pw": "2025-03-14T10:13:00.123456000+00:00", |
| 941 | "dur": 345600000002000, |
| 942 | } |
| 943 | |
| 944 | keys, result = pw.debug.table_to_dicts(table) |
| 945 | |
| 946 | for col_name in ["a", "b", "c"]: |
| 947 | val = result[col_name][keys[0]] |
| 948 | assert isinstance(val, pw.Json) |
| 949 | assert val.as_dict() == expected |
| 950 | |
| 951 | |
| 952 | def test_json_serde(tmp_path: pathlib.Path): |