Skip to content

Commit 3a049e5

Browse files
committed
refactor: improve type handling and assertions in deserialization tests
- Updated import statements to use importlib for dynamic module loading. - Enhanced type assertions in `restore_row_integer_types` and `restore_row_date_types` tests to ensure results are of expected types (list or dict). - Adjusted handling of non-dict items in row descriptions for better type safety.
1 parent 1b129d0 commit 3a049e5

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

tests/unit/test_psycopg_utils.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
import base64
66
import datetime as dt
7+
import importlib
78
import uuid
89
from decimal import Decimal
10+
from typing import Any, cast
911
from unittest.mock import patch
1012

1113
import pytest
@@ -124,7 +126,8 @@ def test_range_empty_without_psycopg(self):
124126

125127
@pytest.mark.skipif(not HAS_PSYCOPG_RANGE, reason="psycopg not installed")
126128
def test_range_dict_with_psycopg_returns_range(self):
127-
from psycopg.types.range import Range
129+
range_module = importlib.import_module("psycopg.types.range")
130+
Range = range_module.Range
128131

129132
range_val = {"__range__": {"lower": 1, "upper": 5, "bounds": "[)"}}
130133
result = deserialize_db_value(range_val)
@@ -133,7 +136,8 @@ def test_range_dict_with_psycopg_returns_range(self):
133136

134137
@pytest.mark.skipif(not HAS_PSYCOPG_RANGE, reason="psycopg not installed")
135138
def test_range_empty_with_psycopg_returns_empty_range(self):
136-
from psycopg.types.range import Range
139+
range_module = importlib.import_module("psycopg.types.range")
140+
Range = range_module.Range
137141

138142
range_val = {"__range__": {"empty": True}}
139143
result = deserialize_db_value(range_val)
@@ -258,6 +262,7 @@ def test_list_row_converts_integer_float_to_int(self):
258262
{"name": "count", "type_code": 23}, # INTEGER
259263
]
260264
result = restore_row_integer_types(row, description)
265+
assert isinstance(result, list)
261266
assert result == [1, "hello", 3]
262267
assert isinstance(result[0], int)
263268
assert isinstance(result[2], int)
@@ -266,20 +271,23 @@ def test_list_row_does_not_convert_non_whole_float(self):
266271
row = [1.5]
267272
description = [{"name": "val", "type_code": 23}]
268273
result = restore_row_integer_types(row, description)
274+
assert isinstance(result, list)
269275
assert result == [1.5]
270276
assert isinstance(result[0], float)
271277

272278
def test_list_row_does_not_convert_non_integer_type(self):
273279
row = [1.0]
274280
description = [{"name": "val", "type_code": 1700}] # NUMERIC
275281
result = restore_row_integer_types(row, description)
282+
assert isinstance(result, list)
276283
assert result == [1.0]
277284
assert isinstance(result[0], float)
278285

279286
def test_list_row_bigint_type_code(self):
280287
row = [9999999999.0]
281288
description = [{"name": "val", "type_code": 20}] # BIGINT
282289
result = restore_row_integer_types(row, description)
290+
assert isinstance(result, list)
283291
assert result == [9999999999]
284292
assert isinstance(result[0], int)
285293

@@ -311,6 +319,7 @@ def test_list_row_extra_columns_beyond_description(self):
311319
row = [1.0, 2.0, 3.0]
312320
description = [{"name": "a", "type_code": 23}] # only one column described
313321
result = restore_row_integer_types(row, description)
322+
assert isinstance(result, list)
314323
assert result[0] == 1
315324
# extra values beyond description appended as-is
316325
assert result[1] == 2.0
@@ -319,7 +328,7 @@ def test_list_row_extra_columns_beyond_description(self):
319328
def test_list_row_description_with_non_dict_items(self):
320329
row = [1.0]
321330
description = [None] # non-dict description item
322-
result = restore_row_integer_types(row, description)
331+
result = restore_row_integer_types(row, cast(list[dict[str, Any]], description))
323332
# type_code is None, not in POSTGRES_INTEGER_TYPE_CODES → no conversion
324333
assert result == [1.0]
325334

@@ -333,26 +342,30 @@ def test_dict_row_converts_integer_float_to_int(self):
333342
{"name": "count", "type_code": 23},
334343
]
335344
result = restore_row_integer_types(row, description)
345+
assert isinstance(result, dict)
336346
assert result == {"id": 5, "name": "test", "count": 3}
337347
assert isinstance(result["id"], int)
338348

339349
def test_dict_row_does_not_convert_non_whole_float(self):
340350
row = {"val": 1.5}
341351
description = [{"name": "val", "type_code": 23}]
342352
result = restore_row_integer_types(row, description)
353+
assert isinstance(result, dict)
343354
assert result["val"] == 1.5
344355

345356
def test_dict_row_unknown_column_not_converted(self):
346357
row = {"unknown": 5.0}
347358
description = [{"name": "id", "type_code": 23}]
348359
result = restore_row_integer_types(row, description)
360+
assert isinstance(result, dict)
349361
# "unknown" not in type_code_by_name, so type_code is None
350362
assert result["unknown"] == 5.0
351363

352364
def test_dict_row_description_with_non_dict_items(self):
353365
row = {"id": 5.0}
354366
description = [None] # non-dict item
355-
result = restore_row_integer_types(row, description)
367+
result = restore_row_integer_types(row, cast(list[dict[str, Any]], description))
368+
assert isinstance(result, dict)
356369
# Non-dict items in description are skipped (no name extracted)
357370
assert result["id"] == 5.0
358371

@@ -428,14 +441,15 @@ def test_list_row_beyond_description_length(self):
428441
row = ["2023-01-15", "extra"]
429442
description = [{"name": "d", "type_code": POSTGRES_DATE_TYPE_CODE}]
430443
result = restore_row_date_types(row, description)
444+
assert isinstance(result, list)
431445
# index 0 converted, index 1 beyond description → no type_code → passthrough
432446
assert result[0] == dt.date(2023, 1, 15)
433447
assert result[1] == "extra"
434448

435449
def test_list_row_non_dict_description_item(self):
436450
row = ["2023-01-15"]
437451
description = [None]
438-
result = restore_row_date_types(row, description)
452+
result = restore_row_date_types(row, cast(list[dict[str, Any]], description))
439453
assert result == ["2023-01-15"]
440454

441455
# --- dict row ---
@@ -447,32 +461,37 @@ def test_dict_row_converts_date_string(self):
447461
{"name": "name", "type_code": 25},
448462
]
449463
result = restore_row_date_types(row, description)
464+
assert isinstance(result, dict)
450465
assert result["created"] == dt.date(2023, 6, 1)
451466
assert result["name"] == "test"
452467

453468
def test_dict_row_converts_time_string(self):
454469
row = {"start_time": "08:00:00"}
455470
description = [{"name": "start_time", "type_code": 1083}]
456471
result = restore_row_date_types(row, description)
472+
assert isinstance(result, dict)
457473
assert result["start_time"] == dt.time(8, 0, 0)
458474

459475
def test_dict_row_unknown_column_passthrough(self):
460476
row = {"unknown": "2023-01-15"}
461477
description = [{"name": "other", "type_code": POSTGRES_DATE_TYPE_CODE}]
462478
result = restore_row_date_types(row, description)
479+
assert isinstance(result, dict)
463480
# "unknown" not in type_code_by_name → type_code None → passthrough
464481
assert result["unknown"] == "2023-01-15"
465482

466483
def test_dict_row_non_string_not_converted(self):
467484
row = {"d": 12345}
468485
description = [{"name": "d", "type_code": POSTGRES_DATE_TYPE_CODE}]
469486
result = restore_row_date_types(row, description)
487+
assert isinstance(result, dict)
470488
assert result["d"] == 12345
471489

472490
def test_dict_row_non_dict_description_items_skipped(self):
473491
row = {"d": "2023-01-15"}
474492
description = [None]
475-
result = restore_row_date_types(row, description)
493+
result = restore_row_date_types(row, cast(list[dict[str, Any]], description))
494+
assert isinstance(result, dict)
476495
assert result["d"] == "2023-01-15"
477496

478497
# --- mixed columns ---
@@ -486,6 +505,7 @@ def test_list_row_mixed_types(self):
486505
{"name": "int_col", "type_code": 23},
487506
]
488507
result = restore_row_date_types(row, description)
508+
assert isinstance(result, list)
489509
assert result[0] == dt.date(2023, 1, 15)
490510
assert result[1] == dt.time(14, 30, 0)
491511
assert result[2] == "plain text"

0 commit comments

Comments
 (0)