Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding tests and support for Django 4.2 - 5x and removing EOL versions of python and django #394

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
16 changes: 10 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ jobs:
fail-fast: false
max-parallel: 5
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10']
django-version: ['2.2', '3.1', '3.2', 'main']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
django-version: ['4.2', '5.0', '5.1', 'main']
exclude:
# No such tox envs:
- {python-version: '3.7', django-version: 'main'}
- {python-version: '3.10', django-version: '2.2'}
- {python-version: '3.10', django-version: '3.1'}
- {python-version: '3.10', django-version: '3.2'}
- {python-version: '3.8', django-version: 'main'}
- {python-version: '3.9', django-version: 'main'}
- {python-version: '3.8', django-version: '5.0'}
- {python-version: '3.9', django-version: '5.0'}
- {python-version: '3.8', django-version: '5.1'}
- {python-version: '3.9', django-version: '5.1'}
- {python-version: '3.13', django-version: '4.2'}
- {python-version: '3.13', django-version: '5.0'}

steps:
- uses: actions/checkout@v2
Expand Down
9 changes: 9 additions & 0 deletions CHANGES.rst
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we removing support for those Django versions? What's the reason? Is there something incompatible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is maybe more of a "philosophical" question.
I try to follow in all my projects the release cycle of Python and Django and migrate the code base always at least to the latest LTS version.
In general it becomes more and more challenging to support EOL versions because it requires patches for compatibility purpose and this effects the maintainability (like here: https://github.com/jazzband/django-newsletter/pull/394/files/d5300e560ad14dda0c625290236e00d7b98d86b7#diff-4d097d8e2ddb447f443dc2a92699225f61c2f7370d077988d93c83cc572d71f9)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in favor of dropping support for older versions that require these patches. In that case we need to remove the patches, too. But that will not take us up to 4.2. We can support more versions.

Remember that this is not "your" or "my" project. I also keep my projects always on the latest versions, but this library has been around for many years and there may be many projects using older Django versions. We don't want to force them to upgrade unnecessarily.

Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changes
=======

1.0(unreleased)
---------------
- Drop support for Django <4.2
- Drop support for Python <3.8
- Add support for Django 4.2, 5.0, 5.1
- Add support for Python 3.11, 3.12
- Fix Compatibility issues with Django 5.1


1.0b1 (unreleased)
------------------
- Add support for Django 3.1
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ soon as near-full coverage is reached.

Compatibility
=============
Currently, django-newsletter officially supports Django 2.2.x LTS, 3.1.x and 3.2.x and Python 3.7 through 3.10.
Currently, django-newsletter officially supports Django 4.2.x LTS, 5.0.x and 5.1.x and Python 3.8 through 3.12.

Requirements
============
Expand Down
6 changes: 3 additions & 3 deletions newsletter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pkg_resources import get_distribution, DistributionNotFound
from importlib.metadata import version, PackageNotFoundError

try:
__version__ = get_distribution("django-newsletter").version
except DistributionNotFound:
__version__ = version("django-newsletter")
except PackageNotFoundError:
# package is not installed
__version__ = None
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Generated by Django 5.0.6 on 2024-05-08 15:28

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("newsletter", "0008_longer_subscription_name"),
]

