fix: add DateTimeAlchemyFilter for datetime columns
This commit is contained in:
parent
f8cb97ce63
commit
20a586e950
2 changed files with 397 additions and 7 deletions
|
|
@ -9,6 +9,7 @@ from unittest.mock import patch
|
|||
import sqlalchemy as sa
|
||||
|
||||
from wuttjamaican.db.model import Base
|
||||
from wuttjamaican.util import get_timezone_by_name
|
||||
|
||||
from wuttaweb.grids import filters as mod
|
||||
from wuttaweb.testing import WebTestCase
|
||||
|
|
@ -569,7 +570,8 @@ class TestBooleanAlchemyFilter(WebTestCase):
|
|||
class TheLocalThing(Base):
|
||||
__tablename__ = "the_local_thing"
|
||||
id = sa.Column(sa.Integer(), primary_key=True, autoincrement=False)
|
||||
date = sa.Column(sa.DateTime(timezone=True), nullable=True)
|
||||
date = sa.Column(sa.Date(), nullable=True)
|
||||
timestamp = sa.Column(sa.DateTime(), nullable=True)
|
||||
|
||||
|
||||
class TestDateAlchemyFilter(WebTestCase):
|
||||
|
|
@ -604,7 +606,7 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
# null value
|
||||
self.assertIsNone(filtr.coerce_value(None))
|
||||
|
||||
# value as datetime
|
||||
# value as date
|
||||
value = datetime.date(2024, 1, 1)
|
||||
result = filtr.coerce_value(value)
|
||||
self.assertIs(value, result)
|
||||
|
|
@ -717,7 +719,7 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, "2024-04-01")
|
||||
|
|
@ -725,6 +727,238 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
|
||||
class TestDateTimeAlchemyFilter(WebTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.setup_web()
|
||||
self.tzlocal = get_timezone_by_name("America/Los_Angeles")
|
||||
|
||||
self.sample_data = [
|
||||
{
|
||||
"id": 1,
|
||||
"timestamp": self.app.make_utc(
|
||||
datetime.datetime(2024, 1, 1, 1, 20, tzinfo=self.tzlocal)
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"timestamp": self.app.make_utc(
|
||||
datetime.datetime(2024, 1, 1, 23, 40, tzinfo=self.tzlocal)
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"timestamp": self.app.make_utc(
|
||||
datetime.datetime(2024, 3, 1, 22, 10, tzinfo=self.tzlocal)
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"timestamp": self.app.make_utc(
|
||||
datetime.datetime(2024, 3, 1, 2, 0, tzinfo=self.tzlocal)
|
||||
),
|
||||
},
|
||||
{"id": 5, "timestamp": None},
|
||||
{"id": 6, "timestamp": None},
|
||||
]
|
||||
|
||||
for thing in self.sample_data:
|
||||
thing = TheLocalThing(**thing)
|
||||
self.session.add(thing)
|
||||
self.session.commit()
|
||||
|
||||
self.sample_query = self.session.query(TheLocalThing)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop("factory", mod.DateTimeAlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_coerce_value(self):
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
|
||||
# null value
|
||||
self.assertIsNone(filtr.coerce_value(None))
|
||||
|
||||
# value as date
|
||||
value = datetime.date(2024, 1, 1)
|
||||
result = filtr.coerce_value(value)
|
||||
self.assertIs(value, result)
|
||||
|
||||
# value as string
|
||||
result = filtr.coerce_value("2024-04-01")
|
||||
self.assertIsInstance(result, datetime.date)
|
||||
self.assertEqual(result, datetime.date(2024, 4, 1))
|
||||
|
||||
# invalid
|
||||
result = filtr.coerce_value("thisinputisbad")
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_equal(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_equal(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_equal(
|
||||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_equal(self.sample_query, "2024-02-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 0)
|
||||
filtered_query = filtr.filter_equal(self.sample_query, "2024-01-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
def test_not_equal(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_not_equal(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, "2024-02-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, "2024-01-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
def test_greater_than(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_greater_than(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_greater_than(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_greater_than(self.sample_query, "2024-02-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
def test_greater_equal(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date (clear of boundary)
|
||||
filtered_query = filtr.filter_greater_equal(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as date (at boundary)
|
||||
filtered_query = filtr.filter_greater_equal(
|
||||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, "2024-01-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
def test_less_than(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_less_than(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_less_than(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_less_than(self.sample_query, "2024-04-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
def test_less_equal(self):
|
||||
model = self.app.model
|
||||
with patch.object(self.app, "get_timezone", return_value=self.tzlocal):
|
||||
|
||||
filtr = self.make_filter(TheLocalThing.timestamp)
|
||||
self.assertEqual(self.sample_query.count(), 6)
|
||||
|
||||
# null value ignored
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date (clear of boundary)
|
||||
filtered_query = filtr.filter_less_equal(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as date (at boundary)
|
||||
filtered_query = filtr.filter_less_equal(
|
||||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, "2024-04-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
|
||||
class TestVerbNotSupported(TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue