Skip to content

Commit c2349d0

Browse files
authored
Fix validation for dates from datetime strings (#110)
Signed-off-by: Pascal Tomecek <[email protected]>
1 parent a33aa7b commit c2349d0

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

ccflow/tests/test_context.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ def test_date_validation(self):
5454
self.assertEqual(TypeAdapter(DateContext).validate_python(str(date.today())), c)
5555
self.assertEqual(TypeAdapter(DateContext).validate_python("0d"), c)
5656
self.assertEqual(TypeAdapter(DateContext).validate_python("-1d"), c1)
57-
self.assertRaises(ValueError, TypeAdapter(DateContext).validate_python, "foo")
57+
self.assertRaises(ValidationError, TypeAdapter(DateContext).validate_python, "foo")
58+
self.assertRaises(ValidationError, TypeAdapter(DateContext).validate_python, None)
5859

59-
# Test validation from datetime (not normally allowed by pydantic)
60+
def test_date_from_datetime_validation(self):
6061
dt = datetime(2022, 1, 1, 12, tzinfo=timezone.utc)
6162
self.assertEqual(TypeAdapter(DateContext).validate_python(dt), DateContext(date=dt.date()))
63+
self.assertEqual(TypeAdapter(DateContext).validate_python(dt.isoformat()), DateContext(date=dt.date()))
6264

6365
def test_datetime_validation(self):
6466
dt = datetime(2022, 1, 1, 12, 0, tzinfo=timezone.utc)

ccflow/tests/test_validators.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from datetime import date, timedelta
2+
from datetime import date, datetime, timedelta
33
from unittest import TestCase
44

55
from ccflow.validators import eval_or_load_object, load_object, normalize_date, str_to_log_level
@@ -12,10 +12,17 @@ class A:
1212
class TestValidators(TestCase):
1313
def test_normalize_date(self):
1414
c = date.today()
15+
self.assertEqual(normalize_date(c), c)
1516
self.assertEqual(normalize_date("0d"), c)
1617
c1 = date.today() - timedelta(1)
1718
self.assertEqual(normalize_date("-1d"), c1)
1819

20+
self.assertEqual(normalize_date(datetime.now()), c)
21+
self.assertEqual(normalize_date(datetime.now().isoformat()), c)
22+
23+
self.assertEqual(normalize_date("foo"), "foo")
24+
self.assertEqual(normalize_date(None), None)
25+
1926
def test_load_object(self):
2027
self.assertEqual(load_object("ccflow.tests.test_validators.A"), A)
2128
self.assertIsNone(load_object(None))

ccflow/validators.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from typing import Any, Dict, Optional
66

77
import pandas as pd
8-
from pydantic import ValidationError
8+
from pydantic import TypeAdapter, ValidationError
99

1010
from .exttypes import PyObjectPath
1111

12+
_DatetimeAdapter = TypeAdapter(datetime)
13+
1214

1315
def normalize_date(v: Any) -> Any:
1416
"""Validator that will convert string offsets to date based on today, and convert datetime to date."""
@@ -18,8 +20,14 @@ def normalize_date(v: Any) -> Any:
1820
return timestamp.date()
1921
except ValueError:
2022
pass
21-
if isinstance(v, datetime):
22-
return v.date()
23+
# Convert from anything that can be converted to a datetime to a date via datetime
24+
# This is not normally allowed by pydantic.
25+
try:
26+
v = _DatetimeAdapter.validate_python(v)
27+
if isinstance(v, datetime):
28+
return v.date()
29+
except ValidationError:
30+
pass
2331
return v
2432

2533

0 commit comments

Comments
 (0)