fix: restore PostgreSQL range values during import
This commit is contained in:
@@ -1,10 +1,34 @@
|
||||
import datetime
|
||||
import decimal
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
|
||||
from netbox_export.services import codec
|
||||
from netbox_export.services.codec import decode_scalar, encode_scalar
|
||||
|
||||
|
||||
@dataclass
|
||||
class FakeRange:
|
||||
lower: object = None
|
||||
upper: object = None
|
||||
bounds: str = "[)"
|
||||
empty: bool = False
|
||||
|
||||
@property
|
||||
def lower_inc(self):
|
||||
return not self.empty and self.bounds[0] == "["
|
||||
|
||||
@property
|
||||
def upper_inc(self):
|
||||
return not self.empty and self.bounds[1] == "]"
|
||||
|
||||
@property
|
||||
def isempty(self):
|
||||
return self.empty
|
||||
|
||||
|
||||
def test_scalar_round_trip():
|
||||
value = {
|
||||
"decimal": decimal.Decimal("12.340"),
|
||||
@@ -17,3 +41,31 @@ def test_scalar_round_trip():
|
||||
|
||||
assert decode_scalar(encode_scalar(value)) == value
|
||||
|
||||
|
||||
def test_postgresql_range_round_trip(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
codec,
|
||||
"_make_range",
|
||||
lambda lower, upper, bounds, empty: FakeRange(lower, upper, bounds, empty),
|
||||
)
|
||||
value = FakeRange(1, 56, "[)")
|
||||
|
||||
encoded = encode_scalar(value)
|
||||
|
||||
assert encoded == {
|
||||
"$type": "range",
|
||||
"lower": 1,
|
||||
"upper": 56,
|
||||
"bounds": "[)",
|
||||
"empty": False,
|
||||
}
|
||||
assert decode_scalar(encoded) == value
|
||||
|
||||
|
||||
def test_real_psycopg_range_round_trip():
|
||||
pytest.importorskip("psycopg")
|
||||
from django.db.backends.postgresql.psycopg_any import NumericRange
|
||||
|
||||
value = NumericRange(1, 56, "[)")
|
||||
|
||||
assert decode_scalar(encode_scalar(value)) == value
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from netbox_export.services.importer import _coerce_model_field_value
|
||||
|
||||
|
||||
@dataclass
|
||||
class FakeRange:
|
||||
lower: object = None
|
||||
upper: object = None
|
||||
bounds: str = "[)"
|
||||
empty: bool = False
|
||||
|
||||
@property
|
||||
def lower_inc(self):
|
||||
return not self.empty and self.bounds[0] == "["
|
||||
|
||||
@property
|
||||
def upper_inc(self):
|
||||
return not self.empty and self.bounds[1] == "]"
|
||||
|
||||
@property
|
||||
def isempty(self):
|
||||
return self.empty
|
||||
|
||||
|
||||
class IntegerField:
|
||||
@staticmethod
|
||||
def to_python(value):
|
||||
return int(value)
|
||||
|
||||
|
||||
class IntegerRangeField:
|
||||
base_field = IntegerField()
|
||||
range_type = FakeRange
|
||||
|
||||
|
||||
class ArrayField:
|
||||
base_field = IntegerRangeField()
|
||||
|
||||
|
||||
def test_legacy_string_ranges_are_restored_for_range_array_fields():
|
||||
value = ["[1, 56)", "(100, 200]", "empty"]
|
||||
|
||||
converted = _coerce_model_field_value(ArrayField(), value)
|
||||
|
||||
assert converted == [
|
||||
FakeRange(1, 56, "[)"),
|
||||
FakeRange(100, 200, "(]"),
|
||||
FakeRange(empty=True),
|
||||
]
|
||||
|
||||
|
||||
def test_range_like_strings_remain_unchanged_for_normal_fields():
|
||||
field = object()
|
||||
|
||||
assert _coerce_model_field_value(field, "[1, 56)") == "[1, 56)"
|
||||
Reference in New Issue
Block a user