operations = [
migrations.AlterField(
model_name="article",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="attachment",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="message",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="newsletter",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="submission",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="subscription",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
]
10 changes: 7 additions & 3 deletions newsletter/models.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with LooseVersion? It's better than manually parsing the version number. Please leave like it was unless there is some good reason.

(Also it's better to just remove code instead of leaving it commented)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH this part I was already in the Django-5 branch I based my changes on and I did not checked that.
From what I see this is a patch in order to support Django versions <1.9.
It would depend here on the general decision if such old versions need to be supported or not.

Copy link
Contributor

@newearthmartin newearthmartin Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a good practice to leave commented lines. Please remove them.

And also there is no point in removing LooseVersion and then manually parsing the version. You can just revert that.

If we are dropping Django < 1.9 , then these lines should all be gone. Otherwise they should remain as they were before, they were more clear than the new ones.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import sys
import os
import time
from datetime import datetime
Expand All @@ -17,7 +18,7 @@
from django.utils.timezone import now
from django.urls import reverse

from distutils.version import LooseVersion
# from distutils.version import LooseVersion

from .fields import DynamicImageField
from .utils import (
Expand Down Expand Up @@ -740,8 +741,11 @@ def get_absolute_url(self):
def get_address(name, email):
# Converting name to ascii for compatibility with django < 1.9.
# Remove this when django 1.8 is no longer supported.
if LooseVersion(django.get_version()) < LooseVersion('1.9'):
name = name.encode('ascii', 'ignore').decode('ascii').strip()
# if LooseVersion(django.get_version()) < LooseVersion('1.9'):
# name = name.encode('ascii', 'ignore').decode('ascii').strip()
# Assuming django.get_version() returns a string like '1.8.18'
django_version = tuple(map(int, django.get_version().split('.')))
name = name.encode('ascii', 'ignore').decode('ascii').strip() if django_version < (1, 9) else name
if name:
return f'{name} <{email}>'
else:
Expand Down
13 changes: 7 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
),
long_description=README,
install_requires=[
"Django>=2.2.16",
"Django>=4.2",
"python-card-me<1.0",
"ldif3<3.2",
"chardet",
Expand All @@ -55,23 +55,24 @@
url='http://github.com/jazzband/django-newsletter/',
packages=find_packages(exclude=("tests", "test_project")),
include_package_data=True,
python_requires='>=3.7',
python_requires='>=3.8',
classifiers=[
'Development Status :: 6 - Mature',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Framework :: Django :: 4.2',
'Framework :: Django :: 5.0',
'Framework :: Django :: 5.2',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Affero General Public License v3',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3 :: Only',
'Topic :: Utilities'
],
Expand Down
2 changes: 1 addition & 1 deletion tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def test_message_with_attachment_admin(self):

change_url = reverse('admin:newsletter_message_change', args=(self.message_with_attachment.pk,))
response = self.client.get(change_url)
self.assertContains(response, '<h2>Attachments</h2>', html=True)
self.assertContains(response, '<a href="/tests/files/sample.txt">tests/files/sample.txt</a>', html=True)


class MessageAdminTests(AdminTestMixin, TestCase):
Expand Down
19 changes: 19 additions & 0 deletions tests/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.test import TestCase
from importlib.metadata import version, PackageNotFoundError
from newsletter import __version__

class TestNewsletterInit(TestCase):

def test_version(self):
try:
expected_version = version("django-newsletter")
except PackageNotFoundError:
expected_version = None
self.assertEqual(__version__, expected_version)

def test_not_existing_version(self):
try:
expected_version = version("django-not-existing-newsletter")
except PackageNotFoundError:
expected_version = None
self.assertIsNone(expected_version)
2 changes: 1 addition & 1 deletion tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_validate_email_nouser_noerror(self):
def test_validate_email_nouser_error(self):
""" Test validate_email_nouser where error is raised. """
User = get_user_model()
password = User.objects.make_random_password()
password = 'testpassword123'
user = User.objects.create_user(
'john', '[email protected]', password)
user.save()
Expand Down
6 changes: 3 additions & 3 deletions tests/test_web.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better use a TEST_PASSWORD variable if we are going to repeat it all over

Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ def test_subscribe_request_post_existinguser_email(self):
""" Post the subscription form without email shoud fail. """

User = get_user_model()
password = User.objects.make_random_password()
password = 'testpassword123'
user = User.objects.create_user(
'john', '[email protected]', password)
user.save()
Expand Down Expand Up @@ -781,7 +781,7 @@ def test_user_update(self):
"""

User = get_user_model()
password = User.objects.make_random_password()
password = 'testpassword123'
user = User.objects.create_user(
'john', '[email protected]', password)
user.save()
Expand Down Expand Up @@ -1055,7 +1055,7 @@ def test_update_request_post_existinguser_email(self):
""" Post the update form without email shoud fail. """

User = get_user_model()
password = User.objects.make_random_password()
password = 'testpassword123'
user = User.objects.create_user(
'john', '[email protected]', password)
user.save()
Expand Down
26 changes: 14 additions & 12 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
[tox]
envlist =
py{37,38,39}-dj{22,31,32}
py{38,39,310}-djmain
py{38,39,310,311,312}-dj{42}
py{310,311,312}-dj{50}
py{310,311,312,313}-dj{51}
py{310,311,312,313}-djmain

[testenv]
deps =
coverage
django-imperavi
# TinyMCE above 3 doesn't support Python 3.5 anymore.
# TODO: Remove version freeze when Django 2.2 LTS support is dropped, early 2022.
django-tinymce<3
django-tinymce
pytz
webtest
django-webtest
dj22: Django>=2.2,<3.0
dj31: Django>=3.1,<3.2
dj32: Django>=3.2,<3.3
dj42: Django>=4.2,<4.3
dj50: Django>=5.0,<5.1
dj51: Django>=5.1,<5.2
djmain: https://github.com/django/django/archive/main.tar.gz
usedevelop = True
ignore_outcome =
Expand All @@ -30,14 +30,16 @@ setenv =

[gh-actions]
python =
3.7: py37
3.8: py38
3.9: py39
3.10: py310
3.11: py311
3.12: py312
3.13: py313

[gh-actions:env]
DJANGO =
2.2: dj22
3.1: dj31
3.2: dj32
4.2: dj42
5.0: dj50
5.1: dj51
main: djmain
Loading