Repository: mbourqui/django-constrainedfilefield (language: python)

Issue:
Support for Django 4.x
Hi there,

In the process of upgrading our Django version to 4.0, we encountered the following incompatibility:
`cannot import name 'ugettext_lazy' from 'django.utils.translation'`

We were able to proceed by replacing the imports:
`from django.utils.translation import ugettext_lazy as _`
by
`from django.utils.translation import gettext_lazy as _`

in both fields/file.py and fields/image.py

Would you be able to apply these changes to enable other users to upgrade to Django 4?

Thanks in advance!


Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index b6a4d54..32cc951 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,31 +4,29 @@ python:
   - 3.6
   - 3.7
   - 3.8
+  - 3.9
 env:
-  - DJANGO_VERSION=1.11.29
-  - DJANGO_VERSION=2.1.15
-  - DJANGO_VERSION=2.2.12
+  - DJANGO_VERSION=2.2.28
+  - DJANGO_VERSION=3.2.15
+  - DJANGO_VERSION=4.0.7
 # https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django
 matrix:
   exclude:
-    - env: DJANGO_VERSION=1.11.29
-      python: 3.8
-    - env: DJANGO_VERSION=2.1.15
-      python: 2.7
-    - env: DJANGO_VERSION=2.1.15
-      python: 3.4
-    - env: DJANGO_VERSION=2.1.15
-      python: 3.8
-    - env: DJANGO_VERSION=2.2.12
-      python: 2.7
-    - env: DJANGO_VERSION=2.2.12
-      python: 3.4
+    - env: DJANGO_VERSION=3.2.15
+      python: 3.5
+    - env: DJANGO_VERSION=4.0.7
+      python: 3.5
+    - env: DJANGO_VERSION=4.0.7
+      python: 3.6
+    - env: DJANGO_VERSION=4.0.7
+      python: 3.7
 addons:
   apt_packages:
     - pandoc
 before_install:
   - ./pypi_packager.sh
 install:
+  - if [[ $TRAVIS_PYTHON_VERSION == 3.7 ]]; then pip install -U importlib_metadata; fi
   - pip install -q django==$DJANGO_VERSION
   - pip install -e .[coverage]
   - pip install -q coveralls
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b8d0e5..49e5aa4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## 5.0.0 (02.09.2022)
+### Added
+- Support of Django 4.0
+
+### Removed
+- Support of Django 1.11
+- Support of Django 2.1
+
 ## 4.0.0 (23.05.2020)
 ### Added
 - Support of Django 2.1
