From c33f211633a1bce19d62aa3e41059620407a35d1 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 12 Jan 2025 19:12:53 -0600 Subject: [PATCH] fix: add grid filters specific to numeric, integer types --- src/wuttaweb/grids/filters.py | 29 +++++++++++++++++++++++++++++ tests/grids/test_filters.py | 24 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/wuttaweb/grids/filters.py b/src/wuttaweb/grids/filters.py index 6be29c7..1250b3d 100644 --- a/src/wuttaweb/grids/filters.py +++ b/src/wuttaweb/grids/filters.py @@ -465,6 +465,33 @@ class StringAlchemyFilter(AlchemyFilter): sa.and_(*criteria))) +class NumericAlchemyFilter(AlchemyFilter): + """ + SQLAlchemy filter option for a numeric data column. + + Subclass of :class:`AlchemyFilter`. + """ + default_verbs = ['equal', 'not_equal', + 'greater_than', 'greater_equal', + 'less_than', 'less_equal'] + + +class IntegerAlchemyFilter(NumericAlchemyFilter): + """ + SQLAlchemy filter option for an integer data column. + + Subclass of :class:`NumericAlchemyFilter`. + """ + + def coerce_value(self, value): + """ """ + if value: + try: + return int(value) + except: + pass + + class BooleanAlchemyFilter(AlchemyFilter): """ SQLAlchemy filter option for a boolean data column. @@ -568,6 +595,8 @@ default_sqlalchemy_filters = { None: AlchemyFilter, sa.String: StringAlchemyFilter, sa.Text: StringAlchemyFilter, + sa.Numeric: NumericAlchemyFilter, + sa.Integer: IntegerAlchemyFilter, sa.Boolean: BooleanAlchemyFilter, sa.Date: DateAlchemyFilter, } diff --git a/tests/grids/test_filters.py b/tests/grids/test_filters.py index bbc6611..557dbff 100644 --- a/tests/grids/test_filters.py +++ b/tests/grids/test_filters.py @@ -326,6 +326,30 @@ class TestStringAlchemyFilter(WebTestCase): self.assertEqual(filtered_query.count(), 6) +class TestIntegerAlchemyFilter(WebTestCase): + + def make_filter(self, model_property, **kwargs): + factory = kwargs.pop('factory', mod.IntegerAlchemyFilter) + kwargs['model_property'] = model_property + return factory(self.request, model_property.key, **kwargs) + + def test_coerce_value(self): + model = self.app.model + filtr = self.make_filter(model.Upgrade.exit_code) + + # null + self.assertIsNone(filtr.coerce_value(None)) + self.assertIsNone(filtr.coerce_value('')) + + # typical + self.assertEqual(filtr.coerce_value('42'), 42) + self.assertEqual(filtr.coerce_value('-42'), -42) + + # invalid + self.assertIsNone(filtr.coerce_value('42.12')) + self.assertIsNone(filtr.coerce_value('bogus')) + + class TestBooleanAlchemyFilter(WebTestCase): def setUp(self):