diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..0310222 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,76 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '37 3 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: 'ubuntu-latest' + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4cb8d8c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: Tox tests + +on: [push, pull_request] + +jobs: + test: + if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.continue-on-error }} + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10"] + django: [32, 42] + continue-on-error: [true] + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache pip + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ format('test-py{0}-django{1}', matrix.python-version, matrix.django) }} + restore-keys: | + ${{ runner.os }}-pip-${{ format('test-py{0}-django{1}', matrix.python-version, matrix.django) }} + - name: Cache tox + uses: actions/cache@v3 + with: + path: .tox + key: ${{ runner.os }}-tox-${{ format('test-{{py{0}-django{1}}}', matrix.python-version, matrix.django) }}-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-tox-${{ format('test-{{py{0}-django{1}}}', matrix.python-version, matrix.django) }}- + - name: Install dependencies + run: | + sudo apt-get install gettext + python -m pip install --upgrade pip setuptools tox>4 tox-docker + - name: Test with tox + env: + TOX_ENV: ${{ format('test-py{0}-django{1}', matrix.python-version, matrix.django) }} + run: | + tox -e$TOX_ENV diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f745dd5..834aaf0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog ========= +Unreleased +================== +* Add compatibility with Django 4.2 +* Dropped support for Django < 3.1 +* Dropped support for python < 3.8 + 0.7.2 (unreleased) ================== diff --git a/aldryn_config.py b/aldryn_config.py index eef99b1..f3616d6 100644 --- a/aldryn_config.py +++ b/aldryn_config.py @@ -126,8 +126,7 @@ def single_process_settings(self, env, settings): MIDDLEWARE_CLASSES.insert( MIDDLEWARE_CLASSES.index( "cms.middleware.utils.ApphookReloadMiddleware" - ) - + 1, + ) + 1, "django_multisite_plus.middlewares.CMSMultiSiteMiddleware", ) diff --git a/setup.cfg b/setup.cfg index dd0dbf1..29aef6e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,8 +18,6 @@ classifiers = Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -34,12 +32,12 @@ include_package_data = True package_dir = = src packages = find: -python_requires = >=3.6 +python_requires = >=3.8 setup_requires = setuptools_scm[toml] install_requires = - django>=2 - django-multisite>=1.4.0 - djangocms-multisite>=0.2.2 # Note: this is divio/djangocms-multisite, not nephila/djangocms-multisite + django>=3.2,<5 + django-multisite @ https://github.com/FidelityInternational/django-multisite/tarball/feat/django-42-compat#egg=django-multisite + djangocms-multisite @ https://github.com/FidelityInternational/djangocms-multisite/tarball/feat/django-42-compat#egg=djangocms-multisite aldryn-django aldryn_addons click @@ -52,3 +50,26 @@ console_scripts = [options.packages.find] where = src + +[flake8] +max-line-length = 120 +exclude = + .git, + __pycache__, + **/migrations/, + build/, + .tox/, + +[isort] +line_length = 79 +multi_line_output = 3 +lines_after_imports = 2 +combine_as_imports = true +include_trailing_comma = true +balanced_wrapping = true +skip = manage.py, migrations, .tox +extra_standard_library = mock +known_django = django +known_cms = cms, menus +known_first_party = djangocms_version_locking +sections = FUTURE, STDLIB, DJANGO, CMS, THIRDPARTY, FIRSTPARTY, LOCALFOLDER diff --git a/setup.py b/setup.py index d271144..31536c5 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ from setuptools import find_packages, setup + setup( name="django-multisite-plus", version="0.7.2", diff --git a/src/django_multisite_plus/admin.py b/src/django_multisite_plus/admin.py index a2e84be..f3d43c4 100644 --- a/src/django_multisite_plus/admin.py +++ b/src/django_multisite_plus/admin.py @@ -39,7 +39,7 @@ def has_add_permission(self, *args, **kwargs): def get_readonly_fields(self, request, obj=None): if not settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: - return super(SiteInline, self).get_readonly_fields(request, obj) + return super().get_readonly_fields(request, obj) return ["slug", "real_domain", "is_enabled", "extra_uwsgi_ini"] @@ -47,16 +47,16 @@ class AliasInline(MultisiteAliasInline): def has_delete_permission(self, *args, **kwargs): if settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: return False - return super(AliasInline, self).has_delete_permission(*args, **kwargs) + return super().has_delete_permission(*args, **kwargs) def has_add_permission(self, *args, **kwargs): if settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: return False - return super(AliasInline, self).has_add_permission(*args, **kwargs) + return super().has_add_permission(*args, **kwargs) def get_readonly_fields(self, request, obj=None): if not settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: - return super(AliasInline, self).get_readonly_fields(request, obj) + return super().get_readonly_fields(request, obj) return ["domain", "site", "is_canonical", "redirect_to_canonical"] @@ -81,41 +81,44 @@ class SiteAdmin(DjangoSiteAdmin): def has_delete_permission(self, *args, **kwargs): if settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: return False - return super(SiteAdmin, self).has_delete_permission(*args, **kwargs) + return super().has_delete_permission(*args, **kwargs) def has_add_permission(self, *args, **kwargs): if settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: return False - return super(SiteAdmin, self).has_add_permission(*args, **kwargs) + return super().has_add_permission(*args, **kwargs) def get_readonly_fields(self, request, obj=None): if not settings.DJANGO_MULTISITE_PLUS_REWRITE_DOMAINS: - return super(SiteAdmin, self).get_readonly_fields(request, obj) + return super().get_readonly_fields(request, obj) return ["domain", "linked_url", "name"] def get_queryset(self, request): - qs = super(SiteAdmin, self).get_queryset(request) + qs = super().get_queryset(request) return qs.prefetch_related("multisiteplus_site") + @admin.display( + description=_("real domain"), + ordering="multisiteplus_site__real_domain", + ) def real_domain(self, obj): return obj.multisiteplus_site.real_domain - real_domain.short_description = _("real domain") - real_domain.admin_order_field = "multisiteplus_site__real_domain" - + @admin.display( + description=_("slug"), + ordering="multisiteplus_site__slug", + ) def slug(self, obj): return obj.multisiteplus_site.slug - slug.short_description = _("slug") - slug.admin_order_field = "multisiteplus_site__slug" - + @admin.display( + description=_("domain"), + ordering="domain", + ) def domain_html(self, obj): return "{}".format(obj.domain) - domain_html.short_description = _("domain") - domain_html.admin_order_field = "domain" - domain_html.allow_tags = True - + @admin.action(description=_("url")) def linked_url(self, obj, text=_("open")): return format_html( '{}', @@ -123,16 +126,14 @@ def linked_url(self, obj, text=_("open")): text, ) - linked_url.short_description = _("url") - linked_url.allow_tags = True - + @admin.display( + description=_("is enabled"), + boolean=True, + ordering="multisiteplus_site__is_enabled", + ) def is_enabled(self, obj): return obj.multisiteplus_site.is_enabled - is_enabled.short_description = _("is enabled") - is_enabled.admin_order_field = "multisiteplus_site__is_enabled" - is_enabled.boolean = True - def update_site_action(self, request, queryset): for obj in queryset: try: diff --git a/src/django_multisite_plus/cms_urls.py b/src/django_multisite_plus/cms_urls.py index d24ce43..2888c5e 100644 --- a/src/django_multisite_plus/cms_urls.py +++ b/src/django_multisite_plus/cms_urls.py @@ -1,8 +1,6 @@ -from django.conf.urls import include - -from djangocms_multisite.urlresolvers import cms_multisite_url +from django.urls import include, re_path urlpatterns = [ - cms_multisite_url(r"^", include("cms.urls")), + re_path(r"^", include("cms.urls")), ] diff --git a/src/django_multisite_plus/management/commands/multisite_plus_populate_sites.py b/src/django_multisite_plus/management/commands/multisite_plus_populate_sites.py index ecb94c2..d70ba20 100644 --- a/src/django_multisite_plus/management/commands/multisite_plus_populate_sites.py +++ b/src/django_multisite_plus/management/commands/multisite_plus_populate_sites.py @@ -1,4 +1,4 @@ -from django.core.management.base import BaseCommand, CommandError +from django.core.management.base import BaseCommand from django_multisite_plus.models import Site diff --git a/src/django_multisite_plus/management/commands/multisite_plus_rewrite_domains.py b/src/django_multisite_plus/management/commands/multisite_plus_rewrite_domains.py index df7ec8d..0ec6dbf 100644 --- a/src/django_multisite_plus/management/commands/multisite_plus_rewrite_domains.py +++ b/src/django_multisite_plus/management/commands/multisite_plus_rewrite_domains.py @@ -1,4 +1,4 @@ -from django.core.management.base import BaseCommand, CommandError +from django.core.management.base import BaseCommand from multisite.models import Alias diff --git a/src/django_multisite_plus/middlewares.py b/src/django_multisite_plus/middlewares.py index 9e3b9da..d2f8356 100644 --- a/src/django_multisite_plus/middlewares.py +++ b/src/django_multisite_plus/middlewares.py @@ -10,7 +10,7 @@ class CMSMultiSiteMiddleware(middleware.CMSMultiSiteMiddleware): def process_request(self, request): - super(CMSMultiSiteMiddleware, self).process_request(request) + super().process_request(request) if "django_multisite_plus.cms_urls" in sys.modules: reload(sys.modules["django_multisite_plus.cms_urls"]) diff --git a/src/django_multisite_plus/migrations/0001_initial.py b/src/django_multisite_plus/migrations/0001_initial.py index 0e44fdb..a46f130 100644 --- a/src/django_multisite_plus/migrations/0001_initial.py +++ b/src/django_multisite_plus/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - import django.contrib.sites.models from django.db import migrations, models diff --git a/src/django_multisite_plus/migrations/0002_auto_20180125_1157.py b/src/django_multisite_plus/migrations/0002_auto_20180125_1157.py index 9be83f7..cee0481 100644 --- a/src/django_multisite_plus/migrations/0002_auto_20180125_1157.py +++ b/src/django_multisite_plus/migrations/0002_auto_20180125_1157.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.8 on 2018-01-25 11:57 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/django_multisite_plus/models.py b/src/django_multisite_plus/models.py index 2f5169b..6b0c15c 100644 --- a/src/django_multisite_plus/models.py +++ b/src/django_multisite_plus/models.py @@ -209,7 +209,7 @@ def update_site(self, use_real_domain=None): site.save() def save(self, **kwargs): - super(Site, self).save(**kwargs) + super().save(**kwargs) self.update_site() diff --git a/tests/testproject/settings.py b/tests/testproject/settings.py index 6bac7e9..0549705 100644 --- a/tests/testproject/settings.py +++ b/tests/testproject/settings.py @@ -19,7 +19,7 @@ DATABASES = { "default": { - "ENGINE": "django.db.backends.postgresql_psycopg2", + "ENGINE": "django.db.backends.postgresql", "NAME": "postgres", "USER": "postgres", "HOST": os.environ["POSTGRES_HOST"], diff --git a/tox.ini b/tox.ini index 931b8b4..76ba5a3 100644 --- a/tox.ini +++ b/tox.ini @@ -2,11 +2,10 @@ # Having the .tox directory in the project directory slows down the # `pip install -e .` step required by `usedevelop = true` considerably. # By moving it out of the way (~500MB), we trim test execution time by > 80%. -toxworkdir = {homedir}/.toxenvs/django-multisite-plus +toxworkdir = /tmp/.toxenvs/django-multisite-plus envlist = clean, - test-py{36,37,38,39,310}-django{22,32}, - test-py{38,39,310}-django{40}, + test-py{38,39,310}-django{32,42}, lint, manifest, coverage @@ -15,15 +14,18 @@ isolated_build = true [testenv] depends = test: clean docker = test: postgres +constrain_package_deps = true deps = test: pytest test: pytest-cov test: pytest-django - django22: django>=2.2,<2.3 django32: django>=3.2,<3.3 - django40: django<=4.0,<4.1 -# django41: django>=4.1,<4.2 -# django42: django>=4.2,<4.3 + django42: django>=4.2,<4.3 +basepython = + py38: python3.8 + py39: python3.9 + py310: python3.10 + commands = test: pytest ./tests {posargs} setenv = @@ -41,9 +43,9 @@ deps = isort flake8 commands = - isort --check-only . + isort --check-only src/django_multisite_plus black --check src/django_multisite_plus - flake8 --ignore=E501,E722,E402,W503,E203 . + flake8 --ignore=E501,E722,E402,W503,E203 src/django_multisite_plus skip_install = true [testenv:clean] @@ -52,7 +54,7 @@ commands = coverage erase skip_install = true [testenv:coverage] -depends = test-py{36,37,38,39,310}-django{22,32,40},clean +depends = test-py{38,39,310}-django{32,42},clean deps = coverage[toml] commands = coverage combine .artifacts/ @@ -73,4 +75,4 @@ healthcheck_cmd = psql \ healthcheck_timeout = 1 healthcheck_retries = 30 healthcheck_interval = 1 -healthcheck_start_period = 1 +healthcheck_start_period = 1 \ No newline at end of file