Skip to content

Commit 8dbac15

Browse files
committed
Added test for composite type deserialization
Signed-off-by: chandr-andr (Kiselev Aleksandr) <chandr@chandr.net>
1 parent 7c88475 commit 8dbac15

File tree

1 file changed

+170
-2
lines changed

1 file changed

+170
-2
lines changed

python/tests/test_value_converter.py

Lines changed: 170 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import datetime
22
import uuid
33
from ipaddress import IPv4Address
4-
from typing import Any
4+
from typing import Any, Dict, List
55

66
import pytest
7+
from pydantic import BaseModel
78
from tests.conftest import DefaultPydanticModel, DefaultPythonModelClass
89

910
from psqlpy import ConnectionPool
@@ -232,7 +233,7 @@ async def test_as_class(
232233
),
233234
),
234235
)
235-
async def test_deserialization_rust_into_python(
236+
async def test_deserialization_simple_into_python(
236237
psql_pool: ConnectionPool,
237238
postgres_type: str,
238239
py_value: Any,
@@ -257,3 +258,170 @@ async def test_deserialization_rust_into_python(
257258
)
258259

259260
assert raw_result.result()[0]["test_field"] == expected_deserialized
261+
262+
263+
async def test_deserialization_composite_into_python(
264+
psql_pool: ConnectionPool,
265+
) -> None:
266+
"""Test that it's possible to deserialize custom postgresql type."""
267+
await psql_pool.execute("DROP TABLE IF EXISTS for_test")
268+
await psql_pool.execute("DROP TYPE IF EXISTS all_types")
269+
create_type_query = """
270+
CREATE type all_types AS (
271+
bytea_ BYTEA,
272+
varchar_ VARCHAR,
273+
text_ TEXT,
274+
bool_ BOOL,
275+
int2_ INT2,
276+
int4_ INT4,
277+
int8_ INT8,
278+
flaot4_ FLOAT4,
279+
date_ DATE,
280+
time_ TIME,
281+
timestamp_ TIMESTAMP,
282+
timestampz_ TIMESTAMPTZ,
283+
uuid_ UUID,
284+
inet_ INET,
285+
jsonb_ JSONB,
286+
json_ JSON,
287+
288+
varchar_arr VARCHAR ARRAY,
289+
text_arr TEXT ARRAY,
290+
bool_arr BOOL ARRAY,
291+
int2_arr INT2 ARRAY,
292+
int4_arr INT4 ARRAY,
293+
int8_arr INT8 ARRAY,
294+
flaot4_arr FLOAT4 ARRAY,
295+
date_arr DATE ARRAY,
296+
time_arr TIME ARRAY,
297+
timestamp_arr TIMESTAMP ARRAY,
298+
timestampz_arr TIMESTAMPTZ ARRAY,
299+
uuid_arr UUID ARRAY,
300+
inet_arr INET ARRAY,
301+
jsonb_arr JSONB ARRAY,
302+
json_arr JSON ARRAY
303+
)
304+
"""
305+
create_table_query = """
306+
CREATE table for_test (custom_type all_types)
307+
"""
308+
309+
await psql_pool.execute(
310+
querystring=create_type_query,
311+
)
312+
await psql_pool.execute(
313+
querystring=create_table_query,
314+
)
315+
await psql_pool.execute(
316+
querystring="INSERT INTO for_test VALUES (ROW($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))", # noqa: E501
317+
parameters=[
318+
b"Bytes",
319+
"Some String",
320+
PyText("Some String"),
321+
True,
322+
SmallInt(123),
323+
Integer(199),
324+
BigInt(10001),
325+
32.12329864501953,
326+
now_datetime.date(),
327+
now_datetime.time(),
328+
now_datetime,
329+
now_datetime_with_tz,
330+
PyUUID(str(uuid_)),
331+
IPv4Address("192.0.0.1"),
332+
{
333+
"test": ["something", 123, "here"],
334+
"nested": ["JSON"],
335+
},
336+
PyJSON(
337+
{
338+
"test": ["something", 123, "here"],
339+
"nested": ["JSON"],
340+
},
341+
),
342+
["Some String", "Some String"],
343+
[PyText("Some String"), PyText("Some String")],
344+
[True, False],
345+
[SmallInt(123), SmallInt(321)],
346+
[Integer(123), Integer(321)],
347+
[BigInt(10001), BigInt(10001)],
348+
[32.12329864501953, 32.12329864501953],
349+
[now_datetime.date(), now_datetime.date()],
350+
[now_datetime.time(), now_datetime.time()],
351+
[now_datetime, now_datetime],
352+
[now_datetime_with_tz, now_datetime_with_tz],
353+
[PyUUID(str(uuid_)), PyUUID(str(uuid_))],
354+
[IPv4Address("192.0.0.1"), IPv4Address("192.0.0.1")],
355+
[
356+
{
357+
"test": ["something", 123, "here"],
358+
"nested": ["JSON"],
359+
},
360+
{
361+
"test": ["something", 123, "here"],
362+
"nested": ["JSON"],
363+
},
364+
],
365+
[
366+
PyJSON(
367+
{
368+
"test": ["something", 123, "here"],
369+
"nested": ["JSON"],
370+
},
371+
),
372+
PyJSON(
373+
{
374+
"test": ["something", 123, "here"],
375+
"nested": ["JSON"],
376+
},
377+
),
378+
],
379+
],
380+
)
381+
382+
class ValidateModelForCustomType(BaseModel):
383+
bytea_: list[int]
384+
varchar_: str
385+
text_: str
386+
bool_: bool
387+
int2_: int
388+
int4_: int
389+
int8_: int
390+
flaot4_: float
391+
date_: datetime.date
392+
time_: datetime.time
393+
timestamp_: datetime.datetime
394+
timestampz_: datetime.datetime
395+
uuid_: uuid.UUID
396+
inet_: IPv4Address
397+
jsonb_: Dict[str, List[str]]
398+
json_: Dict[str, List[str]]
399+
400+
varchar_arr: List[str]
401+
text_arr: List[str]
402+
bool_arr: List[bool]
403+
int2_arr: List[int]
404+
int4_arr: List[int]
405+
int8_arr: List[int]
406+
flaot4_arr: List[float]
407+
date_arr: List[datetime.date]
408+
time_arr: List[datetime.time]
409+
timestamp_arr: List[datetime.datetime]
410+
timestampz_arr: List[datetime.datetime]
411+
uuid_arr: List[uuid.UUID]
412+
inet_arr: List[IPv4Address]
413+
jsonb_arr: List[Dict[str, List[str]]]
414+
json_arr: List[Dict[str, List[str]]]
415+
416+
class TopLevelModel(BaseModel):
417+
custom_type: ValidateModelForCustomType
418+
419+
query_result = await psql_pool.execute(
420+
"SELECT custom_type FROM for_test",
421+
)
422+
423+
model_result = query_result.as_class(
424+
as_class=TopLevelModel,
425+
)
426+
427+
assert isinstance(model_result[0], TopLevelModel)

0 commit comments

Comments
 (0)