Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions src/cl_sii/extras/dj_model_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,29 +153,37 @@ def to_python(self, value: Optional[object]) -> Optional[Rut]:
if the data can't be converted

"""
if value is None or isinstance(value, Rut):
if value is None:
converted_value = value
else:
try:
converted_value = Rut(value, validate_dv=self.validate_dv) # type: ignore
except (AttributeError, TypeError, ValueError) as exc:
if (
isinstance(exc, ValueError)
and exc.args
and exc.args[0] == Rut.INVALID_DV_ERROR_MESSAGE
):
raise django.core.exceptions.ValidationError(
self.error_messages['invalid_dv'],
code='invalid_dv',
params={'value': value},
)

return converted_value
elif isinstance(value, Rut):
if not self.validate_dv:
converted_value = value
return converted_value
elif self.validate_dv and value.validate_dv(raise_exception=False):
converted_value = value
return converted_value

try:
converted_value = Rut(value, validate_dv=self.validate_dv) # type: ignore
except (AttributeError, TypeError, ValueError) as exc:
if (
isinstance(exc, ValueError)
and exc.args
and exc.args[0] == Rut.INVALID_DV_ERROR_MESSAGE
):
raise django.core.exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
self.error_messages['invalid_dv'],
code='invalid_dv',
params={'value': value},
)

raise django.core.exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

return converted_value

def value_to_string(self, obj: django.db.models.Model) -> str:
Expand Down
37 changes: 37 additions & 0 deletions src/tests/test_extras_dj_model_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class RutFieldTest(unittest.TestCase):
valid_rut_canonical: str
valid_rut_instance: Rut
valid_rut_canonical_with_invalid_dv: str
valid_rut_canonical_instance_with_invalid_dv: Rut
valid_rut_verbose_leading_zero_lowercase: str
mock_model_instance: django.db.models.Model

Expand All @@ -19,6 +20,10 @@ def setUpClass(cls) -> None:
cls.valid_rut_canonical = '60803000-K'
cls.valid_rut_instance = Rut(cls.valid_rut_canonical)
cls.valid_rut_canonical_with_invalid_dv = '60803000-0'
cls.valid_rut_canonical_instance_with_invalid_dv = Rut(
cls.valid_rut_canonical_with_invalid_dv
)
assert not cls.valid_rut_canonical_instance_with_invalid_dv.validate_dv()
cls.valid_rut_verbose_leading_zero_lowercase = '060.803.000-k'
cls.mock_model_instance = unittest.mock.create_autospec(
django.db.models.Model, instance=True
Expand All @@ -43,6 +48,14 @@ def test_get_prep_value_of_None(self) -> None:
prepared_value = RutField().get_prep_value(None)
self.assertIsNone(prepared_value)

def test_clean_value_with_invalid_type(self) -> None:
for value_with_invalid_type in [12345678, 12.34, [], {}, object()]:
with self.subTest(value=value_with_invalid_type):
rut_field = RutField()
with self.assertRaises(django.core.exceptions.ValidationError) as cm:
rut_field.clean(value_with_invalid_type, self.mock_model_instance)
self.assertEqual(cm.exception.code, 'invalid')

def test_clean_value_of_rut_str_with_invalid_dv_if_validated(self) -> None:
rut_field = RutField(validate_dv=True)
with self.assertRaises(django.core.exceptions.ValidationError) as cm:
Expand All @@ -57,6 +70,30 @@ def test_clean_value_of_rut_str_with_invalid_dv_if_not_validated(self) -> None:
self.assertIsInstance(cleaned_value, Rut)
self.assertEqual(cleaned_value.canonical, self.valid_rut_canonical_with_invalid_dv)

def test_clean_value_of_rut_instance_with_valid_dv(self) -> None:
for validate_dv in [True, False]:
with self.subTest(validate_dv=validate_dv):
rut_field = RutField(validate_dv=validate_dv)
cleaned_value = rut_field.clean(self.valid_rut_instance, self.mock_model_instance)
self.assertIsInstance(cleaned_value, Rut)
self.assertEqual(cleaned_value, self.valid_rut_instance)

def test_clean_value_of_rut_instance_with_invalid_dv_if_validated(self) -> None:
rut_field = RutField(validate_dv=True)
with self.assertRaises(django.core.exceptions.ValidationError) as cm:
rut_field.clean(
self.valid_rut_canonical_instance_with_invalid_dv, self.mock_model_instance
)
self.assertEqual(cm.exception.code, 'invalid_dv')

def test_clean_value_of_rut_instance_with_invalid_dv_if_not_validated(self) -> None:
rut_field = RutField(validate_dv=False)
cleaned_value = rut_field.clean(
self.valid_rut_canonical_instance_with_invalid_dv, self.mock_model_instance
)
self.assertIsInstance(cleaned_value, Rut)
self.assertEqual(cleaned_value, self.valid_rut_canonical_instance_with_invalid_dv)

def test_deconstruct_without_options(self) -> None:
name, path, args, kwargs = RutField().deconstruct()
self.assertEqual(path, 'cl_sii.extras.dj_model_fields.RutField')
Expand Down
Loading