diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e8c3a9d..408dfdf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,10 +9,15 @@ jobs: continue-on-error: ${{ matrix.continue-on-error }} strategy: matrix: - python-version: [3.11, 3.10.x, 3.9] - django: [42, 32] + python-version: [3.12, 3.11, 3.10.x, 3.9] + django: [50, 42, 32] cms: [nocms, cms311, async] continue-on-error: [false] + exclude: + - django: 50 + cms: cms311 + - django: 50 + python-version: 3.9 steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} diff --git a/app_helper/utils.py b/app_helper/utils.py index 7252629..9764c66 100644 --- a/app_helper/utils.py +++ b/app_helper/utils.py @@ -4,7 +4,6 @@ import shutil import string import sys -from distutils.version import LooseVersion from tempfile import mkdtemp from unittest.mock import patch @@ -16,6 +15,11 @@ from . import HELPER_FILE +try: + from distutils.version import LooseVersion +except ImportError: # pragma: no cover + from setuptools import LooseVersion + try: import cms # NOQA @@ -61,12 +65,17 @@ def load_from_file(module_path): Borrowed from django-cms """ - from imp import PY_SOURCE, load_module - imported = None if module_path: - with open(module_path) as openfile: - imported = load_module("mod", openfile, module_path, ("imported", "r", PY_SOURCE)) + try: + from imp import PY_SOURCE, load_module + + with open(module_path) as openfile: + imported = load_module("mod", openfile, module_path, ("imported", "r", PY_SOURCE)) + except ImportError: # pragma: no cover + from importlib.machinery import SourceFileLoader + + imported = SourceFileLoader("mod", module_path).load_module() return imported diff --git a/changes/244.feature b/changes/244.feature new file mode 100644 index 0000000..941eb31 --- /dev/null +++ b/changes/244.feature @@ -0,0 +1 @@ +Prepare for Django 5.0 / Python 3.12 compatibility diff --git a/setup.cfg b/setup.cfg index dc487f2..e6e6869 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ description = Helper for django applications development long_description = file: README.rst, HISTORY.rst long_description_content_type = text/x-rst license = GPLv2+ -license_file = LICENSE +license_files = LICENSE classifiers = License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) Development Status :: 5 - Production/Stable diff --git a/tox.ini b/tox.ini index 2f92d25..ce33715 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ envlist = ruff pypi-description towncrier + py{312}-django{42,50}-{nocms,async} py{311}-django{42,41,40,32}-{cms311,nocms,async} py{310}-django{42,41,40,32}-{cms311,nocms,async} py{39}-django{32}-{cms311,nocms,async} @@ -20,8 +21,10 @@ deps= django40: django~=4.0.0 django41: django~=4.1.0 django42: django~=4.2.0 + django50: django~=5.0b1 cms311: https://github.com/yakky/django-cms/archive/release/3.11.x.zip cms311: djangocms-text-ckeditor>=5.0,<6.0 + py312: setuptools -r{toxinidir}/requirements-test.txt async: channels[daphne]~=4.0.0 passenv =