Skip to content

Commit 5bb16af

Browse files
authored
Support for Django 4 (#101)
* Support for Django 4 * Change pytest-django version * Change psycopg2 version * Change pytest version * Change tox version * Change pytest-cov version * Update circle ci jobs * Fix ci jobs * Update ci to postgres 12 * Allow Django 5.0 * Bump Django min version to 3.2 * Fix CI to account for >= 3.2 requirement * Fix quote * Remove python 3.12 for now due to distutils removal * Remove Django upper bound * Add back python3.6,3.7 wfs * Downgrade dj-database-url * Fix isnull issue from Django 4
1 parent a55986d commit 5bb16af

File tree

6 files changed

+161
-46
lines changed

6 files changed

+161
-46
lines changed

.circleci/config.yml

+80-27
Original file line numberDiff line numberDiff line change
@@ -3,61 +3,59 @@ jobs:
33
test-python36:
44
docker:
55
- image: python:3.6-alpine
6-
- image: postgres:11.0
6+
- image: postgres:12.0
77
environment:
88
POSTGRES_DB: 'localizedfields'
99
POSTGRES_USER: 'localizedfields'
1010
POSTGRES_PASSWORD: 'localizedfields'
1111
steps:
1212
- checkout
1313
- run:
14-
name: Install packages
15-
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
14+
name: Install packages
15+
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
1616

1717
- run:
18-
name: Install Python packages
19-
command: pip install --progress-bar off .[test]
18+
name: Install Python packages
19+
command: pip install --progress-bar off .[test]
2020

2121
- run:
22-
name: Run tests
23-
command: tox -e 'py36-dj{20,21,22,30,31}'
24-
environment:
25-
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
22+
name: Run tests
23+
command: tox -e 'py36-dj{20,21,22,30,31,32}'
24+
environment:
25+
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
2626

2727
- store_test_results:
28-
path: reports
29-
28+
path: reports
3029
test-python37:
3130
docker:
3231
- image: python:3.7-alpine
33-
- image: postgres:11.0
32+
- image: postgres:12.0
3433
environment:
3534
POSTGRES_DB: 'localizedfields'
3635
POSTGRES_USER: 'localizedfields'
3736
POSTGRES_PASSWORD: 'localizedfields'
3837
steps:
3938
- checkout
4039
- run:
41-
name: Install packages
42-
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
40+
name: Install packages
41+
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
4342

4443
- run:
45-
name: Install Python packages
46-
command: pip install --progress-bar off .[test]
44+
name: Install Python packages
45+
command: pip install --progress-bar off .[test]
4746

4847
- run:
49-
name: Run tests
50-
command: tox -e 'py37-dj{20,21,22,30,31}'
51-
environment:
52-
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
48+
name: Run tests
49+
command: tox -e 'py37-dj{20,21,22,30,31,32}'
50+
environment:
51+
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
5352

5453
- store_test_results:
55-
path: reports
56-
54+
path: reports
5755
test-python38:
5856
docker:
5957
- image: python:3.8-alpine
60-
- image: postgres:11.0
58+
- image: postgres:12.0
6159
environment:
6260
POSTGRES_DB: 'localizedfields'
6361
POSTGRES_USER: 'localizedfields'
@@ -74,7 +72,7 @@ jobs:
7472

7573
- run:
7674
name: Run tests
77-
command: tox -e 'py38-dj{20,21,22,30,31}'
75+
command: tox -e 'py38-dj{20,21,22,30,31,32,40,41,42}'
7876
environment:
7977
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
8078

@@ -84,7 +82,7 @@ jobs:
8482
test-python39:
8583
docker:
8684
- image: python:3.9-alpine
87-
- image: postgres:11.0
85+
- image: postgres:12.0
8886
environment:
8987
POSTGRES_DB: 'localizedfields'
9088
POSTGRES_USER: 'localizedfields'
@@ -101,16 +99,69 @@ jobs:
10199

102100
- run:
103101
name: Run tests
104-
command: tox -e 'py39-dj{21,22,30,31}'
102+
command: tox -e 'py39-dj{30,31,32,40,41,42}'
105103
environment:
106104
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
107105

108106
- store_test_results:
109107
path: reports
110108

109+
test-python310:
110+
docker:
111+
- image: python:3.10-alpine
112+
- image: postgres:12.0
113+
environment:
114+
POSTGRES_DB: 'localizedfields'
115+
POSTGRES_USER: 'localizedfields'
116+
POSTGRES_PASSWORD: 'localizedfields'
117+
steps:
118+
- checkout
119+
- run:
120+
name: Install packages
121+
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
122+
123+
- run:
124+
name: Install Python packages
125+
command: pip install --progress-bar off .[test]
126+
127+
- run:
128+
name: Run tests
129+
command: tox -e 'py310-dj{32,40,41,42,50}'
130+
environment:
131+
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
132+
133+
- store_test_results:
134+
path: reports
135+
test-python311:
136+
docker:
137+
- image: python:3.11-alpine
138+
- image: postgres:12.0
139+
environment:
140+
POSTGRES_DB: 'localizedfields'
141+
POSTGRES_USER: 'localizedfields'
142+
POSTGRES_PASSWORD: 'localizedfields'
143+
steps:
144+
- checkout
145+
- run:
146+
name: Install packages
147+
command: apk add postgresql-libs gcc musl-dev postgresql-dev git
148+
149+
- run:
150+
name: Install Python packages
151+
command: pip install --progress-bar off .[test]
152+
153+
- run:
154+
name: Run tests
155+
command: tox -e 'py311-dj{42,50}'
156+
environment:
157+
DATABASE_URL: 'postgres://localizedfields:localizedfields@localhost:5432/localizedfields'
158+
159+
- store_test_results:
160+
path: reports
161+
111162
analysis:
112163
docker:
113-
- image: python:3.7-alpine
164+
- image: python:3.8-alpine
114165
steps:
115166
- checkout
116167
- run:
@@ -134,4 +185,6 @@ workflows:
134185
- test-python37
135186
- test-python38
136187
- test-python39
188+
- test-python310
189+
- test-python311
137190
- analysis

README.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
| | | |
2-
|--------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1+
| | | |
2+
|--------------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
33
| :white_check_mark: | **Tests** | [![CircleCI](https://circleci.com/gh/SectorLabs/django-localized-fields/tree/master.svg?style=svg)](https://circleci.com/gh/SectorLabs/django-localized-fields/tree/master) |
4-
| :memo: | **License** | [![License](https://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) |
5-
| :package: | **PyPi** | [![PyPi](https://badge.fury.io/py/django-localized-fields.svg)](https://pypi.python.org/pypi/django-localized-fields) |
6-
| <img src="https://cdn.iconscout.com/icon/free/png-256/django-1-282754.png" width="22px" height="22px" align="center" /> | **Django Versions** | 2.0, 2.1, 2.2, 3.0, 3.1, 3.2 |
7-
| <img src="http://www.iconarchive.com/download/i73027/cornmanthe3rd/plex/Other-python.ico" width="22px" height="22px" align="center" /> | **Python Versions** | 3.6, 3.7, 3.8, 3.9 |
8-
| :book: | **Documentation** | [Read The Docs](https://django-localized-fields.readthedocs.io) |
9-
| :warning: | **Upgrade** | [Upgrade fom v5.x](https://django-localized-fields.readthedocs.io/en/latest/releases.html#v6-0)
10-
| :checkered_flag: | **Installation** | [Installation Guide](https://django-localized-fields.readthedocs.io/en/latest/installation.html) |
4+
| :memo: | **License** | [![License](https://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) |
5+
| :package: | **PyPi** | [![PyPi](https://badge.fury.io/py/django-localized-fields.svg)](https://pypi.python.org/pypi/django-localized-fields) |
6+
| <img src="https://cdn.iconscout.com/icon/free/png-256/django-1-282754.png" width="22px" height="22px" align="center" /> | **Django Versions** | 2.0, 2.1, 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, 5.0 |
7+
| <img src="http://www.iconarchive.com/download/i73027/cornmanthe3rd/plex/Other-python.ico" width="22px" height="22px" align="center" /> | **Python Versions** | 3.6, 3.7, 3.8, 3.9, 3.10, 3.11 |
8+
| :book: | **Documentation** | [Read The Docs](https://django-localized-fields.readthedocs.io) |
9+
| :warning: | **Upgrade** | [Upgrade fom v5.x](https://django-localized-fields.readthedocs.io/en/latest/releases.html#v6-0)
10+
| :checkered_flag: | **Installation** | [Installation Guide](https://django-localized-fields.readthedocs.io/en/latest/installation.html) |
1111

1212
`django-localized-fields` is an implementation of a field class for Django models that allows the field's value to be set in multiple languages. It does this by utilizing the ``hstore`` type (PostgreSQL specific), which is available as `models.HStoreField` since Django 1.10.
1313

@@ -20,7 +20,7 @@
2020
## Working with the code
2121
### Prerequisites
2222

23-
* PostgreSQL 10 or newer.
23+
* PostgreSQL 12 or newer.
2424
* Django 2.0 or newer.
2525
* Python 3.6 or newer.
2626

localized_fields/lookups.py

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ def process_lhs(self, qn, connection):
4343
return super().process_lhs(qn, connection)
4444

4545
def get_prep_lookup(self):
46+
# Django 4.0 removed the ability for isnull fields to be something other than a bool
47+
# We should NOT convert them to strings
48+
if isinstance(self.rhs, bool):
49+
return self.rhs
4650
return str(self.rhs)
4751

4852

setup.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def run(self):
3636

3737
setup(
3838
name="django-localized-fields",
39-
version="6.8b3",
39+
version="6.8b4",
4040
packages=find_packages(exclude=["tests"]),
4141
include_package_data=True,
4242
license="MIT License",
@@ -67,6 +67,8 @@ def run(self):
6767
"Programming Language :: Python :: 3.7",
6868
"Programming Language :: Python :: 3.8",
6969
"Programming Language :: Python :: 3.9",
70+
"Programming Language :: Python :: 3.10",
71+
"Programming Language :: Python :: 3.11",
7072
"Topic :: Internet :: WWW/HTTP",
7173
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
7274
],
@@ -80,14 +82,14 @@ def run(self):
8082
':python_version <= "3.6"': ["dataclasses"],
8183
"docs": ["Sphinx==2.2.0", "sphinx-rtd-theme==0.4.3"],
8284
"test": [
83-
"tox==3.14.3",
84-
"pytest==5.3.2",
85-
"pytest-django==3.7.0",
86-
"pytest-cov==2.8.1",
85+
"tox==3.28.0",
86+
"pytest==7.0.1",
87+
"pytest-django==4.5.2",
88+
"pytest-cov==2.12.1",
8789
"dj-database-url==0.5.0",
88-
"django-autoslug==1.9.6",
89-
"django-bleach==0.6.1",
90-
"psycopg2==2.8.4",
90+
"django-autoslug==1.9.9",
91+
"django-bleach==0.9.0",
92+
"psycopg2==2.9.8",
9193
],
9294
"analysis": [
9395
"black==22.3.0",

tests/test_isnull.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import django
2+
import pytest
3+
4+
from django.test import TestCase
5+
6+
from localized_fields.fields import LocalizedField
7+
from localized_fields.value import LocalizedValue
8+
9+
from .fake_model import get_fake_model
10+
11+
12+
class LocalizedIsNullLookupsTestCase(TestCase):
13+
"""Tests whether ref lookups properly work with."""
14+
15+
TestModel1 = None
16+
17+
@classmethod
18+
def setUpClass(cls):
19+
"""Creates the test model in the database."""
20+
super(LocalizedIsNullLookupsTestCase, cls).setUpClass()
21+
cls.TestModel = get_fake_model(
22+
{"text": LocalizedField(null=True, required=[])}
23+
)
24+
cls.TestModel.objects.create(
25+
text=LocalizedValue(dict(en="text_en", ro="text_ro", nl="text_nl"))
26+
)
27+
cls.TestModel.objects.create(
28+
text=None,
29+
)
30+
31+
def test_isnull_lookup_valid_values(self):
32+
"""Test whether isnull properly works with valid values."""
33+
assert self.TestModel.objects.filter(text__isnull=True).exists()
34+
assert self.TestModel.objects.filter(text__isnull=False).exists()
35+
36+
def test_isnull_lookup_null(self):
37+
"""Test whether isnull crashes with None as value."""
38+
39+
with pytest.raises(ValueError):
40+
assert self.TestModel.objects.filter(text__isnull=None).exists()
41+
42+
def test_isnull_lookup_string(self):
43+
"""Test whether isnull properly works with string values on the
44+
corresponding Django version."""
45+
if django.VERSION < (4, 0):
46+
assert self.TestModel.objects.filter(text__isnull="True").exists()
47+
else:
48+
with pytest.raises(ValueError):
49+
assert self.TestModel.objects.filter(
50+
text__isnull="True"
51+
).exists()

tox.ini

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py36-dj{20,21,22,30,31}, py37-dj{20,21,22,30,31}, py38-dj{20,21,22,30,31}, py39-dj{21,22,30,31}
2+
envlist = py36-dj{20,21,22,30,31,32}, py37-dj{20,21,22,30,31,32}, py38-dj{20,21,22,30,31,32,40,41,42}, py39-dj{30,31,32,40,41,42}, py310-dj{32,40,41,42,50}, py311-dj{42,50}
33

44
[testenv]
55
deps =
@@ -8,6 +8,11 @@ deps =
88
dj22: Django>=2.2,<2.3
99
dj30: Django>=3.0,<3.0.2
1010
dj31: Django>=3.1,<3.2
11+
dj32: Django>=3.2,<4.0
12+
dj40: Django>=4.0,<4.1
13+
dj41: Django>=4.1,<4.2
14+
dj42: Django>=4.2,<5.0
15+
dj50: Django>=5.0,<5.1
1116
.[test]
1217
setenv =
1318
DJANGO_SETTINGS_MODULE=settings

0 commit comments

Comments
 (0)