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
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.54.0
current_version = 0.55.0
commit = True
tag = False
message = chore: Bump version from {current_version} to {new_version}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:

- name: Set Up Python ${{ matrix.python_version }}
id: set_up_python
uses: actions/setup-python@v5.6.0
uses: actions/setup-python@v6.0.0
with:
python-version: "${{ matrix.python_version }}"
check-latest: true
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:

- name: Set Up Python ${{ matrix.python_version }}
id: set_up_python
uses: actions/setup-python@v5.6.0
uses: actions/setup-python@v6.0.0
with:
python-version: "${{ matrix.python_version }}"
check-latest: true
Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
make test-coverage-report

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
directory: ./test-reports/coverage/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:

- name: Set Up Python
id: set_up_python
uses: actions/setup-python@v5.6.0
uses: actions/setup-python@v6.0.0
with:
python-version: "3.10"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:

- name: Set Up Python
id: set_up_python
uses: actions/setup-python@v5.6.0
uses: actions/setup-python@v6.0.0
with:
python-version: "3.10"

Expand Down
5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# History

## 0.55.0 (2025-09-10)

- (PR #878, 2025-09-10) extras: Improve Django filter for `Rut`
- (PR #879, 2025-09-10) chore(deps): Bump the github-actions-production group with 2 updates

## 0.54.0 (2025-09-09)

- (PR #871, 2025-09-09) rut: Use class variables for exception messages raised by `Rut`
Expand Down
2 changes: 1 addition & 1 deletion src/cl_sii/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

"""

__version__ = '0.54.0'
__version__ = '0.55.0'
48 changes: 31 additions & 17 deletions src/cl_sii/extras/dj_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
except ImportError as exc: # pragma: no cover
raise ImportError("Package 'django-filter' is required to use this module.") from exc

from collections.abc import Sequence
from copy import deepcopy
from typing import ClassVar, Mapping, Tuple, Type
from typing import Any, ClassVar, Mapping, Type

import django.db.models
import django.forms
Expand All @@ -37,9 +38,37 @@ class RutFilter(django_filters.filters.CharFilter):
- https://github.com/carltongibson/django-filter/blob/24.2/docs/ref/filters.txt
"""

field_class: ClassVar[Type[django.forms.Field]]
field_class: Type[django.forms.Field]
field_class = cl_sii.extras.dj_form_fields.RutField

field_class_for_substrings: Type[django.forms.Field]
field_class_for_substrings = django_filters.filters.CharFilter.field_class

lookup_expressions_for_substrings: Sequence[str] = [
'contains',
'icontains',
'startswith',
'istartswith',
'endswith',
'iendswith',
]

def __init__(
self,
field_name: Any = None,
lookup_expr: Any = None,
*args: Any,
**kwargs: Any,
) -> None:
if lookup_expr in self.lookup_expressions_for_substrings:
# Lookups that can be used to search for substrings will not always
# work with the default field class because some substrings cannot
# be converted to instances of class `Rut`. For example,
# `…__contains="803"` fails because `Rut("803")` raises a `ValueError`.
self.field_class = self.field_class_for_substrings

super().__init__(field_name, lookup_expr, *args, **kwargs)


FILTER_FOR_DBFIELD_DEFAULTS = {
**FILTER_FOR_DBFIELD_DEFAULTS,
Expand All @@ -62,18 +91,3 @@ class SiiFilterSet(django_filters.filterset.FilterSet):

FILTER_DEFAULTS: ClassVar[Mapping[Type[django.db.models.Field], Mapping[str, object]]]
FILTER_DEFAULTS = FILTER_FOR_DBFIELD_DEFAULTS

@classmethod
def filter_for_lookup(
cls, field: django.db.models.Field, lookup_type: str
) -> Tuple[Type[django_filters.filters.Filter], Mapping[str, object]]:
filter_class, params = super().filter_for_lookup(field, lookup_type)

# Override RUT containment lookups.
if isinstance(field, cl_sii.extras.dj_model_fields.RutField) and lookup_type in (
'contains',
'icontains',
):
filter_class, params = django_filters.filters.CharFilter, {}

return filter_class, params
68 changes: 68 additions & 0 deletions src/tests/test_extras_dj_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import django_filters

from cl_sii.extras import dj_form_fields, dj_model_fields
from cl_sii.extras.dj_filters import RutFilter, SiiFilterSet


Expand All @@ -22,6 +23,34 @@ def test_new_instance(self) -> None:
self.assertIsInstance(filter, RutFilter)
self.assertIsInstance(filter, django_filters.filters.Filter)

def test_filter_class_lookup_expressions(self) -> None:
expected_field_class = dj_form_fields.RutField
for lookup_expr in [
'exact',
'iexact',
'in',
'gt',
'gte',
'lt',
'lte',
]:
with self.subTest(field_class=expected_field_class, lookup_expr=lookup_expr):
filter_instance = RutFilter(lookup_expr=lookup_expr)
self.assertIs(filter_instance.field_class, expected_field_class)

expected_field_class = django_filters.CharFilter.field_class
for lookup_expr in [
'contains',
'icontains',
'startswith',
'istartswith',
'endswith',
'iendswith',
]:
with self.subTest(field_class=expected_field_class, lookup_expr=lookup_expr):
filter_instance = RutFilter(lookup_expr=lookup_expr)
self.assertIs(filter_instance.field_class, expected_field_class)

# TODO: Add tests.


Expand All @@ -34,4 +63,43 @@ class SiiFilterSetTest(unittest.TestCase):
def test_filter_for_lookup(self) -> None:
assert SiiFilterSet.filter_for_lookup()

def test_filter_for_lookup_types(self) -> None:
field = dj_model_fields.RutField()

expected_field_class = dj_form_fields.RutField
for lookup_type in [
'exact',
'iexact',
'gt',
'gte',
'lt',
'lte',
]:
with self.subTest(field_class=expected_field_class, lookup_type=lookup_type):
filter_class, params = SiiFilterSet.filter_for_lookup(field, lookup_type)
filter_instance = filter_class(**{'lookup_expr': lookup_type, **params})
self.assertIs(filter_instance.field_class, expected_field_class)

for lookup_type in [
'in',
]:
with self.subTest(field_class=expected_field_class, lookup_type=lookup_type):
filter_class, params = SiiFilterSet.filter_for_lookup(field, lookup_type)
filter_instance = filter_class(**{'lookup_expr': lookup_type, **params})
self.assertTrue(issubclass(filter_instance.field_class, expected_field_class))

expected_field_class = django_filters.CharFilter.field_class
for lookup_type in [
'contains',
'icontains',
'startswith',
'istartswith',
'endswith',
'iendswith',
]:
with self.subTest(field_class=expected_field_class, lookup_type=lookup_type):
filter_class, params = SiiFilterSet.filter_for_lookup(field, lookup_type)
filter_instance = filter_class(**{'lookup_expr': lookup_type, **params})
self.assertIs(filter_instance.field_class, expected_field_class)

# TODO: Add tests.
Loading