diff --git a/README.md b/README.md
index 6088757..3aaf91e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-[![Python](https://img.shields.io/badge/Python-3.5,3.6,3.7,3.8-blue.svg?style=flat-square)](/)
-[![Django](https://img.shields.io/badge/Django-1.11,2.1,2.2-blue.svg?style=flat-square)](/)
+[![Python](https://img.shields.io/badge/Python-3.5,3.6,3.7,3.8,3.9-blue.svg?style=flat-square)](/)
+[![Django](https://img.shields.io/badge/Django-2.2,3.2,4.0-blue.svg?style=flat-square)](/)
 [![License](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg?style=flat-square)](/LICENSE)
 [![PyPIv](https://img.shields.io/pypi/v/django-constrainedfilefield.svg?style=flat-square)](https://pypi.org/project/django-constrainedfilefield)
 [![PyPIs](https://img.shields.io/pypi/status/django-constrainedfilefield.svg)](https://pypi.org/project/django-constrainedfilefield)
@@ -23,7 +23,7 @@ form field.
 
 ## Requirements
 * [Python][] >= 3.5
-* [Django]>= 1.11.29
+* [Django]>= 2.2.28
 * `python-magic` >= 0.4.2 *iff* you want to check the file type
 
 ## Installation
diff --git a/constrainedfilefield/__init__.py b/constrainedfilefield/__init__.py
index ec5434c..b4d4a97 100644
--- a/constrainedfilefield/__init__.py
+++ b/constrainedfilefield/__init__.py
@@ -3,7 +3,7 @@
 
 __license__ = "BSD-3-Clause"
 __author__ = "Marc Bourqui"
-__version__ = "4.0.0"
+__version__ = "5.0.0"
 __version_info__ = tuple(
     [
         int(num) if num.isdigit() else num
diff --git a/constrainedfilefield/fields/file.py b/constrainedfilefield/fields/file.py
index 1e50480..7efed81 100644
--- a/constrainedfilefield/fields/file.py
+++ b/constrainedfilefield/fields/file.py
@@ -7,12 +7,12 @@
 from django.conf import settings
 from django.db import models
 from django.template.defaultfilters import filesizeformat
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 
 class ConstrainedFileField(models.FileField):
     """
-    A FielField with additional constraints. Namely, the file size and type can be restricted. If
+    A FileField with additional constraints. Namely, the file size and type can be restricted. If
     using the types, the magic library is required. Setting neither a file size nor type behaves
     like a regular FileField.
 
diff --git a/constrainedfilefield/fields/image.py b/constrainedfilefield/fields/image.py
index cc381f1..f62f0c7 100644
--- a/constrainedfilefield/fields/image.py
+++ b/constrainedfilefield/fields/image.py
@@ -7,7 +7,7 @@
 from django.conf import settings
 from django.db import models
 from django.template.defaultfilters import filesizeformat
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
 
 
 class ConstrainedImageField(models.ImageField):


Test patch:
diff --git a/constrainedfilefield/tests/models.py b/constrainedfilefield/tests/models.py
index 264f06b..2899dcc 100644
--- a/constrainedfilefield/tests/models.py
+++ b/constrainedfilefield/tests/models.py
@@ -28,7 +28,10 @@ class TestDocModel(models.Model):
 
 
 class TestImageModel(models.Model):
-    the_image = ConstrainedImageField(null=True, blank=True, upload_to="testfile",)
+    the_image = ConstrainedImageField(
+        null=True,
+        blank=True,
+        upload_to="testfile",)
     the_image_small = ConstrainedImageField(
         null=True,
         blank=True,
diff --git a/constrainedfilefield/tests/sample_files/unsupported_image.jpg b/constrainedfilefield/tests/sample_files/unsupported_image.jpg
new file mode 100644
index 0000000..e7bcabe
Binary files /dev/null and b/constrainedfilefield/tests/sample_files/unsupported_image.jpg differ
diff --git a/constrainedfilefield/tests/tests/backend.py b/constrainedfilefield/tests/tests/backend.py
index 9408c72..a58cc56 100644
--- a/constrainedfilefield/tests/tests/backend.py
+++ b/constrainedfilefield/tests/tests/backend.py
@@ -224,6 +224,24 @@ def test_form_invalid_filetype(self):
             u"Allowed types are ['image/png'].",
         )
 
+    def test_form_invalid_image_filetype(self):
+        files = {
+            "the_image_small": self._create_simple_uploaded_file(
+                orig_filename="unsupported_image.jpg",
+                dest_filename="the_file.jpg",
+                content_type="image/jpeg",
+            ),
+        }
+        form = TestImageModelForm(data={}, files=files)
+        self.assertFalse(form.is_valid())
+        self.assertEqual(len(form.errors), 1)
+        self.assertEqual(len(form.errors["the_image_small"]), 1)
+        self.assertEqual(
+            form.errors["the_image_small"][0],
+            u"Unsupported file type: image/jpeg. "
+            u"Allowed types are ['image/png']."
+        )
+
     def test_form_invalid_filetype_and_size(self):
         form = self._create_bound_test_model_form(
             form_class=TestModelForm,
diff --git a/constrainedfilefield/tests/urls.py b/constrainedfilefield/tests/urls.py
index 4a445cb..7c5cee6 100644
--- a/constrainedfilefield/tests/urls.py
+++ b/constrainedfilefield/tests/urls.py
@@ -1,7 +1,7 @@
 # -*- coding:utf-8 -*-
-from django.conf.urls import url
+from django.urls import re_path
 from constrainedfilefield.tests import views
 
 urlpatterns = [
-    url(r"^nomodel/$", views.nomodel_form, name="nomodel"),
+    re_path(r"^nomodel/$", views.nomodel_form, name="nomodel"),
 ]