From 2c0e0c79fb89bb9d39ddccc0c7febac704893fec Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sat, 27 Jan 2024 19:11:37 +0000 Subject: [PATCH 1/7] ci: Add pre-commit config with ruff formatter and linter --- .pre-commit-config.yml | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .pre-commit-config.yml diff --git a/.pre-commit-config.yml b/.pre-commit-config.yml new file mode 100644 index 00000000000..7d2ca86f4f6 --- /dev/null +++ b/.pre-commit-config.yml @@ -0,0 +1,46 @@ +ci: + autofix_commit_msg: | + ci: auto fixes from pre-commit hooks + + for more information, see https://pre-commit.ci + autofix_prs: false + autoupdate_commit_msg: 'ci: pre-commit autoupdate' + autoupdate_schedule: monthly + +repos: + - repo: https://github.com/asottile/pyupgrade + rev: v2.31.0 + hooks: + - id: pyupgrade + args: ["--py39-plus"] + + - repo: https://github.com/adamchainz/django-upgrade + rev: '1.4.0' + hooks: + - id: django-upgrade + args: [--target-version, "3.2"] + + - repo: https://github.com/asottile/yesqa + rev: v1.3.0 + hooks: + - id: yesqa + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: check-merge-conflict + - id: debug-statements + - id: mixed-line-ending + - id: trailing-whitespace + + - repo: https://github.com/codespell-project/codespell + rev: v2.1.0 + hooks: + - id: codespell + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.14 + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format From e2b2a76747254f187cc01cd4102e0bb14daf39d8 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sat, 27 Jan 2024 22:57:36 +0000 Subject: [PATCH 2/7] ci: Update ruff rules --- .github/workflows/linters.yml | 26 ++++++++----------- pyproject.toml | 48 +++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 5360c6f2372..51a036d215d 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -1,28 +1,22 @@ name: django CMS linters.yml -on: [push, pull_request] +on: + push: + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - jobs: ruff: name: ruff runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - cache: 'pip' - - run: | - python -m pip install --upgrade pip - pip install ruff - - name: Run Ruff - run: | - ruff cms - ruff menus + - uses: actions/checkout@v4 + + - run: python -Im pip install --user ruff + + - name: Run ruff + working-directory: ./src + run: ruff --output-format=github cms menus diff --git a/pyproject.toml b/pyproject.toml index 64bdc3d3ff5..58c167350fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,19 +1,39 @@ [tool.ruff] -exclude = [ - ".env", - ".venv", - "**/migrations/**", +# https://beta.ruff.rs/docs/configuration/ +line-length = 119 +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "C", # flake8-comprehensions + "B", # flake8-bugbear + "PLE", # pylint error + "PLR", # pylint refactor + "PLW", # pylint warning + "UP", # pyupgrade +] + +extend-exclude = [ + ".ruff_cache", + ".env", + ".venv", + "**migrations/**", ] + ignore = [ - "E501", # line too long - "F403", # 'from module import *' used; unable to detect undefined names - "E701", # multiple statements on one line (colon) - "F401", # module imported but unused +# "B006", # Do not use mutable data structures for argument defaults +# "PLR0913", # Too many arguments to function call, ] -line-length = 119 -select = [ - "I", - "E", - "F", - "W", + +[tool.ruff.per-file-ignores] +"__init__.py" = [ + "F401" # unused-import ] + +[tool.ruff.isort] +combine-as-imports = true + +[tool.ruff.pyupgrade] +# Preserve types, even if a file imports `from __future__ import annotations`. +keep-runtime-typing = true From 28d3c9a4ff0634e7d53c7aef5183b895ef26df0d Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sun, 28 Jan 2024 13:17:53 +0000 Subject: [PATCH 3/7] ci: Update ruff rules --- .editorconfig | 3 +++ pyproject.toml | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index a8e5db7ce9a..2f249b0858c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,5 +26,8 @@ quote_type = single [*.rst] max_line_length = 80 +[*.toml] +indent_size = 2 + [*.yml] indent_size = 2 diff --git a/pyproject.toml b/pyproject.toml index 58c167350fd..b054adabd5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,15 +21,53 @@ extend-exclude = [ "**migrations/**", ] -ignore = [ -# "B006", # Do not use mutable data structures for argument defaults -# "PLR0913", # Too many arguments to function call, +extend-ignore = [ + "C901", # Too complex + "PLR0911", # Too many return statements + "PLR0912", # Too many branches + "PLR0913", # Too many arguments to function call + "PLR0915", # Too many statements + + # TODO fix separately + "B006", + "B007", + "B027", + "B028", + "B018", + "B020", + "B026", + "B904", + "C400", + "C402", + "C405", + "C408", + "C414", + "C416", + "E701", + "F401", + "F403", + "E501", + "PLR2004", + "PLR5501", + "PLW0120", + "PLW0603", + "PLW0602", + "PLW2901", + "UP028", + "UP030", + "UP031", ] [tool.ruff.per-file-ignores] "__init__.py" = [ "F401" # unused-import ] +"menus/menu_pool.py" = [ + "PLW2901", # `for` loop variable `menu_cls` overwritten by assignment target +] +"cms/toolbar/utils.py" = [ + "B020" # Loop control variable `plugin` overrides iterable it iterates +] [tool.ruff.isort] combine-as-imports = true From 1d99f9ccf56db3d527ccfd1b4c610e1eaba54c79 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sun, 28 Jan 2024 13:18:24 +0000 Subject: [PATCH 4/7] ci: Some straightforward ruff fixes --- cms/admin/forms.py | 691 ++++++++++-------- cms/admin/pageadmin.py | 16 +- cms/admin/placeholderadmin.py | 8 +- cms/admin/settingsadmin.py | 2 +- cms/admin/useradmin.py | 2 +- cms/admin/utils.py | 3 +- cms/app_base.py | 2 +- cms/app_registration.py | 2 +- cms/apphook_pool.py | 2 +- cms/appresolver.py | 2 +- cms/cache/placeholder.py | 7 +- cms/cms_config.py | 6 +- cms/cms_menus.py | 6 +- cms/cms_plugins.py | 3 +- cms/cms_toolbars.py | 9 +- cms/forms/validators.py | 2 +- cms/forms/wizards.py | 8 +- cms/management/commands/startcmsproject.py | 4 +- cms/management/commands/subcommands/copy.py | 2 +- cms/middleware/page.py | 1 - cms/models/contentmodels.py | 10 +- cms/models/managers.py | 5 +- cms/models/pagemodel.py | 14 +- cms/models/placeholdermodel.py | 2 +- cms/models/pluginmodel.py | 6 +- cms/page_rendering.py | 2 +- cms/plugin_base.py | 5 +- cms/plugin_pool.py | 2 +- cms/plugin_rendering.py | 4 +- cms/signals/log_entries.py | 2 +- cms/signals/permissions.py | 6 +- cms/sitemaps/cms_sitemap.py | 1 - cms/templates.py | 2 +- cms/templatetags/cms_admin.py | 7 +- cms/templatetags/cms_js_tags.py | 2 +- cms/templatetags/cms_tags.py | 16 +- cms/test_utils/fixtures/fakemlng.py | 2 +- cms/test_utils/fixtures/menus.py | 8 +- cms/test_utils/fixtures/navextenders.py | 2 +- cms/test_utils/fixtures/templatetags.py | 2 +- .../project/brokenpluginapp/cms_plugins.py | 2 +- .../project/bunch_of_plugins/models.py | 4 +- .../project/mti_pluginapp/models.py | 2 +- .../project/objectpermissionsapp/backends.py | 2 +- .../project/placeholderapp/cms_plugins.py | 2 +- .../project/placeholderapp/models.py | 24 +- .../project/pluginapp/plugins/link/models.py | 2 +- .../plugins/manytomany_rel/models.py | 2 +- .../pluginapp/plugins/multicolumn/models.py | 2 +- .../project/pluginapp/plugins/style/models.py | 2 +- cms/test_utils/project/sampleapp/views.py | 2 +- cms/test_utils/runners.py | 2 +- cms/test_utils/testcases.py | 18 +- cms/test_utils/util/context_managers.py | 10 +- cms/test_utils/util/mock.py | 2 +- cms/test_utils/util/static_analysis.py | 2 +- cms/tests/test_admin.py | 1 - cms/tests/test_app_registration.py | 2 +- cms/tests/test_cache.py | 451 +++++++----- cms/tests/test_check.py | 2 +- cms/tests/test_cms_config_wizards.py | 6 +- cms/tests/test_extensions.py | 4 +- cms/tests/test_forms.py | 6 +- cms/tests/test_management.py | 10 +- cms/tests/test_menu.py | 3 +- cms/tests/test_menu_page_viewperm.py | 4 +- cms/tests/test_migrations.py | 2 +- cms/tests/test_nested_plugins.py | 8 +- cms/tests/test_page.py | 14 +- cms/tests/test_page_admin.py | 9 +- cms/tests/test_placeholder.py | 12 +- cms/tests/test_placeholder_checks.py | 3 +- cms/tests/test_plugin_renderers.py | 4 +- cms/tests/test_plugins.py | 4 +- cms/tests/test_rendering.py | 12 +- cms/tests/test_templatetags.py | 6 +- cms/tests/test_toolbar.py | 51 +- cms/tests/test_toolbar_enabled_models.py | 5 +- cms/tests/test_views.py | 2 +- cms/tests/test_wizards.py | 19 +- cms/toolbar/items.py | 2 +- cms/toolbar/toolbar.py | 2 +- cms/toolbar/utils.py | 3 - cms/toolbar_pool.py | 2 +- cms/utils/apphook_reload.py | 5 +- cms/utils/check.py | 16 +- cms/utils/compat/forms.py | 10 +- cms/utils/conf.py | 2 +- cms/utils/helpers.py | 4 +- cms/utils/page.py | 7 +- cms/utils/placeholder.py | 141 ++-- cms/utils/plugins.py | 8 +- cms/utils/request_ip_resolvers.py | 8 +- cms/utils/setup.py | 8 +- cms/utils/urlutils.py | 6 +- cms/views.py | 25 +- cms/wizards/forms.py | 2 +- cms/wizards/helpers.py | 2 +- cms/wizards/views.py | 2 +- cms/wizards/wizard_base.py | 16 +- cms/wizards/wizard_pool.py | 8 +- menus/base.py | 6 +- menus/menu_pool.py | 23 +- menus/modifiers.py | 5 +- menus/utils.py | 6 +- 105 files changed, 1009 insertions(+), 908 deletions(-) diff --git a/cms/admin/forms.py b/cms/admin/forms.py index 30d3827a120..898961eed85 100644 --- a/cms/admin/forms.py +++ b/cms/admin/forms.py @@ -7,12 +7,10 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.forms.utils import ErrorList from django.forms.widgets import HiddenInput -from django.template.defaultfilters import slugify from django.utils import timezone from django.utils.encoding import force_str from django.utils.functional import cached_property -from django.utils.translation import get_language, gettext -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import get_language, gettext, gettext_lazy as _ from cms import api from cms.apphook_pool import apphook_pool @@ -64,10 +62,16 @@ def get_permission_accessor(obj): User = get_user_model() - if isinstance(obj, (PageUser, User,)): - rel_name = 'user_permissions' + if isinstance( + obj, + ( + PageUser, + User, + ), + ): + rel_name = "user_permissions" else: - rel_name = 'permissions' + rel_name = "permissions" return getattr(obj, rel_name) @@ -76,32 +80,30 @@ def get_page_changed_by_filter_choices(): # Been like this forever # Would be nice for it to filter out by site values = ( - Page - .objects - .distinct() - .order_by('changed_by') - .values_list('changed_by', flat=True) + Page.objects.distinct() + .order_by("changed_by") + .values_list("changed_by", flat=True) ) - yield ('', _('All')) + yield ("", _("All")) for value in values: yield (value, value) def get_page_template_filter_choices(): - yield ('', _('All')) + yield ("", _("All")) - for value, name in get_cms_setting('TEMPLATES'): + for value, name in get_cms_setting("TEMPLATES"): yield (value, name) def save_permissions(data, obj): models = ( - (Page, 'page'), - (PageUser, 'pageuser'), - (PageUserGroup, 'pageuser'), - (PagePermission, 'pagepermission'), + (Page, "page"), + (PageUser, "pageuser"), + (PageUserGroup, "pageuser"), + (PagePermission, "pagepermission"), ) if not obj.pk: @@ -112,11 +114,13 @@ def save_permissions(data, obj): for model, name in models: content_type = ContentType.objects.get_for_model(model) - for key in ('add', 'change', 'delete'): + for key in ("add", "change", "delete"): # add permission `key` for model `model` codename = get_permission_codename(key, model._meta) - permission = Permission.objects.get(content_type=content_type, codename=codename) - field = 'can_%s_%s' % (key, name) + permission = Permission.objects.get( + content_type=content_type, codename=codename + ) + field = "can_%s_%s" % (key, name) if data.get(field): permission_accessor.add(permission) @@ -128,8 +132,9 @@ class CopyPermissionForm(forms.Form): """ Holds the specific field for permissions """ + copy_permissions = forms.BooleanField( - label=_('Copy permissions'), + label=_("Copy permissions"), required=False, initial=True, ) @@ -152,16 +157,16 @@ def __init__(self, attrs=None): super().__init__(attrs) def get_unihandecode_settings(self, language): - if language[:2] in get_cms_setting('UNIHANDECODE_DECODERS'): + if language[:2] in get_cms_setting("UNIHANDECODE_DECODERS"): uhd_lang = language[:2] else: - uhd_lang = get_cms_setting('UNIHANDECODE_DEFAULT_DECODER') - uhd_host = get_cms_setting('UNIHANDECODE_HOST') - uhd_version = get_cms_setting('UNIHANDECODE_VERSION') + uhd_lang = get_cms_setting("UNIHANDECODE_DEFAULT_DECODER") + uhd_host = get_cms_setting("UNIHANDECODE_HOST") + uhd_version = get_cms_setting("UNIHANDECODE_VERSION") if uhd_lang and uhd_host and uhd_version: uhd_urls = [ - f'{uhd_host}unihandecode-{uhd_version}.core.min.js', - f'{uhd_host}unihandecode-{uhd_version}.{uhd_lang}.min.js', + f"{uhd_host}unihandecode-{uhd_version}.core.min.js", + f"{uhd_host}unihandecode-{uhd_version}.{uhd_lang}.min.js", ] else: uhd_urls = [] @@ -170,8 +175,8 @@ def get_unihandecode_settings(self, language): @property def media(self): js_media = [ - 'admin/js/urlify.js', - static_with_version('cms/js/dist/bundle.forms.slugwidget.min.js'), + "admin/js/urlify.js", + static_with_version("cms/js/dist/bundle.forms.slugwidget.min.js"), ] + self.uhd_urls return forms.Media(js=js_media) @@ -184,33 +189,33 @@ class BasePageContentForm(forms.ModelForm): label=_("Title"), max_length=255, widget=forms.TextInput(), - help_text=_('The default title') + help_text=_("The default title"), ) slug = forms.SlugField( label=_("Slug"), max_length=255, - help_text=_('The part of the title that is used in the URL') + help_text=_("The part of the title that is used in the URL"), ) menu_title = forms.CharField( label=_("Menu Title"), widget=forms.TextInput(), - help_text=_('Overwrite what is displayed in the menu'), - required=False + help_text=_("Overwrite what is displayed in the menu"), + required=False, ) page_title = forms.CharField( label=_("Page Title"), widget=forms.TextInput(), required=False, - help_text=_('Overwrites what is displayed at the top of your browser or in bookmarks'), + help_text=_( + "Overwrites what is displayed at the top of your browser or in bookmarks" + ), ) meta_description = forms.CharField( - label=_('Description meta tag'), + label=_("Description meta tag"), max_length=320, required=False, - widget=forms.Textarea( - attrs={'maxlength': '320', 'rows': '4'} - ), - help_text=_('A description of the page used by search engines.'), + widget=forms.Textarea(attrs={"maxlength": "320", "rows": "4"}), + help_text=_("A description of the page used by search engines."), ) class Meta: @@ -219,8 +224,8 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - attrs = dict(self.fields['slug'].widget.attrs or {}, language=self._language) - self.fields['slug'].widget = SlugWidget(attrs=attrs) + attrs = dict(self.fields["slug"].widget.attrs or {}, language=self._language) + self.fields["slug"].widget = SlugWidget(attrs=attrs) @cached_property def _language(self): @@ -233,7 +238,7 @@ def _user(self): class AddPageForm(BasePageContentForm): source = forms.ModelChoiceField( - label=_('Page type'), + label=_("Page type"), queryset=Page.objects.filter(is_page_type=True), required=False, ) @@ -248,22 +253,22 @@ class AddPageForm(BasePageContentForm): widget=forms.HiddenInput(), ) content_defaults = { - 'in_navigation': True, + "in_navigation": True, } class Meta: model = PageContent - fields = ['source'] + fields = ["source"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - source_field = self.fields.get('source') + source_field = self.fields.get("source") if not source_field or source_field.widget.is_hidden: return - page_field = self.fields.get('cms_page') + page_field = self.fields.get("cms_page") if page_field: page_field.queryset = page_field.queryset.filter(node__site=self._site) @@ -273,8 +278,10 @@ def __init__(self, *args, **kwargs): if root_page: # Set the choicefield's choices to the various page_types descendants = root_page.get_descendant_pages().filter(is_page_type=True) - titles = PageContent.objects.filter(page__in=descendants, language=self._language) - choices = [('', '---------')] + titles = PageContent.objects.filter( + page__in=descendants, language=self._language + ) + choices = [("", "---------")] choices.extend((title.page_id, title.title) for title in titles) source_field.choices = choices else: @@ -291,14 +298,14 @@ def clean(self): # addressed first. return data - parent_node = data.get('parent_node') + parent_node = data.get("parent_node") if parent_node: - slug = data['slug'] + slug = data["slug"] parent_path = parent_node.item.get_path(self._language) - path = u'%s/%s' % (parent_path, slug) if parent_path else slug + path = "%s/%s" % (parent_path, slug) if parent_path else slug else: - path = data['slug'] + path = data["slug"] try: # Validate the url @@ -309,13 +316,13 @@ def clean(self): user_language=self._language, ) except ValidationError as error: - self.add_error('slug', error) + self.add_error("slug", error) else: - data['path'] = path + data["path"] = path return data def clean_parent_node(self): - parent_node = self.cleaned_data.get('parent_node') + parent_node = self.cleaned_data.get("parent_node") if parent_node and parent_node.site_id != self._site.pk: raise ValidationError("Site doesn't match the parent's page site") @@ -324,24 +331,24 @@ def clean_parent_node(self): def create_translation(self, page): data = self.cleaned_data title_kwargs = { - 'page': page, - 'language': self._language, - 'slug': data['slug'], - 'path': data['path'], - 'title': data['title'], - 'template': self.get_template(), - 'created_by': self._user, + "page": page, + "language": self._language, + "slug": data["slug"], + "path": data["path"], + "title": data["title"], + "template": self.get_template(), + "created_by": self._user, } title_kwargs.update(self.content_defaults) - if 'menu_title' in data: - title_kwargs['menu_title'] = data['menu_title'] + if "menu_title" in data: + title_kwargs["menu_title"] = data["menu_title"] - if 'page_title' in data: - title_kwargs['page_title'] = data['page_title'] + if "page_title" in data: + title_kwargs["page_title"] = data["page_title"] - if 'meta_description' in data: - title_kwargs['meta_description'] = data['meta_description'] + if "meta_description" in data: + title_kwargs["meta_description"] = data["meta_description"] return api.create_page_content(**title_kwargs) def from_source(self, source, parent=None): @@ -358,15 +365,15 @@ def from_source(self, source, parent=None): return new_page def get_template(self): - source = self.cleaned_data.get('source') + source = self.cleaned_data.get("source") if source: return source.get_template(self._language) return PageContent.TEMPLATE_DEFAULT def save(self, *args, **kwargs): - page = self.cleaned_data.get('cms_page') - source = self.cleaned_data.get('source') - parent = self.cleaned_data.get('parent_node') + page = self.cleaned_data.get("cms_page") + source = self.cleaned_data.get("source") + parent = self.cleaned_data.get("parent_node") operation_token = send_pre_page_operation( request=self._request, @@ -380,7 +387,7 @@ def save(self, *args, **kwargs): new_page = self.from_source(source, parent=parent) else: new_page = Page() - new_page.set_tree_node(self._site, target=parent, position='last-child') + new_page.set_tree_node(self._site, target=parent, position="last-child") new_page.save() translation = self.create_translation(new_page) @@ -399,12 +406,12 @@ def save(self, *args, **kwargs): slot=source_placeholder.slot, default_width=source_placeholder.default_width, ) - source_placeholder.copy_plugins(target_placeholder, language=translation.language) + source_placeholder.copy_plugins( + target_placeholder, language=translation.language + ) is_first = not ( - TreeNode - .objects - .get_for_site(self._site) + TreeNode.objects.get_for_site(self._site) .exclude(pk=new_page.node_id) .exists() ) @@ -436,7 +443,7 @@ class AddPageTypeForm(AddPageForm): widget=forms.HiddenInput(), ) content_defaults = { - 'in_navigation': False, + "in_navigation": False, } def get_or_create_root(self): @@ -454,7 +461,7 @@ def get_or_create_root(self): if not root_page.has_translation(self._language): api.create_page_content( language=self._language, - title=gettext('Page Types'), + title=gettext("Page Types"), page=root_page, slug=PAGE_TYPES_ID, path=PAGE_TYPES_ID, @@ -489,7 +496,7 @@ def from_source(self, source, parent=None): def save(self, *args, **kwargs): new_page = super().save(*args, **kwargs) - if not self.cleaned_data.get('source'): + if not self.cleaned_data.get("source"): # User has created a page-type via "Add page" # instead of from another page. new_page.update(is_page_type=True) @@ -506,57 +513,72 @@ class DuplicatePageForm(AddPageForm): class ChangePageForm(BasePageContentForm): overwrite_url = forms.CharField( - label=_('Overwrite URL'), + label=_("Overwrite URL"), max_length=255, required=False, - help_text=_('Keep this field empty if standard path should be used.'), + help_text=_("Keep this field empty if standard path should be used."), ) soft_root = forms.BooleanField( - label=_('Soft root'), + label=_("Soft root"), required=False, help_text=_("All ancestors will not be displayed in the navigation"), ) redirect = PageSmartLinkField( - label=_('Redirect'), + label=_("Redirect"), required=False, - help_text=_('Redirects to this URL.'), - placeholder_text=_('Start typing...'), - ajax_view='admin:cms_page_get_list', + help_text=_("Redirects to this URL."), + placeholder_text=_("Start typing..."), + ajax_view="admin:cms_page_get_list", ) limit_visibility_in_menu = forms.TypedChoiceField( - choices=PageContent._meta.get_field('limit_visibility_in_menu').choices, + choices=PageContent._meta.get_field("limit_visibility_in_menu").choices, label=_("menu visibility"), help_text=_("limit when this page is visible in the menu"), - initial=PageContent._meta.get_field('limit_visibility_in_menu').default, + initial=PageContent._meta.get_field("limit_visibility_in_menu").default, required=False, coerce=int, empty_value=None, ) fieldsets = ( - (None, { - 'fields': ('title', 'slug', 'template', 'page_title', 'meta_description'), - }), - (_('URL options'), { - 'fields': ('overwrite_url', 'redirect'), - 'classes': ['collapse'], - }), - (_('Menu options'), { - 'fields': ('soft_root', 'menu_title', 'limit_visibility_in_menu'), - 'classes': ['collapse'], - }) + ( + None, + { + "fields": ( + "title", + "slug", + "template", + "page_title", + "meta_description", + ), + }, + ), + ( + _("URL options"), + { + "fields": ("overwrite_url", "redirect"), + "classes": ["collapse"], + }, + ), + ( + _("Menu options"), + { + "fields": ("soft_root", "menu_title", "limit_visibility_in_menu"), + "classes": ["collapse"], + }, + ), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.url_obj = self.instance.page.get_url(self._language) - self.fields['slug'].initial = self.url_obj.slug - self.fields['redirect'].widget.language = self._language - self.fields['redirect'].initial = self.instance.redirect + self.fields["slug"].initial = self.url_obj.slug + self.fields["redirect"].widget.language = self._language + self.fields["redirect"].initial = self.instance.redirect if not self.url_obj.managed: - self.fields['overwrite_url'].initial = self.url_obj.path + self.fields["overwrite_url"].initial = self.url_obj.path @cached_property def _language(self): @@ -573,28 +595,30 @@ def clean(self): page = self.instance.page if page.is_home: - data['path'] = '' + data["path"] = "" return data - slug = data['slug'] - path_override = self.cleaned_data.get('overwrite_url') + slug = data["slug"] + path_override = self.cleaned_data.get("overwrite_url") parent_page = page.parent_page if path_override: - path = path_override.strip('/') + path = path_override.strip("/") elif parent_page and parent_page.is_home: path = slug elif parent_page: base_path = parent_page.get_path(self._language) - path = u'%s/%s' % (base_path, slug) if base_path else None + path = "%s/%s" % (base_path, slug) if base_path else None else: path = slug if path is None: - data['path'] = None + data["path"] = None return data - user_language = get_site_language_from_request(self._request, site_id=self._site.pk) + user_language = get_site_language_from_request( + self._request, site_id=self._site.pk + ) try: # Validate the url @@ -606,20 +630,20 @@ def clean(self): exclude_page=page, ) except ValidationError as error: - field = 'overwrite_url' if path_override else 'slug' + field = "overwrite_url" if path_override else "slug" self.add_error(field, error) else: - data['path'] = path + data["path"] = path return data def clean_xframe_options(self): - if 'xframe_options' not in self.fields: + if "xframe_options" not in self.fields: return # nothing to do, field isn't present - xframe_options = self.cleaned_data['xframe_options'] + xframe_options = self.cleaned_data["xframe_options"] - if xframe_options == '': - return PageContent._meta.get_field('xframe_options').default + if xframe_options == "": + return PageContent._meta.get_field("xframe_options").default return xframe_options def save(self, commit=True): @@ -631,14 +655,14 @@ def save(self, commit=True): data = self.cleaned_data.copy() page = self.instance.page - page_slug = data.pop('slug', None) - page_path = data.pop('path', None) - page_overwrite_url = data.pop('overwrite_url', None) + page_slug = data.pop("slug", None) + page_path = data.pop("path", None) + page_overwrite_url = data.pop("overwrite_url", None) page_content = super().save(commit=False) page_content.update( changed_by=get_clean_username(self._request.user), changed_date=timezone.now(), - **data + **data, ) page.update_urls( self._language, @@ -649,7 +673,7 @@ def save(self, commit=True): page._update_url_path_recursive(self._language) page.clear_cache(menu=True) - if page.application_urls and 'slug' in self.changed_data: + if page.application_urls and "slug" in self.changed_data: # Connects the apphook restart handler to the request finished signal set_restart_trigger() send_post_page_operation( @@ -667,15 +691,15 @@ class AdvancedSettingsForm(forms.ModelForm): _request = None application_urls = forms.ChoiceField( - label=_('Application'), + label=_("Application"), choices=(), required=False, - help_text=_('Hook application to this page.'), + help_text=_("Hook application to this page."), ) # This is really a 'fake' field which does not correspond to any Page attribute # But creates a stub field to be populate by js application_configs = forms.CharField( - label=_('Application configurations'), + label=_("Application configurations"), required=False, widget=ApplicationConfigSelect, ) @@ -683,22 +707,23 @@ class AdvancedSettingsForm(forms.ModelForm): class Meta: model = Page fields = [ - 'login_required', - 'reverse_id', - 'navigation_extenders', - 'application_urls', - 'application_namespace', - 'application_configs', + "login_required", + "reverse_id", + "navigation_extenders", + "application_urls", + "application_namespace", + "application_configs", ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - if 'navigation_extenders' in self.fields: + if "navigation_extenders" in self.fields: navigation_extenders = self.get_navigation_extenders() - self.fields['navigation_extenders'].widget = forms.Select( - {}, [('', "---------")] + navigation_extenders) - if 'application_urls' in self.fields: + self.fields["navigation_extenders"].widget = forms.Select( + {}, [("", "---------")] + navigation_extenders + ) + if "application_urls" in self.fields: # Prepare a dict mapping the apps by class name ('PollApp') to # their app_name attribute ('polls'), if any. app_namespaces = {} @@ -710,28 +735,34 @@ def __init__(self, *args, **kwargs): if app.app_config: app_configs[hook[0]] = app - self.fields['application_urls'].widget = AppHookSelect( - attrs={'id': 'application_urls'}, - app_namespaces=app_namespaces + self.fields["application_urls"].widget = AppHookSelect( + attrs={"id": "application_urls"}, app_namespaces=app_namespaces ) - self.fields['application_urls'].choices = [('', "---------")] + apphook_pool.get_apphooks() + self.fields["application_urls"].choices = [ + ("", "---------") + ] + apphook_pool.get_apphooks() page_data = self.data if self.data else self.initial if app_configs: - self.fields['application_configs'].widget = ApplicationConfigSelect( - attrs={'id': 'application_configs'}, + self.fields["application_configs"].widget = ApplicationConfigSelect( + attrs={"id": "application_configs"}, app_configs=app_configs, ) - if page_data.get('application_urls', False) and page_data['application_urls'] in app_configs: - configs = app_configs[page_data['application_urls']].get_configs() - self.fields['application_configs'].widget.choices = [ + if ( + page_data.get("application_urls", False) + and page_data["application_urls"] in app_configs + ): + configs = app_configs[page_data["application_urls"]].get_configs() + self.fields["application_configs"].widget.choices = [ (config.pk, force_str(config)) for config in configs ] try: - config = configs.get(namespace=self.initial['application_namespace']) - self.fields['application_configs'].initial = config.pk + config = configs.get( + namespace=self.initial["application_namespace"] + ) + self.fields["application_configs"].initial = config.pk except ObjectDoesNotExist: # Provided apphook configuration doesn't exist (anymore), # just skip it @@ -749,18 +780,19 @@ def clean(self): # Fail fast if there's errors in the form return cleaned_data - if 'reverse_id' in self.fields: - reverse_id = cleaned_data['reverse_id'] + if "reverse_id" in self.fields: + reverse_id = cleaned_data["reverse_id"] if reverse_id: lookup = Page.objects.on_site(self._site).filter(reverse_id=reverse_id) if lookup.exclude(pk=self.instance.pk).exists(): - self._errors['reverse_id'] = self.error_class( - [_('A page with this reverse URL id exists already.')]) - apphook = cleaned_data.get('application_urls', None) + self._errors["reverse_id"] = self.error_class( + [_("A page with this reverse URL id exists already.")] + ) + apphook = cleaned_data.get("application_urls", None) # The field 'application_namespace' is a misnomer. It should be # 'instance_namespace'. - instance_namespace = cleaned_data.get('application_namespace', None) - application_config = cleaned_data.get('application_configs', None) + instance_namespace = cleaned_data.get("application_namespace", None) + application_config = cleaned_data.get("application_configs", None) if apphook: apphooks_with_config = self.get_apphooks_with_config() @@ -771,35 +803,47 @@ def clean(self): # the 'usual' namespace field to be backward compatible # with existing apphooks try: - appconfig_pk = forms.IntegerField(required=True).to_python(application_config) + appconfig_pk = forms.IntegerField(required=True).to_python( + application_config + ) except ValidationError: - self._errors['application_configs'] = ErrorList([ - _('Invalid application config value') - ]) + self._errors["application_configs"] = ErrorList( + [_("Invalid application config value")] + ) return self.cleaned_data try: - config = apphooks_with_config[apphook].get_configs().get(pk=appconfig_pk) + config = ( + apphooks_with_config[apphook].get_configs().get(pk=appconfig_pk) + ) except ObjectDoesNotExist: - self._errors['application_configs'] = ErrorList([ - _('Invalid application config value') - ]) + self._errors["application_configs"] = ErrorList( + [_("Invalid application config value")] + ) return self.cleaned_data if self._check_unique_namespace_instance(config.namespace): # Looks like there's already one with the default instance # namespace defined. - self._errors['application_configs'] = ErrorList([ - _('An application instance using this configuration already exists.') - ]) + self._errors["application_configs"] = ErrorList( + [ + _( + "An application instance using this configuration already exists." + ) + ] + ) else: - self.cleaned_data['application_namespace'] = config.namespace + self.cleaned_data["application_namespace"] = config.namespace else: if instance_namespace: if self._check_unique_namespace_instance(instance_namespace): - self._errors['application_namespace'] = ErrorList([ - _('An application instance with this name already exists.') - ]) + self._errors["application_namespace"] = ErrorList( + [ + _( + "An application instance with this name already exists." + ) + ] + ) else: # The attribute on the apps 'app_name' is a misnomer, it should be # 'application_namespace'. @@ -808,9 +852,13 @@ def clean(self): if self._check_unique_namespace_instance(application_namespace): # Looks like there's already one with the default instance # namespace defined. - self._errors['application_namespace'] = ErrorList([ - _('An application instance with this name already exists.') - ]) + self._errors["application_namespace"] = ErrorList( + [ + _( + "An application instance with this name already exists." + ) + ] + ) else: # OK, there are zero instances of THIS app that use the # default instance namespace, so, since the user didn't @@ -818,13 +866,15 @@ def clean(self): # line is really setting the "instance namespace" of the # new app to the app’s "application namespace", which is # the default instance namespace. - self.cleaned_data['application_namespace'] = application_namespace + self.cleaned_data["application_namespace"] = ( + application_namespace + ) if instance_namespace and not apphook: - self.cleaned_data['application_namespace'] = None + self.cleaned_data["application_namespace"] = None if application_config and not apphook: - self.cleaned_data['application_configs'] = None + self.cleaned_data["application_configs"] = None return self.cleaned_data def get_apphooks(self): @@ -838,19 +888,22 @@ def get_navigation_extenders(self): return menu_pool.get_menus_by_attribute("cms_enabled", True) def _check_unique_namespace_instance(self, namespace): - return Page.objects.on_site(self._site).filter( - application_namespace=namespace - ).exclude(pk=self.instance.pk).exists() + return ( + Page.objects.on_site(self._site) + .filter(application_namespace=namespace) + .exclude(pk=self.instance.pk) + .exists() + ) def has_changed_apphooks(self): changed_data = self.changed_data - if 'application_urls' in changed_data: + if "application_urls" in changed_data: return True - return 'application_namespace' in changed_data + return "application_namespace" in changed_data def save(self, *args, **kwargs): - page = super(AdvancedSettingsForm, self).save(*args, **kwargs) + page = super().save(*args, **kwargs) page.clear_cache(menu=True) clear_permission_cache() @@ -865,10 +918,10 @@ class PageTreeForm(forms.Form): target = forms.ModelChoiceField(queryset=Page.objects.none(), required=False) def __init__(self, *args, **kwargs): - self.page = kwargs.pop('page') - self._site = kwargs.pop('site', Site.objects.get_current()) + self.page = kwargs.pop("page") + self._site = kwargs.pop("site", Site.objects.get_current()) super().__init__(*args, **kwargs) - self.fields['target'].queryset = Page.objects.filter( + self.fields["target"].queryset = Page.objects.filter( node__site=self._site, is_page_type=self.page.is_page_type, ) @@ -879,8 +932,8 @@ def get_root_nodes(self): return nodes.exclude(cms_pages__is_page_type=not self.page.is_page_type) def get_tree_options(self): - position = self.cleaned_data['position'] - target_page = self.cleaned_data.get('target') + position = self.cleaned_data["position"] + target_page = self.cleaned_data.get("target") parent_node = target_page.node if target_page else None if parent_node: @@ -896,12 +949,12 @@ def _get_tree_options_for_root(self, position): # The position requested is not occupied. # Add the node as the last root node, # relative to the current site. - return (siblings.reverse()[0], 'right') - return (target_node, 'left') + return (siblings.reverse()[0], "right") + return (target_node, "left") def _get_tree_options_for_parent(self, parent_node, position): if position == 0: - return (parent_node, 'first-child') + return (parent_node, "first-child") siblings = parent_node.get_children().filter(site=self._site) @@ -910,8 +963,8 @@ def _get_tree_options_for_parent(self, parent_node, position): except IndexError: # The position requested is not occupied. # Add the node to be the parent's first child - return (parent_node, 'last-child') - return (target_node, 'left') + return (parent_node, "last-child") + return (target_node, "left") class MovePageForm(PageTreeForm): @@ -919,15 +972,18 @@ class MovePageForm(PageTreeForm): def clean(self): cleaned_data = super().clean() - if self.page.is_home and cleaned_data.get('target'): - self.add_error('target', force_str(_('You can\'t move the home page inside another page'))) + if self.page.is_home and cleaned_data.get("target"): + self.add_error( + "target", + force_str(_("You can't move the home page inside another page")), + ) return cleaned_data def get_tree_options(self): options = super().get_tree_options() target_node, target_node_position = options - if target_node_position != 'left': + if target_node_position != "left": return (target_node, target_node_position) node = self.page.node @@ -937,16 +993,16 @@ def get_tree_options(self): # The node being moved appears before the target node # and is a sibling of the target node. # The user is moving from left to right. - target_node_position = 'right' + target_node_position = "right" elif node_is_first: # The node being moved appears before the target node # but is not a sibling of the target node. # The user is moving from right to left. - target_node_position = 'left' + target_node_position = "left" else: # The node being moved appears after the target node. # The user is moving from right to left. - target_node_position = 'left' + target_node_position = "left" return (target_node, target_node_position) def move_page(self): @@ -959,7 +1015,7 @@ class CopyPageForm(PageTreeForm): def copy_page(self, user): target, position = self.get_tree_options() - copy_permissions = self.cleaned_data.get('copy_permissions', False) + copy_permissions = self.cleaned_data.get("copy_permissions", False) new_page = self.page.copy_with_descendants( target_node=target, position=position, @@ -976,14 +1032,14 @@ def _get_tree_options_for_root(self, position): # The user is copying a page to a site with no pages # Add the node as the last root node. siblings = self.get_root_nodes().reverse() - return (siblings[0], 'right') + return (siblings[0], "right") class ChangeListForm(forms.Form): BOOLEAN_CHOICES = ( - ('', _('All')), - ('1', _('Yes')), - ('0', _('No')), + ("", _("All")), + ("1", _("Yes")), + ("0", _("No")), ) q = forms.CharField(required=False, widget=forms.HiddenInput()) @@ -994,13 +1050,13 @@ class ChangeListForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['changed_by'].choices = get_page_changed_by_filter_choices() - self.fields['template'].choices = get_page_template_filter_choices() + self.fields["changed_by"].choices = get_page_changed_by_filter_choices() + self.fields["template"].choices = get_page_template_filter_choices() def is_filtered(self): data = self.cleaned_data - if self.cleaned_data.get('q'): + if self.cleaned_data.get("q"): return True return any(bool(data.get(field.name)) for field in self.visible_fields()) @@ -1013,7 +1069,7 @@ def get_filter_items(self): def run_filters(self, queryset): for field, value in self.get_filter_items(): - query = {'{}__exact'.format(field): value} + query = {f"{field}__exact": value} queryset = queryset.filter(**query) return queryset @@ -1036,9 +1092,10 @@ class PagePermissionInlineAdminForm(BasePermissionAdminForm): level or under him in chosen page tree, and users which were created by him, but aren't assigned to higher page level than current user. """ + page = forms.ModelChoiceField( queryset=Page.objects.all(), - label=_('user'), + label=_("user"), widget=HiddenInput(), required=True, ) @@ -1057,7 +1114,7 @@ def __init__(self, *args, **kwargs): # user PKs in limit_choices_to in the query string of the popup we're # in danger of causing 414 errors so we fall back to the normal input # widget. - if get_cms_setting('RAW_ID_USERS'): + if get_cms_setting("RAW_ID_USERS"): if sub_users.count() < 500: # If there aren't too many users, proceed as normal and use a # raw id field with limit_choices_to @@ -1078,31 +1135,31 @@ def __init__(self, *args, **kwargs): # This check will be False if the number of users in the system # is less than the threshold set by the RAW_ID_USERS setting. - if isinstance(self.fields['user'].widget, ForeignKeyRawIdWidget): + if isinstance(self.fields["user"].widget, ForeignKeyRawIdWidget): # We can't set a queryset on a raw id lookup, but we can use # the fact that it respects the limit_choices_to parameter. if limit_choices: - self.fields['user'].widget.rel.limit_choices_to = dict( - id__in=list(sub_users.values_list('pk', flat=True)) + self.fields["user"].widget.rel.limit_choices_to = dict( + id__in=list(sub_users.values_list("pk", flat=True)) ) else: - self.fields['user'].widget = UserSelectAdminWidget() - self.fields['user'].queryset = sub_users - self.fields['user'].widget.user = user # assign current user + self.fields["user"].widget = UserSelectAdminWidget() + self.fields["user"].queryset = sub_users + self.fields["user"].widget.user = user # assign current user - self.fields['group'].queryset = get_subordinate_groups(user, site) + self.fields["group"].queryset = get_subordinate_groups(user, site) class Meta: fields = [ - 'user', - 'group', - 'can_add', - 'can_change', - 'can_delete', - 'can_change_advanced_settings', - 'can_change_permissions', - 'can_move_page', - 'grant_on', + "user", + "group", + "can_add", + "can_change", + "can_delete", + "can_change_advanced_settings", + "can_change_permissions", + "can_move_page", + "grant_on", ] model = PagePermission @@ -1110,22 +1167,22 @@ class Meta: class ViewRestrictionInlineAdminForm(BasePermissionAdminForm): page = forms.ModelChoiceField( queryset=Page.objects.all(), - label=_('user'), + label=_("user"), widget=HiddenInput(), required=True, ) can_view = forms.BooleanField( - label=_('can_view'), + label=_("can_view"), widget=HiddenInput(), initial=True, ) class Meta: fields = [ - 'user', - 'group', - 'grant_on', - 'can_view', + "user", + "group", + "grant_on", + "can_view", ] model = PagePermission @@ -1137,99 +1194,114 @@ class GlobalPagePermissionAdminForm(BasePermissionAdminForm): class Meta: fields = [ - 'user', - 'group', - 'can_add', - 'can_change', - 'can_delete', - 'can_change_advanced_settings', - 'can_change_permissions', - 'can_move_page', - 'can_view', - 'sites', + "user", + "group", + "can_add", + "can_change", + "can_delete", + "can_change_advanced_settings", + "can_change_permissions", + "can_move_page", + "can_view", + "sites", ] model = GlobalPagePermission class GenericCmsPermissionForm(forms.ModelForm): - """Generic form for User & Group permissions in cms - """ + """Generic form for User & Group permissions in cms""" + _current_user = None - can_add_page = forms.BooleanField(label=_('Add'), required=False, initial=True) - can_change_page = forms.BooleanField(label=_('Change'), required=False, initial=True) - can_delete_page = forms.BooleanField(label=_('Delete'), required=False) + can_add_page = forms.BooleanField(label=_("Add"), required=False, initial=True) + can_change_page = forms.BooleanField( + label=_("Change"), required=False, initial=True + ) + can_delete_page = forms.BooleanField(label=_("Delete"), required=False) # pageuser is for pageuser & group - they are combined together, # and read out from PageUser model - can_add_pageuser = forms.BooleanField(label=_('Add'), required=False) - can_change_pageuser = forms.BooleanField(label=_('Change'), required=False) - can_delete_pageuser = forms.BooleanField(label=_('Delete'), required=False) + can_add_pageuser = forms.BooleanField(label=_("Add"), required=False) + can_change_pageuser = forms.BooleanField(label=_("Change"), required=False) + can_delete_pageuser = forms.BooleanField(label=_("Delete"), required=False) - can_add_pagepermission = forms.BooleanField(label=_('Add'), required=False) - can_change_pagepermission = forms.BooleanField(label=_('Change'), required=False) - can_delete_pagepermission = forms.BooleanField(label=_('Delete'), required=False) + can_add_pagepermission = forms.BooleanField(label=_("Add"), required=False) + can_change_pagepermission = forms.BooleanField(label=_("Change"), required=False) + can_delete_pagepermission = forms.BooleanField(label=_("Delete"), required=False) def __init__(self, *args, **kwargs): - instance = kwargs.get('instance') - initial = kwargs.get('initial') or {} + instance = kwargs.get("instance") + initial = kwargs.get("initial") or {} if instance: initial = initial or {} initial.update(self.populate_initials(instance)) - kwargs['initial'] = initial + kwargs["initial"] = initial super().__init__(*args, **kwargs) def clean(self): data = super().clean() # Validate Page options - if not data.get('can_change_page'): - if data.get('can_add_page'): - message = _("Users can't create a page without permissions " - "to change the created page. Edit permissions required.") + if not data.get("can_change_page"): + if data.get("can_add_page"): + message = _( + "Users can't create a page without permissions " + "to change the created page. Edit permissions required." + ) raise ValidationError(message) - if data.get('can_delete_page'): - message = _("Users can't delete a page without permissions " - "to change the page. Edit permissions required.") + if data.get("can_delete_page"): + message = _( + "Users can't delete a page without permissions " + "to change the page. Edit permissions required." + ) raise ValidationError(message) - if data.get('can_add_pagepermission'): - message = _("Users can't set page permissions without permissions " - "to change a page. Edit permissions required.") + if data.get("can_add_pagepermission"): + message = _( + "Users can't set page permissions without permissions " + "to change a page. Edit permissions required." + ) raise ValidationError(message) - if data.get('can_delete_pagepermission'): - message = _("Users can't delete page permissions without permissions " - "to change a page. Edit permissions required.") + if data.get("can_delete_pagepermission"): + message = _( + "Users can't delete page permissions without permissions " + "to change a page. Edit permissions required." + ) raise ValidationError(message) # Validate PagePermission options - if not data.get('can_change_pagepermission'): - if data.get('can_add_pagepermission'): - message = _("Users can't create page permissions without permissions " - "to change the created permission. Edit permissions required.") + if not data.get("can_change_pagepermission"): + if data.get("can_add_pagepermission"): + message = _( + "Users can't create page permissions without permissions " + "to change the created permission. Edit permissions required." + ) raise ValidationError(message) - if data.get('can_delete_pagepermission'): - message = _("Users can't delete page permissions without permissions " - "to change permissions. Edit permissions required.") + if data.get("can_delete_pagepermission"): + message = _( + "Users can't delete page permissions without permissions " + "to change permissions. Edit permissions required." + ) raise ValidationError(message) def populate_initials(self, obj): - """Read out permissions from permission system. - """ + """Read out permissions from permission system.""" initials = {} permission_accessor = get_permission_accessor(obj) for model in (Page, PageUser, PagePermission): name = model.__name__.lower() content_type = ContentType.objects.get_for_model(model) - permissions = permission_accessor.filter(content_type=content_type).values_list('codename', flat=True) - for key in ('add', 'change', 'delete'): + permissions = permission_accessor.filter( + content_type=content_type + ).values_list("codename", flat=True) + for key in ("add", "change", "delete"): codename = get_permission_codename(key, model._meta) - initials['can_%s_%s' % (key, name)] = codename in permissions + initials["can_%s_%s" % (key, name)] = codename in permissions return initials def save(self, commit=True): @@ -1245,19 +1317,19 @@ class PageUserAddForm(forms.ModelForm): user = forms.ModelChoiceField(queryset=User.objects.none()) class Meta: - fields = ['user'] + fields = ["user"] model = PageUser def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['user'].queryset = self.get_subordinates() + self.fields["user"].queryset = self.get_subordinates() def get_subordinates(self): subordinates = get_subordinate_users(self._current_user, self._current_site) return subordinates.filter(pageuser__isnull=True) def save(self, commit=True): - user = self.cleaned_data['user'] + user = self.cleaned_data["user"] instance = super().save(commit=False) instance.created_by = self._current_user @@ -1277,7 +1349,7 @@ class PageUserChangeForm(UserChangeForm): _current_user = None class Meta: - fields = '__all__' + fields = "__all__" model = PageUser def __init__(self, *args, **kwargs): @@ -1287,15 +1359,15 @@ def __init__(self, *args, **kwargs): # Limit permissions to include only # the permissions available to the manager. permissions = self.get_available_permissions() - self.fields['user_permissions'].queryset = permissions + self.fields["user_permissions"].queryset = permissions # Limit groups to include only those where # the manager is a member. - self.fields['groups'].queryset = self.get_available_groups() + self.fields["groups"].queryset = self.get_available_groups() def get_available_permissions(self): permissions = self._current_user.get_all_permissions() - permission_codes = (perm.rpartition('.')[-1] for perm in permissions) + permission_codes = (perm.rpartition(".")[-1] for perm in permissions) return Permission.objects.filter(codename__in=permission_codes) def get_available_groups(self): @@ -1306,7 +1378,7 @@ class PageUserGroupForm(GenericCmsPermissionForm): class Meta: model = PageUserGroup - fields = ('name', ) + fields = ("name",) def save(self, commit=True): if not self.instance.pk: @@ -1328,7 +1400,7 @@ class PluginAddValidationForm(forms.Form): plugin_type = forms.CharField(required=True) def clean_plugin_type(self): - plugin_type = self.cleaned_data['plugin_type'] + plugin_type = self.cleaned_data["plugin_type"] try: plugin_pool.get_plugin(plugin_type) @@ -1345,30 +1417,34 @@ def clean(self): if self.errors: return data - language = data['plugin_language'] - position = data['plugin_position'] - placeholder = data['placeholder_id'] - parent_plugin = data.get('plugin_parent') + language = data["plugin_language"] + position = data["plugin_position"] + placeholder = data["placeholder_id"] + parent_plugin = data.get("plugin_parent") if language not in get_language_list(): message = gettext("Language must be set to a supported language!") - self.add_error('plugin_language', message) + self.add_error("plugin_language", message) return self.cleaned_data if parent_plugin: if parent_plugin.language != language: message = gettext("Parent plugin language must be same as language!") - self.add_error('plugin_language', message) + self.add_error("plugin_language", message) return self.cleaned_data if parent_plugin.placeholder_id != placeholder.pk: - message = gettext("Parent plugin placeholder must be same as placeholder!") - self.add_error('placeholder_id', message) + message = gettext( + "Parent plugin placeholder must be same as placeholder!" + ) + self.add_error("placeholder_id", message) return self.cleaned_data if position <= parent_plugin.position: message = gettext("Plugin position must be greater than %(position)d") - self.add_error('placeholder_id', message % {'position': parent_plugin.position}) + self.add_error( + "placeholder_id", message % {"position": parent_plugin.position} + ) return self.cleaned_data page = placeholder.page @@ -1376,10 +1452,7 @@ def clean(self): try: has_reached_plugin_limit( - placeholder, - data['plugin_type'], - language, - template=template + placeholder, data["plugin_type"], language, template=template ) except PluginLimitReached as error: self.add_error(None, force_str(error)) @@ -1395,22 +1468,22 @@ class RequestToolbarForm(forms.Form): def clean(self): data = self.cleaned_data - obj_id = data.get('obj_id') - obj_type = data.get('obj_type') + obj_id = data.get("obj_id") + obj_type = data.get("obj_type") if not bool(obj_id or obj_type): return data if (obj_id and not obj_type) or (obj_type and not obj_id): - message = 'Invalid object lookup. Both obj_id and obj_type are required' + message = "Invalid object lookup. Both obj_id and obj_type are required" raise forms.ValidationError(message) - app, sep, model = obj_type.rpartition('.') + app, sep, model = obj_type.rpartition(".") try: model_class = apps.get_model(app_label=app, model_name=model) except LookupError: - message = 'Invalid object lookup. Both obj_id and obj_type are required' + message = "Invalid object lookup. Both obj_id and obj_type are required" raise forms.ValidationError(message) try: @@ -1420,14 +1493,14 @@ def clean(self): else: generic_obj = model_class.objects.get(pk=obj_id) except model_class.DoesNotExist: - message = 'Invalid object lookup. Both obj_id and obj_type are required' + message = "Invalid object lookup. Both obj_id and obj_type are required" raise forms.ValidationError(message) else: - data['attached_obj'] = generic_obj + data["attached_obj"] = generic_obj return data def clean_cms_path(self): - path = self.cleaned_data.get('cms_path') + path = self.cleaned_data.get("cms_path") if path: validate_relative_url(path) diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py index 573cc046ac9..0e190bbd57e 100644 --- a/cms/admin/pageadmin.py +++ b/cms/admin/pageadmin.py @@ -127,11 +127,7 @@ def log_deletion(self, request, object, object_repr): return def get_admin_url(self, action, *args): - url_name = "{}_{}_{}".format( - self.opts.app_label, - self.opts.model_name, - action, - ) + url_name = f"{self.opts.app_label}_{self.opts.model_name}_{action}" return admin_reverse(url_name, args=args) def get_preserved_filters(self, request): @@ -830,11 +826,7 @@ def get_object(self, request, object_id, from_field=None): return obj def get_admin_url(self, action, *args): - url_name = "{}_{}_{}".format( - self.opts.app_label, - self.opts.model_name, - action, - ) + url_name = f"{self.opts.app_label}_{self.opts.model_name}_{action}" return admin_reverse(url_name, args=args) def get_preserved_filters(self, request): @@ -1297,7 +1289,7 @@ def delete_view(self, request, object_id, extra_context=None): return HttpResponseRedirect(admin_reverse('index')) redirect_to = self.get_admin_url('changelist') - redirect_to += '?language={}'.format(request_language) + redirect_to += f'?language={request_language}' return HttpResponseRedirect(redirect_to) context = { @@ -1381,7 +1373,7 @@ def get_tree(self, request): depth=(page.node.depth + 1 if page else 1), follow_descendants=True, ) - return HttpResponse(u''.join(rows)) + return HttpResponse(''.join(rows)) def get_tree_rows(self, request, pages, language, depth=1, follow_descendants=True): diff --git a/cms/admin/placeholderadmin.py b/cms/admin/placeholderadmin.py index fe8822fca1e..f0570896774 100644 --- a/cms/admin/placeholderadmin.py +++ b/cms/admin/placeholderadmin.py @@ -21,8 +21,7 @@ from django.utils.decorators import method_decorator from django.utils.encoding import force_str from django.utils.html import conditional_escape -from django.utils.translation import get_language_from_path -from django.utils.translation import gettext as _ +from django.utils.translation import get_language_from_path, gettext as _ from django.views.decorators.clickjacking import xframe_options_sameorigin from django.views.decorators.http import require_POST @@ -79,7 +78,7 @@ def _instance_overrides_method(base, instance, method_name): return unbound_method != bound_method -class FrontendEditableAdminMixin(): +class FrontendEditableAdminMixin: """ Adding ``FrontendEditableAdminMixin`` to models admin class allows to open that admin in the frontend by double-clicking on fields rendered with the ``render_model`` template @@ -120,8 +119,7 @@ def edit_field(self, request, object_id, language): 'message': force_str(_("Field %s not found")) % raw_fields } return render(request, 'admin/cms/page/plugin/error_form.html', context) - if not request.user.has_perm("{0}.change_{1}".format(self.model._meta.app_label, - self.model._meta.model_name)): + if not request.user.has_perm(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}"): context = { 'opts': opts, 'message': force_str(_("You do not have permission to edit this item")) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index 51ac222f21b..41c585d96ad 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -123,7 +123,7 @@ def response_post_save_change(self, request, obj): args=[obj.id, ], current_app=self.admin_site.name ) - return HttpResponseRedirect("{0}?reload_window".format(post_url)) + return HttpResponseRedirect(f"{post_url}?reload_window") def has_change_permission(self, request, obj=None): if obj and obj.user == request.user: diff --git a/cms/admin/useradmin.py b/cms/admin/useradmin.py index a6ee94f9c46..f2c57b8296b 100644 --- a/cms/admin/useradmin.py +++ b/cms/admin/useradmin.py @@ -25,7 +25,7 @@ admin_class = admin_instance.__class__ -class GenericCmsPermissionAdmin(): +class GenericCmsPermissionAdmin: def get_subordinates(self, user, site): raise NotImplementedError diff --git a/cms/admin/utils.py b/cms/admin/utils.py index 5a330b10af3..73a8701db8a 100644 --- a/cms/admin/utils.py +++ b/cms/admin/utils.py @@ -18,8 +18,7 @@ from django.utils.html import format_html_join from django.utils.http import urlencode from django.utils.safestring import mark_safe -from django.utils.translation import get_language -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import get_language, gettext_lazy as _ from cms.models.managers import ContentAdminManager from cms.toolbar.utils import get_object_preview_url diff --git a/cms/app_base.py b/cms/app_base.py index 08453881eb5..6a4c391ae9b 100644 --- a/cms/app_base.py +++ b/cms/app_base.py @@ -117,7 +117,7 @@ def get_urls(self, page=None, language=None, **kwargs): return self._urls -class CMSAppConfig(): +class CMSAppConfig: """ .. versionadded:: 4.0 diff --git a/cms/app_registration.py b/cms/app_registration.py index 170fc4622a9..19a7983176c 100644 --- a/cms/app_registration.py +++ b/cms/app_registration.py @@ -128,7 +128,7 @@ def configure_cms_apps(apps_with_features): and run code to register them with their config """ for app_with_feature in apps_with_features: - enabled_property = "{}_enabled".format(app_with_feature.label) + enabled_property = f"{app_with_feature.label}_enabled" configure_app = app_with_feature.cms_extension.configure_app for app_config in get_cms_config_apps(): diff --git a/cms/apphook_pool.py b/cms/apphook_pool.py index 66858605e27..68574990051 100644 --- a/cms/apphook_pool.py +++ b/cms/apphook_pool.py @@ -9,7 +9,7 @@ from cms.utils.conf import get_cms_setting -class ApphookPool(): +class ApphookPool: def __init__(self): self.apphooks = [] diff --git a/cms/appresolver.py b/cms/appresolver.py index b6496bed4ff..e3df4bba589 100644 --- a/cms/appresolver.py +++ b/cms/appresolver.py @@ -157,7 +157,7 @@ def get_app_urls(urls): if not hasattr(mod, 'urlpatterns'): raise ImproperlyConfigured( "URLConf `%s` has no urlpatterns attribute" % urlconf) - yield getattr(mod, 'urlpatterns') + yield mod.urlpatterns elif isinstance(urlconf, (list, tuple)): yield urlconf else: diff --git a/cms/cache/placeholder.py b/cms/cache/placeholder.py index 6ab0f1df11b..951b07ac75b 100644 --- a/cms/cache/placeholder.py +++ b/cms/cache/placeholder.py @@ -35,12 +35,7 @@ def _get_placeholder_cache_version_key(placeholder, lang, site_id): and per VARY header. """ prefix = get_cms_setting('CACHE_PREFIX') - key = '{prefix}|placeholder_cache_version|id:{id}|lang:{lang}|site:{site}'.format( - prefix=prefix, - id=placeholder.pk, - lang=str(lang), - site=site_id, - ) + key = f'{prefix}|placeholder_cache_version|id:{placeholder.pk}|lang:{str(lang)}|site:{site_id}' # django itself adds "version" add the end of cache-keys, e.g. ":1". # -> If `cache.set()` is for example called with `version=""`, it still adds # `:` at the end. So if we check the length for `> 250`, a length of 249 diff --git a/cms/cms_config.py b/cms/cms_config.py index d4b067c986b..91cdd4066bb 100644 --- a/cms/cms_config.py +++ b/cms/cms_config.py @@ -40,9 +40,7 @@ def configure_wizards(self, cms_config): "from cms.wizards.wizard_base.Wizard" ) elif wizard.id in self.wizards: - msg = "Wizard for model {} has already been registered".format( - wizard.get_model() - ) + msg = f"Wizard for model {wizard.get_model()} has already been registered" logger.warning(msg) else: self.wizards[wizard.id] = wizard @@ -53,7 +51,7 @@ def configure_toolbar_enabled_models(self, cms_config): for model, render_func, *grouper in cms_config.cms_toolbar_enabled_models: if model in self.toolbar_enabled_models: logger.warning( - "Model {} already registered for frontend rendering".format(model), + f"Model {model} already registered for frontend rendering", ) else: self.toolbar_enabled_models[model] = render_func diff --git a/cms/cms_menus.py b/cms/cms_menus.py index c05cda453af..adfa2259192 100644 --- a/cms/cms_menus.py +++ b/cms/cms_menus.py @@ -102,8 +102,8 @@ def get_menu_node_for_page(renderer, page, language, fallbacks=None): if page.navigation_extenders: if page.navigation_extenders in renderer.menus: extenders.append(page.navigation_extenders) - elif "{0}:{1}".format(page.navigation_extenders, page.pk) in renderer.menus: - extenders.append("{0}:{1}".format(page.navigation_extenders, page.pk)) + elif f"{page.navigation_extenders}:{page.pk}" in renderer.menus: + extenders.append(f"{page.navigation_extenders}:{page.pk}") # Is this page an apphook? If so, we need to handle the apphooks's nodes # Only run this if we have a translation in the requested language for this # object. The title cache should have been prepopulated in CMSMenu.get_nodes @@ -119,7 +119,7 @@ def get_menu_node_for_page(renderer, page, language, fallbacks=None): if hasattr(ext, "get_instances"): # CMSAttachMenus are treated a bit differently to allow them to be # able to be attached to multiple points in the navigation. - exts.append("{0}:{1}".format(ext.__name__, page.pk)) + exts.append(f"{ext.__name__}:{page.pk}") elif hasattr(ext, '__name__'): exts.append(ext.__name__) else: diff --git a/cms/cms_plugins.py b/cms/cms_plugins.py index 46f2b18dccb..ab9bab0cabd 100644 --- a/cms/cms_plugins.py +++ b/cms/cms_plugins.py @@ -7,8 +7,7 @@ ) from django.middleware.csrf import get_token from django.urls import re_path -from django.utils.translation import get_language, gettext -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import get_language, gettext, gettext_lazy as _ from cms.models import CMSPlugin, Placeholder from cms.models.aliaspluginmodel import AliasPluginModel diff --git a/cms/cms_toolbars.py b/cms/cms_toolbars.py index 167e294246e..6883d875f43 100644 --- a/cms/cms_toolbars.py +++ b/cms/cms_toolbars.py @@ -6,8 +6,6 @@ from django.urls import NoReverseMatch, Resolver404, resolve, reverse from django.utils.translation import ( gettext_lazy as _, -) -from django.utils.translation import ( override as force_language, ) @@ -23,7 +21,6 @@ from cms.toolbar_base import CMSToolbar from cms.toolbar_pool import toolbar_pool from cms.utils import get_language_from_request, page_permissions -from cms.utils.compat import DJANGO_4_2 from cms.utils.conf import get_cms_setting from cms.utils.i18n import get_language_dict, get_language_tuple from cms.utils.page_permissions import ( @@ -493,7 +490,7 @@ def change_language_menu(self): if add: add_plugins_menu = language_menu.get_or_create_menu( - '{0}-add'.format(LANGUAGE_MENU_IDENTIFIER), _('Add Translation') + f'{LANGUAGE_MENU_IDENTIFIER}-add', _('Add Translation') ) page_add_url = admin_reverse('cms_pagecontent_add') @@ -504,7 +501,7 @@ def change_language_menu(self): if remove: remove_plugins_menu = language_menu.get_or_create_menu( - '{0}-del'.format(LANGUAGE_MENU_IDENTIFIER), _('Delete Translation') + f'{LANGUAGE_MENU_IDENTIFIER}-del', _('Delete Translation') ) disabled = len(remove) == 1 for code, name in remove: @@ -516,7 +513,7 @@ def change_language_menu(self): if copy: copy_plugins_menu = language_menu.get_or_create_menu( - '{0}-copy'.format(LANGUAGE_MENU_IDENTIFIER), _('Copy all plugins') + f'{LANGUAGE_MENU_IDENTIFIER}-copy', _('Copy all plugins') ) title = _('from %s') question = _('Are you sure you want to copy all plugins from %s?') diff --git a/cms/forms/validators.py b/cms/forms/validators.py index da3ab31a612..b96ee047344 100644 --- a/cms/forms/validators.py +++ b/cms/forms/validators.py @@ -46,7 +46,7 @@ def validate_url_uniqueness(site, path, language, user_language=None, exclude_pa else: change_url = "" # Empty page has no slug if user_language: - change_url += '?language={}'.format(user_language) + change_url += f'?language={user_language}' conflict_url = '%(page_title)s' % { 'change_url': change_url, diff --git a/cms/forms/wizards.py b/cms/forms/wizards.py index 3841620346e..4bd0c4765f3 100644 --- a/cms/forms/wizards.py +++ b/cms/forms/wizards.py @@ -4,11 +4,9 @@ from django.core.exceptions import ValidationError from django.db import transaction from django.utils.text import slugify -from django.utils.translation import gettext -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext, gettext_lazy as _ -from cms.admin.forms import AddPageForm -from cms.admin.forms import SlugWidget as AdminSlugWidget +from cms.admin.forms import AddPageForm, SlugWidget as AdminSlugWidget from cms.plugin_pool import plugin_pool from cms.utils import permissions from cms.utils.conf import get_cms_setting @@ -100,7 +98,7 @@ def clean(self): if parent_node: base = parent_node.item.get_path(self._language) - path = u'%s/%s' % (base, slug) if base else slug + path = '%s/%s' % (base, slug) if base else slug else: base = '' path = slug diff --git a/cms/management/commands/startcmsproject.py b/cms/management/commands/startcmsproject.py index fbf62e13525..74cbe6fa3f9 100644 --- a/cms/management/commands/startcmsproject.py +++ b/cms/management/commands/startcmsproject.py @@ -115,7 +115,7 @@ def install_requirements(self, project): self.write_command(f'python -m pip install -r "{requirements}"') result = subprocess.run( [sys.executable, "-m", "pip", "install", "-r", requirements], - capture_output=True, + capture_output=True, check=False, ) if result.returncode: self.stderr.write(self.style.ERROR(result.stderr.decode())) @@ -132,7 +132,7 @@ def install_requirements(self, project): def run_management_command(self, commands, capture_output=False): self.write_command("python -m manage " + " ".join(commands)) - result = subprocess.run([sys.executable, "-m", "manage"] + commands, capture_output=capture_output) + result = subprocess.run([sys.executable, "-m", "manage"] + commands, capture_output=capture_output, check=False) if result.returncode: if capture_output: self.stderr.write(self.style.ERROR(result.stderr.decode())) diff --git a/cms/management/commands/subcommands/copy.py b/cms/management/commands/subcommands/copy.py index d709da50f48..c3c0b55e2ec 100644 --- a/cms/management/commands/subcommands/copy.py +++ b/cms/management/commands/subcommands/copy.py @@ -182,7 +182,7 @@ def handle(self, *args, **options): if page.is_home: new_page.set_as_homepage() self.stdout.write( - 'Copied CMS Tree from SITE_ID {0} successfully to SITE_ID {1}.\n'.format(from_site.pk, to_site.pk) + f'Copied CMS Tree from SITE_ID {from_site.pk} successfully to SITE_ID {to_site.pk}.\n' ) def get_site(self, site_id): diff --git a/cms/middleware/page.py b/cms/middleware/page.py index 0243c184cb5..71f9e784e57 100644 --- a/cms/middleware/page.py +++ b/cms/middleware/page.py @@ -18,4 +18,3 @@ def get_page(request): class CurrentPageMiddleware(MiddlewareMixin): def process_request(self, request): request.current_page = SimpleLazyObject(lambda: get_page(request)) - return None diff --git a/cms/models/contentmodels.py b/cms/models/contentmodels.py index c9163ff0e43..2b4946577b2 100644 --- a/cms/models/contentmodels.py +++ b/cms/models/contentmodels.py @@ -134,22 +134,16 @@ class Meta: app_label = 'cms' def __str__(self): - return u"%s (%s)" % (self.title, self.language) + return "%s (%s)" % (self.title, self.language) def __repr__(self): - display = '<{module}.{class_name} id={id} object at {location}>'.format( - module=self.__module__, - class_name=self.__class__.__name__, - id=self.pk, - location=hex(id(self)), - ) + display = f'<{self.__module__}.{self.__class__.__name__} id={self.pk} object at {hex(id(self))}>' return display def update(self, **data): for field, value in data.items(): setattr(self, field, value) self.save(update_fields=data.keys()) - return def save(self, **kwargs): # delete template cache diff --git a/cms/models/managers.py b/cms/models/managers.py index fbeaf3cbe37..dd32afd6d7d 100644 --- a/cms/models/managers.py +++ b/cms/models/managers.py @@ -63,10 +63,7 @@ def search(self, q, language=None, current_site_only=True): if related_query_name and not related_query_name.startswith('+'): for field in cmsplugin.search_fields: qp |= Q(**{ - 'pagecontent_set__placeholders__cmsplugin__{0}__{1}__icontains'.format( - related_query_name, - field, - ): q}) + f'pagecontent_set__placeholders__cmsplugin__{related_query_name}__{field}__icontains': q}) if language: qt &= Q(pagecontent_set__language=language) qp &= Q(cmsplugin__language=language) diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py index 923e09e4f63..54f0a944bdd 100644 --- a/cms/models/pagemodel.py +++ b/cms/models/pagemodel.py @@ -13,11 +13,7 @@ from django.utils.timezone import now from django.utils.translation import ( get_language, -) -from django.utils.translation import ( gettext_lazy as _, -) -from django.utils.translation import ( override as force_language, ) from treebeard.mp_tree import MP_Node @@ -101,7 +97,6 @@ def update(self, **data): for field, value in data.items(): setattr(self, field, value) - return def get_cached_ancestors(self): if self._has_cached_hierarchy(): @@ -216,12 +211,7 @@ def __str__(self): return force_str(title) def __repr__(self): - display = '<{module}.{class_name} id={id} object at {location}>'.format( - module=self.__module__, - class_name=self.__class__.__name__, - id=self.pk, - location=hex(id(self)), - ) + display = f'<{self.__module__}.{self.__class__.__name__} id={self.pk} object at {hex(id(self))}>' return display def _clear_node_cache(self): @@ -753,7 +743,7 @@ def get_path_for_slug(self, slug, language): if self.parent_page: base = self.parent_page.get_path(language, fallback=True) # base can be empty when the parent is a home-page - path = u'%s/%s' % (base, slug) if base else slug + path = '%s/%s' % (base, slug) if base else slug else: path = slug return path diff --git a/cms/models/placeholdermodel.py b/cms/models/placeholdermodel.py index 1c4160dc38b..0d0a79688a6 100644 --- a/cms/models/placeholdermodel.py +++ b/cms/models/placeholdermodel.py @@ -822,5 +822,5 @@ def _recalculate_plugin_positions(self, language): cursor.execute(sql, [self.pk, language]) else: raise RuntimeError( - '{} is not supported by django-cms'.format(connection.vendor) + f'{connection.vendor} is not supported by django-cms' ) diff --git a/cms/models/pluginmodel.py b/cms/models/pluginmodel.py index ad77f99f431..bcb7e44f249 100644 --- a/cms/models/pluginmodel.py +++ b/cms/models/pluginmodel.py @@ -76,7 +76,7 @@ def plugin_supports_cte(): return not (db_vendor == 'mysql' and connection.mysql_version < (8, 0)) -class BoundRenderMeta(): +class BoundRenderMeta: def __init__(self, meta): self.index = 0 self.total = 1 @@ -305,14 +305,14 @@ def get_instance_icon_src(self): Get src URL for instance's icon """ instance, plugin = self.get_plugin_instance() - return plugin.icon_src(instance) if instance else u'' + return plugin.icon_src(instance) if instance else '' def get_instance_icon_alt(self): """ Get alt text for instance's icon """ instance, plugin = self.get_plugin_instance() - return force_str(plugin.icon_alt(instance)) if instance else u'' + return force_str(plugin.icon_alt(instance)) if instance else '' def update(self, refresh=False, **fields): CMSPlugin.objects.filter(pk=self.pk).update(**fields) diff --git a/cms/page_rendering.py b/cms/page_rendering.py index 079d7208cf4..e4d11881ab9 100644 --- a/cms/page_rendering.py +++ b/cms/page_rendering.py @@ -1,7 +1,7 @@ from django.conf import settings from django.http import Http404, HttpResponseRedirect from django.template.response import TemplateResponse -from django.urls import Resolver404, get_resolver, resolve, reverse +from django.urls import Resolver404, resolve, reverse from cms import __version__, constants from cms.cache.page import set_page_cache diff --git a/cms/plugin_base.py b/cms/plugin_base.py index 8ecfd3011ab..59af8622898 100644 --- a/cms/plugin_base.py +++ b/cms/plugin_base.py @@ -11,8 +11,7 @@ from django.shortcuts import render from django.utils.encoding import force_str, smart_str from django.utils.html import escapejs -from django.utils.translation import gettext -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext, gettext_lazy as _ from cms import operations from cms.exceptions import SubClassNeededError @@ -702,7 +701,7 @@ def __str__(self): return self.name -class PluginMenuItem(): +class PluginMenuItem: """ Creates an item in the plugin / placeholder menu diff --git a/cms/plugin_pool.py b/cms/plugin_pool.py index 07c25b3965f..60f1a98844d 100644 --- a/cms/plugin_pool.py +++ b/cms/plugin_pool.py @@ -15,7 +15,7 @@ from cms.utils.helpers import normalize_name -class PluginPool(): +class PluginPool: def __init__(self): self.plugins = {} diff --git a/cms/plugin_rendering.py b/cms/plugin_rendering.py index e040ff4e38e..1d5ff431ada 100644 --- a/cms/plugin_rendering.py +++ b/cms/plugin_rendering.py @@ -43,7 +43,7 @@ def _unpack_plugins(parent_plugin): return found_plugins -class RenderedPlaceholder(): +class RenderedPlaceholder: __slots__ = ( 'language', 'site_id', @@ -75,7 +75,7 @@ def __hash__(self): return hash(self.placeholder) -class BaseRenderer(): +class BaseRenderer: load_structure = False placeholder_edit_template = '' diff --git a/cms/signals/log_entries.py b/cms/signals/log_entries.py index 4a7b2551ed9..563409ebf9b 100644 --- a/cms/signals/log_entries.py +++ b/cms/signals/log_entries.py @@ -88,7 +88,7 @@ def _is_valid_page_instance(page): """ Check if the supplied object is a valid Page / PageType object """ - return isinstance(page, Page) or isinstance(page, PageType) + return isinstance(page, (Page, PageType)) def log_page_operations(sender, **kwargs): diff --git a/cms/signals/permissions.py b/cms/signals/permissions.py index 6bf90642d31..266453e84a5 100644 --- a/cms/signals/permissions.py +++ b/cms/signals/permissions.py @@ -51,13 +51,13 @@ def pre_delete_user(instance, **kwargs): def pre_save_group(instance, raw, **kwargs): if instance.pk: - user_set = getattr(instance, 'user_set') + user_set = instance.user_set for user in user_set.all(): clear_user_permission_cache(user) def pre_delete_group(instance, **kwargs): - user_set = getattr(instance, 'user_set') + user_set = instance.user_set for user in user_set.all(): clear_user_permission_cache(user) @@ -66,7 +66,7 @@ def _clear_users_permissions(instance): if instance.user: clear_user_permission_cache(instance.user) if instance.group: - user_set = getattr(instance.group, 'user_set') + user_set = instance.group.user_set for user in user_set.all(): clear_user_permission_cache(user) diff --git a/cms/sitemaps/cms_sitemap.py b/cms/sitemaps/cms_sitemap.py index a10c6b83ae9..b76a9f26ba7 100644 --- a/cms/sitemaps/cms_sitemap.py +++ b/cms/sitemaps/cms_sitemap.py @@ -1,4 +1,3 @@ -from collections import defaultdict from django.contrib.sitemaps import Sitemap from django.db.models import OuterRef, Q, Subquery diff --git a/cms/templates.py b/cms/templates.py index 0c0cabfbdee..29d00ce1779 100644 --- a/cms/templates.py +++ b/cms/templates.py @@ -2,7 +2,7 @@ from django.utils.functional import cached_property -class TemplatesCache(): +class TemplatesCache: def __init__(self): self._cached_templates = {} diff --git a/cms/templatetags/cms_admin.py b/cms/templatetags/cms_admin.py index f68f1511d07..c14e76be102 100644 --- a/cms/templatetags/cms_admin.py +++ b/cms/templatetags/cms_admin.py @@ -9,8 +9,7 @@ from django.utils.encoding import force_str from django.utils.html import format_html from django.utils.safestring import mark_safe -from django.utils.translation import get_language -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import get_language, gettext_lazy as _ from cms.models import Page from cms.models.contentmodels import PageContent @@ -20,7 +19,7 @@ register = template.Library() -CMS_ADMIN_ICON_BASE = "{}admin/img/".format(settings.STATIC_URL) +CMS_ADMIN_ICON_BASE = f"{settings.STATIC_URL}admin/img/" class GetAdminUrlForLanguage(AsTag): @@ -40,7 +39,7 @@ def get_value(self, context, page, language): if page_content: return admin_reverse('cms_pagecontent_change', args=[page_content.pk]) admin_url = admin_reverse('cms_pagecontent_add') - admin_url += '?cms_page={}&language={}'.format(page.pk, language) + admin_url += f'?cms_page={page.pk}&language={language}' return admin_url diff --git a/cms/templatetags/cms_js_tags.py b/cms/templatetags/cms_js_tags.py index eb647367a5c..3b27739282e 100644 --- a/cms/templatetags/cms_js_tags.py +++ b/cms/templatetags/cms_js_tags.py @@ -52,7 +52,7 @@ def render_plugin_init_js(context, plugin): plugin_js = renderer.get_plugin_toolbar_js(plugin) # Add the toolbar javascript for this plugin to the # sekizai "js" namespace. - context[get_varname()]['js'].append(''.format(plugin_js)) + context[get_varname()]['js'].append(f'') @register.tag(name="javascript_string") diff --git a/cms/templatetags/cms_tags.py b/cms/templatetags/cms_tags.py index f9a01cb6fb4..792bbed898e 100644 --- a/cms/templatetags/cms_tags.py +++ b/cms/templatetags/cms_tags.py @@ -24,12 +24,8 @@ from django.utils.http import urlencode from django.utils.translation import ( get_language, - override, -) -from django.utils.translation import ( gettext_lazy as _, -) -from django.utils.translation import ( + override, override as force_language, ) from sekizai.templatetags.sekizai_tags import RenderBlock, SekizaiParser @@ -39,10 +35,8 @@ from cms.models import ( CMSPlugin, Page, - StaticPlaceholder, -) -from cms.models import ( Placeholder as PlaceholderModel, + StaticPlaceholder, ) from cms.plugin_pool import plugin_pool from cms.toolbar.utils import get_toolbar_from_request @@ -507,17 +501,17 @@ def _get_editable_context(self, context, instance, language, edit_fields, with force_language(lang): extra_context = {} if edit_fields == 'changelist': - instance.get_plugin_name = u"%s %s list" % (smart_str(_('Edit')), smart_str(opts.verbose_name)) + instance.get_plugin_name = "%s %s list" % (smart_str(_('Edit')), smart_str(opts.verbose_name)) extra_context['attribute_name'] = 'changelist' elif editmode: - instance.get_plugin_name = u"%s %s" % (smart_str(_('Edit')), smart_str(opts.verbose_name)) + instance.get_plugin_name = "%s %s" % (smart_str(_('Edit')), smart_str(opts.verbose_name)) if not context.get('attribute_name', None): # Make sure CMS.Plugin object will not clash in the frontend. extra_context['attribute_name'] = '-'.join( edit_fields ) if not isinstance('edit_fields', str) else edit_fields else: - instance.get_plugin_name = u"%s %s" % (smart_str(_('Add')), smart_str(opts.verbose_name)) + instance.get_plugin_name = "%s %s" % (smart_str(_('Add')), smart_str(opts.verbose_name)) extra_context['attribute_name'] = 'add' extra_context['instance'] = instance extra_context['generic'] = opts diff --git a/cms/test_utils/fixtures/fakemlng.py b/cms/test_utils/fixtures/fakemlng.py index 8041f6323dc..771296ea8f3 100644 --- a/cms/test_utils/fixtures/fakemlng.py +++ b/cms/test_utils/fixtures/fakemlng.py @@ -2,7 +2,7 @@ from cms.test_utils.project.fakemlng.models import MainModel, Translations -class FakemlngFixtures(): +class FakemlngFixtures: def create_fixtures(self): main = MainModel.objects.create() en = Translations.objects.create(master=main, language_code='en') diff --git a/cms/test_utils/fixtures/menus.py b/cms/test_utils/fixtures/menus.py index d74a7476804..bace2566252 100644 --- a/cms/test_utils/fixtures/menus.py +++ b/cms/test_utils/fixtures/menus.py @@ -1,7 +1,7 @@ from cms.api import create_page -class MenusFixture(): +class MenusFixture: def create_fixtures(self): """ Tree from fixture: @@ -31,7 +31,7 @@ def create_fixtures(self): create_page('P8', in_navigation=True, parent=p6, **defaults) -class ExtendedMenusFixture(): +class ExtendedMenusFixture: def create_fixtures(self): """ Tree from fixture: @@ -67,7 +67,7 @@ def create_fixtures(self): create_page('P11', in_navigation=True, parent=p10, **defaults) -class SubMenusFixture(): +class SubMenusFixture: def create_fixtures(self): """ Tree from fixture: @@ -97,7 +97,7 @@ def create_fixtures(self): create_page('P8', in_navigation=True, parent=p6, **defaults) -class SoftrootFixture(): +class SoftrootFixture: def create_fixtures(self): """ top diff --git a/cms/test_utils/fixtures/navextenders.py b/cms/test_utils/fixtures/navextenders.py index eea330e59bd..8e3a98eab31 100644 --- a/cms/test_utils/fixtures/navextenders.py +++ b/cms/test_utils/fixtures/navextenders.py @@ -2,7 +2,7 @@ from cms.models.pagemodel import Page -class NavextendersFixture(): +class NavextendersFixture: def create_fixtures(self): """ Tree from fixture: diff --git a/cms/test_utils/fixtures/templatetags.py b/cms/test_utils/fixtures/templatetags.py index db02e0de6f3..cb04bdd91af 100644 --- a/cms/test_utils/fixtures/templatetags.py +++ b/cms/test_utils/fixtures/templatetags.py @@ -1,7 +1,7 @@ from cms.api import create_page, create_page_content -class TwoPagesFixture(): +class TwoPagesFixture: def create_fixtures(self): defaults = { 'template': 'nav_playground.html', diff --git a/cms/test_utils/project/brokenpluginapp/cms_plugins.py b/cms/test_utils/project/brokenpluginapp/cms_plugins.py index 23e4b229354..9a8dd95fefc 100644 --- a/cms/test_utils/project/brokenpluginapp/cms_plugins.py +++ b/cms/test_utils/project/brokenpluginapp/cms_plugins.py @@ -1 +1 @@ -import nonexistingmodule # nopyflakes +import nonexistingmodule # noqa: F401 diff --git a/cms/test_utils/project/bunch_of_plugins/models.py b/cms/test_utils/project/bunch_of_plugins/models.py index e1647d11978..66a55e81d6f 100644 --- a/cms/test_utils/project/bunch_of_plugins/models.py +++ b/cms/test_utils/project/bunch_of_plugins/models.py @@ -5,11 +5,11 @@ class TestPlugin1(CMSPlugin): pass -class LeftMixin(): +class LeftMixin: pass -class RightMixin(): +class RightMixin: pass diff --git a/cms/test_utils/project/mti_pluginapp/models.py b/cms/test_utils/project/mti_pluginapp/models.py index 146bda8f460..fd89cf4acf2 100644 --- a/cms/test_utils/project/mti_pluginapp/models.py +++ b/cms/test_utils/project/mti_pluginapp/models.py @@ -3,7 +3,7 @@ from cms.models import CMSPlugin -class SomeParent(): +class SomeParent: pass diff --git a/cms/test_utils/project/objectpermissionsapp/backends.py b/cms/test_utils/project/objectpermissionsapp/backends.py index b29d1f5d2c1..72e70de6886 100644 --- a/cms/test_utils/project/objectpermissionsapp/backends.py +++ b/cms/test_utils/project/objectpermissionsapp/backends.py @@ -3,7 +3,7 @@ from django.db.models import Model -class ObjectPermissionBackend(): +class ObjectPermissionBackend: def has_perm(self, user_obj, perm, obj=None): if user_obj and user_obj.is_superuser: return True diff --git a/cms/test_utils/project/placeholderapp/cms_plugins.py b/cms/test_utils/project/placeholderapp/cms_plugins.py index 54cc593cbb1..26df106f1ce 100644 --- a/cms/test_utils/project/placeholderapp/cms_plugins.py +++ b/cms/test_utils/project/placeholderapp/cms_plugins.py @@ -13,7 +13,7 @@ def render(self, context, instance, placeholder): return context def icon_src(self, instance): - return settings.STATIC_URL + u"cms/img/icons/plugins/image.png" + return settings.STATIC_URL + "cms/img/icons/plugins/image.png" @classmethod def get_extra_placeholder_menu_items(cls, request, placeholder): diff --git a/cms/test_utils/project/placeholderapp/models.py b/cms/test_utils/project/placeholderapp/models.py index 3c9380cad46..dbfd4bba5d9 100644 --- a/cms/test_utils/project/placeholderapp/models.py +++ b/cms/test_utils/project/placeholderapp/models.py @@ -15,10 +15,10 @@ def dynamic_placeholder_2(instance): class Example1(models.Model): - char_1 = models.CharField(u'char_1', max_length=255) - char_2 = models.CharField(u'char_2', max_length=255) - char_3 = models.CharField(u'char_3', max_length=255) - char_4 = models.CharField(u'char_4', max_length=255) + char_1 = models.CharField('char_1', max_length=255) + char_2 = models.CharField('char_2', max_length=255) + char_3 = models.CharField('char_3', max_length=255) + char_4 = models.CharField('char_4', max_length=255) date_field = models.DateField(null=True) placeholder = PlaceholderField('placeholder') publish = models.BooleanField(default=True) @@ -52,24 +52,24 @@ def dynamic_url(self, request): class TwoPlaceholderExample(models.Model): - char_1 = models.CharField(u'char_1', max_length=255) - char_2 = models.CharField(u'char_2', max_length=255) - char_3 = models.CharField(u'char_3', max_length=255) - char_4 = models.CharField(u'char_4', max_length=255) + char_1 = models.CharField('char_1', max_length=255) + char_2 = models.CharField('char_2', max_length=255) + char_3 = models.CharField('char_3', max_length=255) + char_4 = models.CharField('char_4', max_length=255) placeholder_1 = PlaceholderField('placeholder_1', related_name='p1') placeholder_2 = PlaceholderField('placeholder_2', related_name='p2') class DynamicPlaceholderSlotExample(models.Model): - char_1 = models.CharField(u'char_1', max_length=255) - char_2 = models.CharField(u'char_2', max_length=255) + char_1 = models.CharField('char_1', max_length=255) + char_2 = models.CharField('char_2', max_length=255) placeholder_1 = PlaceholderField(dynamic_placeholder_1, related_name='dynamic_pl_1') placeholder_2 = PlaceholderField(dynamic_placeholder_2, related_name='dynamic_pl_2') class CharPksExample(models.Model): - char_1 = models.CharField(u'char_1', max_length=255) - slug = models.SlugField(u'char_1', max_length=255, primary_key=True) + char_1 = models.CharField('char_1', max_length=255) + slug = models.SlugField('char_1', max_length=255, primary_key=True) placeholder_1 = PlaceholderField('placeholder_1', related_name='charpk_p1') def __str__(self): diff --git a/cms/test_utils/project/pluginapp/plugins/link/models.py b/cms/test_utils/project/pluginapp/plugins/link/models.py index 546b39e0d46..ac0df3dfe61 100644 --- a/cms/test_utils/project/pluginapp/plugins/link/models.py +++ b/cms/test_utils/project/pluginapp/plugins/link/models.py @@ -17,7 +17,7 @@ def __str__(self): return self.name or str(self.pk) def get_short_description(self): - return '{} ({})'.format(self.name, self.get_link()) + return f'{self.name} ({self.get_link()})' def get_link(self): return self.external_link diff --git a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py index 58d8105b646..8dc3c8013ad 100644 --- a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py +++ b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py @@ -8,7 +8,7 @@ class Article(models.Model): section = models.ForeignKey('Section', on_delete=models.CASCADE) def __str__(self): - return u"%s -- %s" % (self.title, self.section) + return "%s -- %s" % (self.title, self.section) class Section(models.Model): diff --git a/cms/test_utils/project/pluginapp/plugins/multicolumn/models.py b/cms/test_utils/project/pluginapp/plugins/multicolumn/models.py index 7c62b74c88e..52c31878b4d 100644 --- a/cms/test_utils/project/pluginapp/plugins/multicolumn/models.py +++ b/cms/test_utils/project/pluginapp/plugins/multicolumn/models.py @@ -8,4 +8,4 @@ class MultiColumns(CMSPlugin): def __str__(self): plugins = self.child_plugin_instances or [] - return "{} columns".format(len(plugins)) + return f"{len(plugins)} columns" diff --git a/cms/test_utils/project/pluginapp/plugins/style/models.py b/cms/test_utils/project/pluginapp/plugins/style/models.py index 65054595054..668c68d60be 100644 --- a/cms/test_utils/project/pluginapp/plugins/style/models.py +++ b/cms/test_utils/project/pluginapp/plugins/style/models.py @@ -52,7 +52,7 @@ def get_short_description(self): if self.label: display.append(self.label) if self.tag_type: - display.append('<{0}>'.format(self.tag_type)) + display.append(f'<{self.tag_type}>') if self.class_name: classes.append(self.class_name) if self.additional_classes: diff --git a/cms/test_utils/project/sampleapp/views.py b/cms/test_utils/project/sampleapp/views.py index 68194a7b095..65c40171e92 100644 --- a/cms/test_utils/project/sampleapp/views.py +++ b/cms/test_utils/project/sampleapp/views.py @@ -58,7 +58,7 @@ def notfound(request): raise Http404 -class ClassView(): +class ClassView: def __call__(self, request, *args, **kwargs): context = {'content': 'plain text'} return render(request, "sampleapp/plain.html", context) diff --git a/cms/test_utils/runners.py b/cms/test_utils/runners.py index 14675054618..2026e157243 100644 --- a/cms/test_utils/runners.py +++ b/cms/test_utils/runners.py @@ -38,4 +38,4 @@ def teardown_test_environment(self, **kwargs): )[:10] print("Ten slowest tests:") for func_name, timing in by_time: - print("{t:.2f}s {f}".format(f=func_name, t=timing)) + print(f"{timing:.2f}s {func_name}") diff --git a/cms/test_utils/testcases.py b/cms/test_utils/testcases.py index ea3bbc9777a..44ced9324c8 100644 --- a/cms/test_utils/testcases.py +++ b/cms/test_utils/testcases.py @@ -420,7 +420,7 @@ def get_request(self, path=None, language=None, post_data=None, enforce_csrf_che else: request.current_page = None - class MockStorage(): + class MockStorage: def __len__(self): return 0 @@ -498,7 +498,7 @@ def apphook_clear(self): def get_admin_url(self, model, action, *args): opts = model._meta - url_name = "{}_{}_{}".format(opts.app_label, opts.model_name, action) + url_name = f"{opts.app_label}_{opts.model_name}_{action}" return admin_reverse(url_name, args=args) def get_permissions_test_page(self): @@ -558,7 +558,7 @@ def get_add_plugin_uri(self, placeholder, plugin_type, language='en', parent=Non if placeholder.page: path = placeholder.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' if position is None: position = placeholder.get_next_plugin_position(language, parent=parent, insert_order='last') @@ -582,7 +582,7 @@ def get_change_plugin_uri(self, plugin, language=None): if plugin.page: path = plugin.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_edit_plugin', args=(plugin.pk,)) endpoint += '?' + urlencode({'cms_path': path}) @@ -594,7 +594,7 @@ def get_move_plugin_uri(self, plugin, language=None): if plugin.page: path = plugin.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_move_plugin') endpoint += '?' + urlencode({'cms_path': path}) @@ -606,7 +606,7 @@ def get_copy_plugin_uri(self, plugin, language=None): if plugin.page: path = plugin.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_copy_plugins') endpoint += '?' + urlencode({'cms_path': path}) @@ -618,7 +618,7 @@ def get_copy_placeholder_uri(self, placeholder, language=None): if placeholder.page: path = placeholder.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_copy_plugins') endpoint += '?' + urlencode({'cms_path': path}) @@ -630,7 +630,7 @@ def get_delete_plugin_uri(self, plugin, language=None): if plugin.page: path = plugin.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_delete_plugin', args=(plugin.pk,)) endpoint += '?' + urlencode({'cms_path': path}) @@ -642,7 +642,7 @@ def get_clear_placeholder_url(self, placeholder, language=None): if placeholder.page: path = placeholder.page.get_absolute_url(language) else: - path = '/{}/'.format(language) + path = f'/{language}/' endpoint = admin_reverse('cms_placeholder_clear_placeholder', args=(placeholder.pk,)) endpoint += '?' + urlencode({ diff --git a/cms/test_utils/util/context_managers.py b/cms/test_utils/util/context_managers.py index 5e5792f0c7f..a05aede24ad 100644 --- a/cms/test_utils/util/context_managers.py +++ b/cms/test_utils/util/context_managers.py @@ -14,7 +14,7 @@ class NULL: pass -class StdOverride(): +class StdOverride: def __init__(self, std='out', buffer=None): self.std = std self.buffer = buffer or StringIO() @@ -42,7 +42,7 @@ def __init__(self, buffer=None): super().__init__('out', buffer) -class LanguageOverride(): +class LanguageOverride: def __init__(self, language): self.newlang = language @@ -80,7 +80,7 @@ def __exit__(self, exc, value, tb): self.cleanup() -class UserLoginContext(): +class UserLoginContext: def __init__(self, testcase, user): self.testcase = testcase self.user = user @@ -99,7 +99,7 @@ def __exit__(self, exc, value, tb): self.testcase.client.logout() -class ChangeModel(): +class ChangeModel: """ Changes attributes on a model while within the context. @@ -164,7 +164,7 @@ def signal_tester(*signals): signal.disconnect(env) -class SignalTester(): +class SignalTester: def __init__(self): self.call_count = 0 diff --git a/cms/test_utils/util/mock.py b/cms/test_utils/util/mock.py index 326095aecfa..a97f2e016b4 100644 --- a/cms/test_utils/util/mock.py +++ b/cms/test_utils/util/mock.py @@ -1,4 +1,4 @@ -class AttributeObject(): +class AttributeObject: """ mock = AttributeObject(hello='world') mock.hello # 'world' diff --git a/cms/test_utils/util/static_analysis.py b/cms/test_utils/util/static_analysis.py index 1a326c75346..8eabc89b0fa 100644 --- a/cms/test_utils/util/static_analysis.py +++ b/cms/test_utils/util/static_analysis.py @@ -7,7 +7,7 @@ def _pyflakes_report_with_nopyflakes(self, messageClass, node, *args, **kwargs): - with open(self.filename, 'r') as code: + with open(self.filename) as code: if code.readlines()[node.lineno - 1].strip().endswith('# nopyflakes'): return self.messages.append(messageClass(self.filename, node, *args, **kwargs)) diff --git a/cms/tests/test_admin.py b/cms/tests/test_admin.py index 7f8254dfabb..de1308c297a 100644 --- a/cms/tests/test_admin.py +++ b/cms/tests/test_admin.py @@ -1,5 +1,4 @@ import json -from unittest import skipIf from django.contrib import admin from django.contrib.admin.sites import site diff --git a/cms/tests/test_app_registration.py b/cms/tests/test_app_registration.py index d0599f3cd6e..d30c336a71d 100644 --- a/cms/tests/test_app_registration.py +++ b/cms/tests/test_app_registration.py @@ -1,9 +1,9 @@ from importlib import import_module +from unittest.mock import Mock, patch from django.apps import AppConfig, apps from django.core.exceptions import ImproperlyConfigured from django.test import override_settings -from mock import Mock, patch from cms import app_registration from cms.apps import CMSConfig diff --git a/cms/tests/test_cache.py b/cms/tests/test_cache.py index 1380f69f62b..1271047eed8 100644 --- a/cms/tests/test_cache.py +++ b/cms/tests/test_cache.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import time from django.conf import settings @@ -41,30 +39,32 @@ class CacheTestCase(CMSTestCase): def tearDown(self): from django.core.cache import cache - super(CacheTestCase, self).tearDown() + + super().tearDown() cache.clear() def setUp(self): from django.core.cache import cache - super(CacheTestCase, self).setUp() + + super().setUp() cache.clear() def test_cache_placeholder(self): template = "{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}" - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() - placeholder_en = page1.get_placeholders('en').filter(slot="body")[0] - placeholder_de = page1.get_placeholders('en').filter(slot="body")[0] - add_plugin(placeholder_en, "TextPlugin", 'en', body="English") - add_plugin(placeholder_de, "TextPlugin", 'de', body="Deutsch") + placeholder_en = page1.get_placeholders("en").filter(slot="body")[0] + placeholder_de = page1.get_placeholders("en").filter(slot="body")[0] + add_plugin(placeholder_en, "TextPlugin", "en", body="English") + add_plugin(placeholder_de, "TextPlugin", "de", body="Deutsch") request = self.get_request(page1_url) request.current_page = Page.objects.get(pk=page1.pk) request.toolbar = CMSToolbar(request) with self.assertNumQueries(FuzzyInt(5, 9)): self.render_template_obj(template, {}, request) request = self.get_request(page1_url) - request.session['cms_edit'] = True + request.session["cms_edit"] = True request.current_page = Page.objects.get(pk=page1.pk) request.toolbar = CMSToolbar(request) template = "{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}" @@ -73,7 +73,7 @@ def test_cache_placeholder(self): # toolbar with self.login_user_context(self.get_superuser()): request = self.get_request(page1_url) - request.session['cms_edit'] = True + request.session["cms_edit"] = True request.current_page = Page.objects.get(pk=page1.pk) request.toolbar = CMSToolbar(request) request.toolbar.show_toolbar = True @@ -81,8 +81,8 @@ def test_cache_placeholder(self): with self.assertNumQueries(5): self.render_template_obj(template, {}, request) exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware' + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = dict( CMS_PAGE_CACHE=False, @@ -94,34 +94,34 @@ def test_cache_placeholder(self): with self.assertNumQueries(FuzzyInt(5, 13)): self.client.get(page1_url) - overrides['CMS_PLACEHOLDER_CACHE'] = False + overrides["CMS_PLACEHOLDER_CACHE"] = False with self.settings(**overrides): with self.assertNumQueries(FuzzyInt(7, 17)): self.client.get(page1_url) def test_no_cache_plugin(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() - placeholder1 = page1.get_placeholders('en').filter(slot='body')[0] - placeholder2 = page1.get_placeholders('en').filter(slot='right-column')[0] + placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] + placeholder2 = page1.get_placeholders("en").filter(slot="right-column")[0] try: plugin_pool.register_plugin(NoCachePlugin) except PluginAlreadyRegistered: pass - add_plugin(placeholder1, 'TextPlugin', 'en', body="English") - add_plugin(placeholder2, 'TextPlugin', 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") template = "{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}" # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware' + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): # Request the page without the 'no-cache' plugin @@ -154,7 +154,7 @@ def test_no_cache_plugin(self): # Add the 'no-cache' plugin with self.login_user_context(self.get_superuser()): - endpoint = self.get_add_plugin_uri(placeholder1, 'NoCachePlugin') + endpoint = self.get_add_plugin_uri(placeholder1, "NoCachePlugin") self.client.post(endpoint, {}) request = self.get_request(page1_url) request.current_page = Page.objects.get(pk=page1.pk) @@ -163,8 +163,8 @@ def test_no_cache_plugin(self): output = self.render_template_obj(template, {}, request) with self.assertNumQueries(FuzzyInt(13, 24)): response = self.client.get(page1_url) - self.assertTrue("no-cache" in response['Cache-Control']) - resp1 = response.content.decode('utf8').split("$$$")[1] + self.assertTrue("no-cache" in response["Cache-Control"]) + resp1 = response.content.decode("utf8").split("$$$")[1] request = self.get_request(page1_url) request.current_page = Page.objects.get(pk=page1.pk) @@ -174,33 +174,33 @@ def test_no_cache_plugin(self): with self.settings(CMS_PAGE_CACHE=False): with self.assertNumQueries(FuzzyInt(8, 16)): response = self.client.get(page1_url) - resp2 = response.content.decode('utf8').split("$$$")[1] + resp2 = response.content.decode("utf8").split("$$$")[1] self.assertNotEqual(output, output2) self.assertNotEqual(resp1, resp2) plugin_pool.unregister_plugin(NoCachePlugin) def test_timedelta_cache_plugin(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] placeholder2 = page1.get_placeholders("en").filter(slot="right-column")[0] plugin_pool.register_plugin(TimeDeltaCacheExpirationPlugin) - add_plugin(placeholder1, "TextPlugin", 'en', body="English") - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") # Add *TimeDeltaCacheExpirationPlugin, expires in 45s. - add_plugin(placeholder1, "TimeDeltaCacheExpirationPlugin", 'en') + add_plugin(placeholder1, "TimeDeltaCacheExpirationPlugin", "en") # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): request = self.get_request(page1.get_absolute_url()) @@ -209,12 +209,14 @@ def test_timedelta_cache_plugin(self): with self.assertNumQueries(FuzzyInt(14, 25)): # was 14, 24 response = self.client.get(page1.get_absolute_url()) - self.assertTrue('max-age=45' in response['Cache-Control'], response['Cache-Control']) + self.assertTrue( + "max-age=45" in response["Cache-Control"], response["Cache-Control"] + ) plugin_pool.unregister_plugin(TimeDeltaCacheExpirationPlugin) def test_datetime_cache_plugin(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] @@ -223,22 +225,22 @@ def test_datetime_cache_plugin(self): plugin_pool.register_plugin(DateTimeCacheExpirationPlugin) except PluginAlreadyRegistered: pass - add_plugin(placeholder1, "TextPlugin", 'en', body="English") - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") # Add *CacheExpirationPlugins, one expires in 50s, the other in 40s. # The page should expire in the least of these, or 40s. - add_plugin(placeholder1, "DateTimeCacheExpirationPlugin", 'en') + add_plugin(placeholder1, "DateTimeCacheExpirationPlugin", "en") # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): request = self.get_request(page1_url) @@ -246,40 +248,44 @@ def test_datetime_cache_plugin(self): request.toolbar = CMSToolbar(request) with self.assertNumQueries(FuzzyInt(14, 25)): # was 14, 24 response = self.client.get(page1_url) - self.assertTrue('max-age=40' in response['Cache-Control'], response['Cache-Control']) + self.assertTrue( + "max-age=40" in response["Cache-Control"], response["Cache-Control"] + ) plugin_pool.unregister_plugin(DateTimeCacheExpirationPlugin) def TTLCacheExpirationPlugin(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] placeholder2 = page1.get_placeholders("en").filter(slot="right-column")[0] plugin_pool.register_plugin(TTLCacheExpirationPlugin) - add_plugin(placeholder1, "TextPlugin", 'en', body="English") - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") # Add *CacheExpirationPlugins, one expires in 50s, the other in 40s. # The page should expire in the least of these, or 40s. - add_plugin(placeholder1, "TTLCacheExpirationPlugin", 'en') + add_plugin(placeholder1, "TTLCacheExpirationPlugin", "en") # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): - request = self.get_request('/en/') + request = self.get_request("/en/") request.current_page = Page.objects.get(pk=page1.pk) request.toolbar = CMSToolbar(request) with self.assertNumQueries(FuzzyInt(14, 25)): # was 14, 24 - response = self.client.get('/en/') - self.assertTrue('max-age=50' in response['Cache-Control'], response['Cache-Control']) + response = self.client.get("/en/") + self.assertTrue( + "max-age=50" in response["Cache-Control"], response["Cache-Control"] + ) plugin_pool.unregister_plugin(TTLCacheExpirationPlugin) @@ -288,7 +294,7 @@ def test_expiration_cache_plugins(self): Tests that when used in combination, the page is cached to the shortest TTL. """ - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] @@ -302,23 +308,23 @@ def test_expiration_cache_plugins(self): plugin_pool.register_plugin(NoCachePlugin) except PluginAlreadyRegistered: pass - add_plugin(placeholder1, "TextPlugin", 'en', body="English") - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") # Add *CacheExpirationPlugins, one expires in 50s, the other in 40s. # The page should expire in the least of these, or 40s. - add_plugin(placeholder1, "TTLCacheExpirationPlugin", 'en') - add_plugin(placeholder2, "DateTimeCacheExpirationPlugin", 'en') + add_plugin(placeholder1, "TTLCacheExpirationPlugin", "en") + add_plugin(placeholder2, "DateTimeCacheExpirationPlugin", "en") # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): request = self.get_request(page1_url) @@ -326,10 +332,12 @@ def test_expiration_cache_plugins(self): request.toolbar = CMSToolbar(request) with self.assertNumQueries(FuzzyInt(14, 26)): response = self.client.get(page1_url) - resp1 = response.content.decode('utf8').split("$$$")[1] - self.assertTrue('max-age=40' in response['Cache-Control'], response['Cache-Control']) # noqa - cache_control1 = response['Cache-Control'] - expires1 = response['Expires'] + resp1 = response.content.decode("utf8").split("$$$")[1] + self.assertTrue( + "max-age=40" in response["Cache-Control"], response["Cache-Control"] + ) # noqa + cache_control1 = response["Cache-Control"] + expires1 = response["Expires"] time.sleep(1) # This ensures that the cache has aged measurably @@ -339,40 +347,40 @@ def test_expiration_cache_plugins(self): request.toolbar = CMSToolbar(request) with self.assertNumQueries(0): response = self.client.get(page1_url) - resp2 = response.content.decode('utf8').split("$$$")[1] + resp2 = response.content.decode("utf8").split("$$$")[1] # Content will be the same self.assertEqual(resp2, resp1) # Cache-Control will be different because the cache has aged - self.assertNotEqual(response['Cache-Control'], cache_control1) + self.assertNotEqual(response["Cache-Control"], cache_control1) # However, the Expires timestamp will be the same - self.assertEqual(response['Expires'], expires1) + self.assertEqual(response["Expires"], expires1) plugin_pool.unregister_plugin(TTLCacheExpirationPlugin) plugin_pool.unregister_plugin(DateTimeCacheExpirationPlugin) plugin_pool.unregister_plugin(NoCachePlugin) def test_dual_legacy_cache_plugins(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] placeholder2 = page1.get_placeholders("en").filter(slot="right-column")[0] plugin_pool.register_plugin(LegacyCachePlugin) - add_plugin(placeholder1, "TextPlugin", 'en', body="English") - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "TextPlugin", "en", body="English") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") # Adds a no-cache plugin. In older versions of the CMS, this would # prevent the page from caching in, but since this plugin also defines # get_cache_expiration() it is ignored. - add_plugin(placeholder1, "LegacyCachePlugin", 'en') + add_plugin(placeholder1, "LegacyCachePlugin", "en") # Ensure that we're testing in an environment WITHOUT the MW cache, as # we are testing the internal page cache, not the MW cache. exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.CacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.CacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): request = self.get_request(page1_url) @@ -380,36 +388,36 @@ def test_dual_legacy_cache_plugins(self): request.toolbar = CMSToolbar(request) with self.assertNumQueries(FuzzyInt(14, 25)): response = self.client.get(page1_url) - self.assertTrue('no-cache' not in response['Cache-Control']) + self.assertTrue("no-cache" not in response["Cache-Control"]) plugin_pool.unregister_plugin(LegacyCachePlugin) def test_cache_page(self): # Ensure that we're testing in an environment WITHOUT the MW cache... exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware' + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): # Silly to do these tests if this setting isn't True - page_cache_setting = get_cms_setting('PAGE_CACHE') + page_cache_setting = get_cms_setting("PAGE_CACHE") self.assertTrue(page_cache_setting) # Create a test page - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() # Add some content placeholder = page1.get_placeholders("en").filter(slot="body")[0] - add_plugin(placeholder, "TextPlugin", 'en', body="English") - add_plugin(placeholder, "TextPlugin", 'de', body="Deutsch") + add_plugin(placeholder, "TextPlugin", "en", body="English") + add_plugin(placeholder, "TextPlugin", "de", body="Deutsch") # Create a request object - request = self.get_request(page1_url, 'en') + request = self.get_request(page1_url, "en") # Ensure that user is NOT authenticated self.assertFalse(request.user.is_authenticated) @@ -448,15 +456,15 @@ def test_no_page_cache_on_toolbar_edit(self): with self.settings(CMS_PAGE_CACHE=True): superuser = self.get_superuser() # Create a test page - page = create_page('test page 1', 'nav_playground.html', 'en') + page = create_page("test page 1", "nav_playground.html", "en") page_content = self.get_page_title_obj(page) page_url = page.get_absolute_url() page_edit_url = get_object_edit_url(page_content) # Add some content placeholder = page.get_placeholders("en").filter(slot="body")[0] - add_plugin(placeholder, "TextPlugin", 'en', body="English") - add_plugin(placeholder, "TextPlugin", 'de', body="Deutsch") + add_plugin(placeholder, "TextPlugin", "en", body="English") + add_plugin(placeholder, "TextPlugin", "de", body="Deutsch") # Make an initial edit endpoint request with self.login_user_context(superuser): @@ -478,29 +486,29 @@ def test_invalidate_restart(self): # Ensure that we're testing in an environment WITHOUT the MW cache... exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware' + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): # Silly to do these tests if this setting isn't True - page_cache_setting = get_cms_setting('PAGE_CACHE') + page_cache_setting = get_cms_setting("PAGE_CACHE") self.assertTrue(page_cache_setting) # Create a test page - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() # Add some content placeholder = page1.get_placeholders("en").filter(slot="body")[0] - add_plugin(placeholder, "TextPlugin", 'en', body="English") - add_plugin(placeholder, "TextPlugin", 'de', body="Deutsch") + add_plugin(placeholder, "TextPlugin", "en", body="English") + add_plugin(placeholder, "TextPlugin", "de", body="Deutsch") # Create a request object - request = self.get_request(page1.get_path('en'), 'en') + request = self.get_request(page1.get_path("en"), "en") # Ensure that user is NOT authenticated self.assertFalse(request.user.is_authenticated) @@ -526,48 +534,51 @@ def test_invalidate_restart(self): self.assertEqual(response.status_code, 200) def test_sekizai_plugin(self): - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") placeholder1 = page1.get_placeholders("en").filter(slot="body")[0] placeholder2 = page1.get_placeholders("en").filter(slot="right-column")[0] plugin_pool.register_plugin(SekizaiPlugin) - add_plugin(placeholder1, "SekizaiPlugin", 'en') - add_plugin(placeholder2, "TextPlugin", 'en', body="Deutsch") + add_plugin(placeholder1, "SekizaiPlugin", "en") + add_plugin(placeholder2, "TextPlugin", "en", body="Deutsch") response = self.client.get(page1.get_absolute_url()) - self.assertContains(response, 'alert(') + self.assertContains(response, "alert(") response = self.client.get(page1.get_absolute_url()) - self.assertContains(response, 'alert(') + self.assertContains(response, "alert(") def test_cache_invalidation(self): # Ensure that we're testing in an environment WITHOUT the MW cache... exclude = [ - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware' + "django.middleware.cache.UpdateCacheMiddleware", + "django.middleware.cache.FetchFromCacheMiddleware", ] overrides = { - 'MIDDLEWARE': [mw for mw in settings.MIDDLEWARE if mw not in exclude] + "MIDDLEWARE": [mw for mw in settings.MIDDLEWARE if mw not in exclude] } with self.settings(**overrides): # Silly to do these tests if this setting isn't True - page_cache_setting = get_cms_setting('PAGE_CACHE') + page_cache_setting = get_cms_setting("PAGE_CACHE") self.assertTrue(page_cache_setting) - page1 = create_page('test page 1', 'nav_playground.html', 'en') + page1 = create_page("test page 1", "nav_playground.html", "en") page1_url = page1.get_absolute_url() placeholder = page1.get_placeholders("en").get(slot="body") - add_plugin(placeholder, "TextPlugin", 'en', body="First content") + add_plugin(placeholder, "TextPlugin", "en", body="First content") response = self.client.get(page1_url) - self.assertContains(response, 'First content') + self.assertContains(response, "First content") response = self.client.get(page1_url) - self.assertContains(response, 'First content') + self.assertContains(response, "First content") with self.login_user_context(self.get_superuser()): - post_data = {'name': 'A Link', 'external_link': 'https://www.django-cms.org'} - endpoint = self.get_add_plugin_uri(placeholder, 'LinkPlugin') + post_data = { + "name": "A Link", + "external_link": "https://www.django-cms.org", + } + endpoint = self.get_add_plugin_uri(placeholder, "LinkPlugin") self.client.post(endpoint, post_data) response = self.client.get(page1_url) - self.assertContains(response, 'A Link') + self.assertContains(response, "A Link") def test_render_placeholder_cache(self): """ @@ -576,31 +587,26 @@ def test_render_placeholder_cache(self): Assert that placeholder cache is cleared correctly when a plugin is saved """ invalidate_cms_page_cache() - ex = Example1( - char_1='one', - char_2='two', - char_3='tree', - char_4='four' - ) + ex = Example1(char_1="one", char_2="two", char_3="tree", char_4="four") ex.save() ph1 = ex.placeholder ### # add the test plugin ## - test_plugin = add_plugin(ph1, u"TextPlugin", u"en", body="Some text") + test_plugin = add_plugin(ph1, "TextPlugin", "en", body="Some text") test_plugin.save() request = self.get_request() content_renderer = self.get_content_renderer(request) # asserting initial text context = SekizaiContext() - context['request'] = self.get_request() + context["request"] = self.get_request() text = content_renderer.render_placeholder(ph1, context) self.assertEqual(text, "Some text") # deleting local plugin cache del ph1._plugins_cache - test_plugin.body = 'Other text' + test_plugin.body = "Other text" test_plugin.save() # plugin text has changed, so the placeholder rendering @@ -611,134 +617,179 @@ def test_render_placeholder_cache(self): class PlaceholderCacheTestCase(CMSTestCase): def setUp(self): from django.core.cache import cache - super(PlaceholderCacheTestCase, self).setUp() + + super().setUp() cache.clear() - self.page = create_page( - 'en test page', 'nav_playground.html', 'en') + self.page = create_page("en test page", "nav_playground.html", "en") # Now create and publish as 'de' title - create_page_content('de', "de test page", self.page, template='nav_playground.html') + create_page_content( + "de", "de test page", self.page, template="nav_playground.html" + ) self.placeholder_en = self.page.get_placeholders("en").filter(slot="body")[0] self.placeholder_de = self.page.get_placeholders("de").filter(slot="body")[0] plugin_pool.register_plugin(VaryCacheOnPlugin) - add_plugin(self.placeholder_en, 'TextPlugin', 'en', body='English') - add_plugin(self.placeholder_de, 'TextPlugin', 'de', body='Deutsch') - add_plugin(self.placeholder_en, 'VaryCacheOnPlugin', 'en') - add_plugin(self.placeholder_de, 'VaryCacheOnPlugin', 'de') + add_plugin(self.placeholder_en, "TextPlugin", "en", body="English") + add_plugin(self.placeholder_de, "TextPlugin", "de", body="Deutsch") + add_plugin(self.placeholder_en, "VaryCacheOnPlugin", "en") + add_plugin(self.placeholder_de, "VaryCacheOnPlugin", "de") - self.en_request = self.get_request('/en/') + self.en_request = self.get_request("/en/") self.en_request.current_page = Page.objects.get(pk=self.page.pk) - self.en_us_request = self.get_request('/en/') - self.en_us_request.META['HTTP_COUNTRY_CODE'] = 'US' + self.en_us_request = self.get_request("/en/") + self.en_us_request.META["HTTP_COUNTRY_CODE"] = "US" - self.en_uk_request = self.get_request('/en/') - self.en_uk_request.META['HTTP_COUNTRY_CODE'] = 'UK' + self.en_uk_request = self.get_request("/en/") + self.en_uk_request.META["HTTP_COUNTRY_CODE"] = "UK" - self.de_request = self.get_request('/de/') + self.de_request = self.get_request("/de/") self.de_request.current_page = Page.objects.get(pk=self.page.pk) def tearDown(self): from django.core.cache import cache - super(PlaceholderCacheTestCase, self).tearDown() + + super().tearDown() plugin_pool.unregister_plugin(VaryCacheOnPlugin) cache.clear() def test_get_placeholder_cache_version_key(self): - cache_version_key = '{prefix}|placeholder_cache_version|id:{id}|lang:{lang}|site:{site}'.format( - prefix=get_cms_setting('CACHE_PREFIX'), - id=self.placeholder_en.pk, - lang='en', - site=1, + cache_version_key = ( + "{prefix}|placeholder_cache_version|id:{id}|lang:{lang}|site:{site}".format( + prefix=get_cms_setting("CACHE_PREFIX"), + id=self.placeholder_en.pk, + lang="en", + site=1, + ) ) self.assertEqual( - _get_placeholder_cache_version_key(self.placeholder_en, 'en', 1), - cache_version_key + _get_placeholder_cache_version_key(self.placeholder_en, "en", 1), + cache_version_key, ) def test_set_clear_get_placeholder_cache_version(self): - initial, _ = _get_placeholder_cache_version(self.placeholder_en, 'en', 1) - clear_placeholder_cache(self.placeholder_en, 'en', 1) - version, _ = _get_placeholder_cache_version(self.placeholder_en, 'en', 1) + initial, _ = _get_placeholder_cache_version(self.placeholder_en, "en", 1) + clear_placeholder_cache(self.placeholder_en, "en", 1) + version, _ = _get_placeholder_cache_version(self.placeholder_en, "en", 1) self.assertGreater(version, initial) def test_get_placeholder_cache_key(self): - version, vary_on_list = _get_placeholder_cache_version(self.placeholder_en, 'en', 1) - desired_key = '{prefix}|render_placeholder|id:{id}|lang:{lang}|site:{site}|tz:{tz}|v:{version}|country-code:{cc}'.format( # noqa - prefix=get_cms_setting('CACHE_PREFIX'), + version, vary_on_list = _get_placeholder_cache_version( + self.placeholder_en, "en", 1 + ) + desired_key = "{prefix}|render_placeholder|id:{id}|lang:{lang}|site:{site}|tz:{tz}|v:{version}|country-code:{cc}".format( # noqa + prefix=get_cms_setting("CACHE_PREFIX"), id=self.placeholder_en.pk, - lang='en', + lang="en", site=1, tz=get_timezone_name(), version=version, - cc='_', + cc="_", + ) + _set_placeholder_cache_version( + self.placeholder_en, "en", 1, version, vary_on_list=vary_on_list, duration=1 + ) + actual_key = _get_placeholder_cache_key( + self.placeholder_en, "en", 1, self.en_request ) - _set_placeholder_cache_version(self.placeholder_en, 'en', 1, version, vary_on_list=vary_on_list, duration=1) - actual_key = _get_placeholder_cache_key(self.placeholder_en, 'en', 1, self.en_request) self.assertEqual(actual_key, desired_key) - en_key = _get_placeholder_cache_key(self.placeholder_en, 'en', 1, self.en_request) - de_key = _get_placeholder_cache_key(self.placeholder_de, 'de', 1, self.de_request) + en_key = _get_placeholder_cache_key( + self.placeholder_en, "en", 1, self.en_request + ) + de_key = _get_placeholder_cache_key( + self.placeholder_de, "de", 1, self.de_request + ) self.assertNotEqual(en_key, de_key) - en_us_key = _get_placeholder_cache_key(self.placeholder_en, 'en', 1, self.en_us_request) + en_us_key = _get_placeholder_cache_key( + self.placeholder_en, "en", 1, self.en_us_request + ) self.assertNotEqual(en_key, en_us_key) - desired_key = '{prefix}|render_placeholder|id:{id}|lang:{lang}|site:{site}|tz:{tz}|v:{version}|country-code:{cc}'.format( # noqa - prefix=get_cms_setting('CACHE_PREFIX'), + desired_key = "{prefix}|render_placeholder|id:{id}|lang:{lang}|site:{site}|tz:{tz}|v:{version}|country-code:{cc}".format( # noqa + prefix=get_cms_setting("CACHE_PREFIX"), id=self.placeholder_en.pk, - lang='en', + lang="en", site=1, tz=get_timezone_name(), version=version, - cc='US', + cc="US", ) self.assertEqual(en_us_key, desired_key) def test_set_get_placeholder_cache(self): # Test with a super-long prefix en_renderer = self.get_content_renderer(self.en_request) - en_context = Context({ - 'request': self.en_request, - }) + en_context = Context( + { + "request": self.en_request, + } + ) en_us_renderer = self.get_content_renderer(self.en_us_request) - en_us_context = Context({ - 'request': self.en_us_request, - }) + en_us_context = Context( + { + "request": self.en_us_request, + } + ) en_uk_renderer = self.get_content_renderer(self.en_uk_request) - en_uk_context = Context({ - 'request': self.en_uk_request, - }) + en_uk_context = Context( + { + "request": self.en_uk_request, + } + ) - en_content = en_renderer.render_placeholder(self.placeholder_en, en_context, 'en', width=350) - en_us_content = en_us_renderer.render_placeholder(self.placeholder_en, en_us_context, 'en', width=350) - en_uk_content = en_uk_renderer.render_placeholder(self.placeholder_en, en_uk_context, 'en', width=350) + en_content = en_renderer.render_placeholder( + self.placeholder_en, en_context, "en", width=350 + ) + en_us_content = en_us_renderer.render_placeholder( + self.placeholder_en, en_us_context, "en", width=350 + ) + en_uk_content = en_uk_renderer.render_placeholder( + self.placeholder_en, en_uk_context, "en", width=350 + ) del self.placeholder_en._plugins_cache de_renderer = self.get_content_renderer(self.de_request) - de_context = Context({ - 'request': self.de_request, - }) - de_content = de_renderer.render_placeholder(self.placeholder_de, de_context, 'de', width=350) + de_context = Context( + { + "request": self.de_request, + } + ) + de_content = de_renderer.render_placeholder( + self.placeholder_de, de_context, "de", width=350 + ) self.assertNotEqual(en_content, de_content) - set_placeholder_cache(self.placeholder_en, 'en', 1, en_content, self.en_request) - cached_en_content = get_placeholder_cache(self.placeholder_en, 'en', 1, self.en_request) + set_placeholder_cache(self.placeholder_en, "en", 1, en_content, self.en_request) + cached_en_content = get_placeholder_cache( + self.placeholder_en, "en", 1, self.en_request + ) self.assertEqual(cached_en_content, en_content) - set_placeholder_cache(self.placeholder_de, 'de', 1, de_content, self.de_request) - cached_de_content = get_placeholder_cache(self.placeholder_de, 'de', 1, self.de_request) + set_placeholder_cache(self.placeholder_de, "de", 1, de_content, self.de_request) + cached_de_content = get_placeholder_cache( + self.placeholder_de, "de", 1, self.de_request + ) self.assertNotEqual(cached_en_content, cached_de_content) - set_placeholder_cache(self.placeholder_en, 'en', 1, en_us_content, self.en_us_request) - cached_en_us_content = get_placeholder_cache(self.placeholder_en, 'en', 1, self.en_us_request) + set_placeholder_cache( + self.placeholder_en, "en", 1, en_us_content, self.en_us_request + ) + cached_en_us_content = get_placeholder_cache( + self.placeholder_en, "en", 1, self.en_us_request + ) self.assertNotEqual(cached_en_content, cached_en_us_content) - set_placeholder_cache(self.placeholder_en, 'en', 1, en_uk_content, self.en_uk_request) - cached_en_uk_content = get_placeholder_cache(self.placeholder_en, 'en', 1, self.en_uk_request) + set_placeholder_cache( + self.placeholder_en, "en", 1, en_uk_content, self.en_uk_request + ) + cached_en_uk_content = get_placeholder_cache( + self.placeholder_en, "en", 1, self.en_uk_request + ) self.assertNotEqual(cached_en_us_content, cached_en_uk_content) def test_set_get_placeholder_cache_with_long_prefix(self): @@ -748,25 +799,33 @@ def test_set_get_placeholder_cache_with_long_prefix(self): """ # Use an absurdly long cache prefix to get us in the right neighborhood... with self.settings(CMS_CACHE_PREFIX="super_lengthy_prefix" * 9): # 180 chars - en_crazy_request = self.get_request('/en/') + en_crazy_request = self.get_request("/en/") en_crazy_renderer = self.get_content_renderer(self.de_request) # Use a ridiculously long "country code" (80 chars), already we're at 260 chars. - en_crazy_request.META['HTTP_COUNTRY_CODE'] = 'US' * 40 # 80 chars - en_crazy_context = Context({'request': en_crazy_request}) + en_crazy_request.META["HTTP_COUNTRY_CODE"] = "US" * 40 # 80 chars + en_crazy_context = Context({"request": en_crazy_request}) en_crazy_content = en_crazy_renderer.render_placeholder( self.placeholder_en, en_crazy_context, - language='en', + language="en", width=350, ) - set_placeholder_cache(self.placeholder_en, 'en', 1, en_crazy_content, en_crazy_request) + set_placeholder_cache( + self.placeholder_en, "en", 1, en_crazy_content, en_crazy_request + ) # Prove that it is hashed... - crazy_cache_key = _get_placeholder_cache_key(self.placeholder_en, 'en', 1, en_crazy_request) + crazy_cache_key = _get_placeholder_cache_key( + self.placeholder_en, "en", 1, en_crazy_request + ) key_length = len(crazy_cache_key) # 221 = 180 (prefix length) + 1 (separator) + 40 (sha1 hash) - self.assertTrue('render_placeholder' not in crazy_cache_key and key_length == 221) + self.assertTrue( + "render_placeholder" not in crazy_cache_key and key_length == 221 + ) # Prove it still works as expected - cached_en_crazy_content = get_placeholder_cache(self.placeholder_en, 'en', 1, en_crazy_request) + cached_en_crazy_content = get_placeholder_cache( + self.placeholder_en, "en", 1, en_crazy_request + ) self.assertEqual(en_crazy_content, cached_en_crazy_content) diff --git a/cms/tests/test_check.py b/cms/tests/test_check.py index cadb4ce60d1..88a09a34992 100644 --- a/cms/tests/test_check.py +++ b/cms/tests/test_check.py @@ -35,7 +35,7 @@ def write_stderr(self, message): pass -class CheckAssertMixin(): +class CheckAssertMixin: def assertCheck(self, successful, **assertions): """ asserts that checks are successful or not diff --git a/cms/tests/test_cms_config_wizards.py b/cms/tests/test_cms_config_wizards.py index b37fedfbe10..f446892a9b0 100644 --- a/cms/tests/test_cms_config_wizards.py +++ b/cms/tests/test_cms_config_wizards.py @@ -1,6 +1,7 @@ +from unittest.mock import Mock, patch + from django.apps import apps from django.core.exceptions import ImproperlyConfigured -from mock import Mock, patch from cms.app_registration import get_cms_config_apps, get_cms_extension_apps from cms.cms_config import CMSCoreExtensions @@ -72,8 +73,7 @@ def test_warning_if_registering_the_same_wizard_twice(self, mocked_logger): cms_config = Mock( cms_enabled=True, cms_wizards=[wizard, wizard]) extensions.configure_wizards(cms_config) - warning_msg = "Wizard for model {} has already been registered".format( - wizard.get_model()) + warning_msg = f"Wizard for model {wizard.get_model()} has already been registered" # Warning message displayed mocked_logger.assert_called_once_with(warning_msg) # wizards dict is still what we expect it to be diff --git a/cms/tests/test_extensions.py b/cms/tests/test_extensions.py index 91def2d7c8b..4dc32ba5fa0 100644 --- a/cms/tests/test_extensions.py +++ b/cms/tests/test_extensions.py @@ -393,7 +393,7 @@ def populate(self): ) toolbar_pool.register(SampleExtension) with self.login_user_context(self.admin): - response = self.client.get('{}?edit'.format(self.page.get_absolute_url())) + response = self.client.get(f'{self.page.get_absolute_url()}?edit') self.assertIn("TestItem", response.rendered_content) toolbar_pool.toolbars = old_toolbars @@ -416,7 +416,7 @@ def populate(self): ) toolbar_pool.register(SampleExtension) with self.login_user_context(self.admin): - response = self.client.get('{}?edit'.format(self.page.get_absolute_url())) + response = self.client.get(f'{self.page.get_absolute_url()}?edit') self.assertIn("TestItem", response.rendered_content) toolbar_pool.toolbars = old_toolbars diff --git a/cms/tests/test_forms.py b/cms/tests/test_forms.py index 04f88be5e63..2e3ed1d461c 100644 --- a/cms/tests/test_forms.py +++ b/cms/tests/test_forms.py @@ -176,7 +176,7 @@ def test_update_site_and_page_choices(self): 'nav_playground.html', 'en', site=site, parent=page1) # enforce the choices to be casted to a list - site_choices, page_choices = [list(bit) for bit in update_site_and_page_choices('en')] + site_choices, page_choices = (list(bit) for bit in update_site_and_page_choices('en')) self.assertEqual(page_choices, [ ('', '----'), (site.name, [ @@ -189,7 +189,7 @@ def test_update_site_and_page_choices(self): self.assertEqual(site_choices, [(site.pk, site.name)]) def test_app_config_select_escaping(self): - class FakeAppConfig(): + class FakeAppConfig: def __init__(self, pk, config): self.pk = pk self.config = config @@ -197,7 +197,7 @@ def __init__(self, pk, config): def __str__(self): return self.config - class FakeApp(): + class FakeApp: def __init__(self, name, configs=()): self.name = name self.configs = configs diff --git a/cms/tests/test_management.py b/cms/tests/test_management.py index fbd2fe2b9b5..d9a652cfc59 100644 --- a/cms/tests/test_management.py +++ b/cms/tests/test_management.py @@ -170,7 +170,7 @@ def test_list_plugins(self): self.assertEqual( bogus_plugins_report["type"], - u'BogusPlugin') + 'BogusPlugin') self.assertEqual( bogus_plugins_report["instances"][0], @@ -184,7 +184,7 @@ def test_list_plugins(self): self.assertEqual( link_plugins_report["type"], - u'LinkPlugin') + 'LinkPlugin') self.assertEqual( link_plugins_report["instances"][0].get_plugin_instance()[0], @@ -198,7 +198,7 @@ def test_list_plugins(self): self.assertEqual( text_plugins_report["type"], - u'TextPlugin') + 'TextPlugin') self.assertEqual( len(text_plugins_report["instances"]), @@ -385,7 +385,7 @@ def test_copy_langs_no_content(self): ) pages = Page.objects.on_site(site) for page in pages: - self.assertEqual(set((u'en', u'de')), set(page.get_languages())) + self.assertEqual(set(('en', 'de')), set(page.get_languages())) # These asserts that no orphaned plugin exists self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins) self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) @@ -488,7 +488,7 @@ def test_copy_existing_title(self): ) pages = Page.objects.on_site(site) for page in pages: - self.assertEqual(set((u'en', u'de')), set(page.get_languages())) + self.assertEqual(set(('en', 'de')), set(page.get_languages())) # Original PageContent untouched self.assertEqual("root page de", Page.objects.get_home(site).get_title("de")) diff --git a/cms/tests/test_menu.py b/cms/tests/test_menu.py index b1accefac3b..c038236f050 100644 --- a/cms/tests/test_menu.py +++ b/cms/tests/test_menu.py @@ -6,8 +6,7 @@ from django.template import Template, TemplateSyntaxError from django.template.context import Context from django.test.utils import override_settings -from django.utils.translation import activate -from django.utils.translation import override as force_language +from django.utils.translation import activate, override as force_language from cms.api import create_page, create_page_content from cms.apphook_pool import apphook_pool diff --git a/cms/tests/test_menu_page_viewperm.py b/cms/tests/test_menu_page_viewperm.py index 6ef3b7885df..57bd59c411f 100644 --- a/cms/tests/test_menu_page_viewperm.py +++ b/cms/tests/test_menu_page_viewperm.py @@ -150,7 +150,7 @@ def _setup_user_groups(self): user = self._create_user(username, is_staff) if groupname: group, _ = Group.objects.get_or_create(name=groupname) - user_set = getattr(group, 'user_set') + user_set = group.user_set user_set.add(user) group.save() @@ -594,7 +594,7 @@ def _setup_pages(self): def _setup_user(self): user = self._create_user('user_6', True) group = Group.objects.create(name=self.GROUPNAME_6) - user_set = getattr(group, 'user_set') + user_set = group.user_set user_set.add(user) group.save() diff --git a/cms/tests/test_migrations.py b/cms/tests/test_migrations.py index 01f7c62c225..ea59f40503b 100644 --- a/cms/tests/test_migrations.py +++ b/cms/tests/test_migrations.py @@ -25,4 +25,4 @@ def test_for_missing_migrations(self): status_code = '0' if status_code == '1': - self.fail('There are missing migrations:\n {}'.format(output.getvalue())) + self.fail(f'There are missing migrations:\n {output.getvalue()}') diff --git a/cms/tests/test_nested_plugins.py b/cms/tests/test_nested_plugins.py index 0fe66fd66ea..abb838f447e 100644 --- a/cms/tests/test_nested_plugins.py +++ b/cms/tests/test_nested_plugins.py @@ -689,7 +689,7 @@ def test_copy_page_nested_plugin(self): org_placeholder = org_link_child_plugin.placeholder copied_placeholder = copied_link_child_plugin.placeholder msg = "placeholder of the original plugin and copied plugin are the same" - ok = ((org_placeholder.id != copied_placeholder.id)) + ok = (org_placeholder.id != copied_placeholder.id) self.assertTrue(ok, msg) def test_copy_page_nested_plugin_moved_parent_plugin(self): @@ -837,13 +837,13 @@ def test_copy_page_nested_plugin_moved_parent_plugin(self): found_page = page_two_ph_three.page if page_two_ph_three else None self.assertEqual(found_page, page_two) # check the stored placeholders org vs copy - msg = u'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( + msg = 'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( page_two_ph_one.pk, page_one_ph_one.pk, page_two.pk) self.assertNotEqual(page_two_ph_one.pk, page_one_ph_one.pk, msg) - msg = u'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( + msg = 'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( page_two_ph_two.pk, page_one_ph_two.pk, page_two.pk) self.assertNotEqual(page_two_ph_two.pk, page_one_ph_two.pk, msg) - msg = u'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( + msg = 'placehoder ids copy:%s org:%s copied page %s are identical - tree broken' % ( page_two_ph_three.pk, page_one_ph_three.pk, page_two.pk) self.assertNotEqual(page_two_ph_three.pk, page_one_ph_three.pk, msg) # get the plugins from the original page diff --git a/cms/tests/test_page.py b/cms/tests/test_page.py index 130d77519e2..70f70b2a7e6 100644 --- a/cms/tests/test_page.py +++ b/cms/tests/test_page.py @@ -166,7 +166,7 @@ def test_create_page_api(self): page = self.create_homepage(**page_data) self.assertEqual(Page.objects.count(), 1) self.assertTrue(page.is_home) - self.assertEqual(list(page.get_urls().values_list('path', flat=True)), [u'']) + self.assertEqual(list(page.get_urls().values_list('path', flat=True)), ['']) @skipIf(has_no_custom_user(), 'No custom user') def test_create_page_api_with_long_username(self): @@ -185,12 +185,12 @@ def test_create_page_api_with_long_username(self): self.assertEqual(Page.objects.count(), 1) self.assertLessEqual(len(page.created_by), constants.PAGE_USERNAME_MAX_LENGTH) - self.assertRegexpMatches(page.created_by, r'V+\.{3} \(id=\d+\)') + self.assertRegex(page.created_by, r'V+\.{3} \(id=\d+\)') self.assertLessEqual(len(page.changed_by), constants.PAGE_USERNAME_MAX_LENGTH) - self.assertRegexpMatches(page.changed_by, r'V+\.{3} \(id=\d+\)') + self.assertRegex(page.changed_by, r'V+\.{3} \(id=\d+\)') - self.assertEqual(list(page.get_urls().values_list('path', flat=True)), [u'root']) + self.assertEqual(list(page.get_urls().values_list('path', flat=True)), ['root']) def test_get_available_slug_recursion(self): """ Checks cms.utils.page.get_available_slug for infinite recursion @@ -419,7 +419,7 @@ def test_add_placeholder(self): response = self.client.get(url) self.assertEqual(200, response.status_code) path = os.path.join(settings.TEMPLATES[0]['DIRS'][0], 'add_placeholder.html') - with open(path, 'r') as fobj: + with open(path) as fobj: old = fobj.read() try: new = old.replace( @@ -609,7 +609,7 @@ def test_page_and_title_repr(self): saved_page = create_page('test saved page', 'nav_playground.html', 'en') self.assertIsNotNone(saved_page.pk) - self.assertIn('id={}'.format(saved_page.pk), repr(saved_page)) + self.assertIn(f'id={saved_page.pk}', repr(saved_page)) non_saved_title = PageContent() self.assertIsNone(non_saved_title.pk) @@ -617,7 +617,7 @@ def test_page_and_title_repr(self): saved_content = saved_page.get_content_obj() self.assertIsNotNone(saved_content.pk) - self.assertIn('id={}'.format(saved_content.pk), repr(saved_content)) + self.assertIn(f'id={saved_content.pk}', repr(saved_content)) def test_page_overwrite_urls(self): diff --git a/cms/tests/test_page_admin.py b/cms/tests/test_page_admin.py index 11b1d982b98..6a068f4a522 100644 --- a/cms/tests/test_page_admin.py +++ b/cms/tests/test_page_admin.py @@ -467,10 +467,7 @@ def test_page_obj_change_data_from_template_tags(self): req.GET = {} actual_result = t.render(template.Context({"request": req})) - desired_result = "{0} changed on {1}".format( - change_user, - actual_result[-19:] - ) + desired_result = f"{change_user} changed on {actual_result[-19:]}" save_time = datetime.datetime.strptime( actual_result[-19:], "%Y-%m-%dT%H:%M:%S" @@ -1610,7 +1607,7 @@ def _get_page_permissions_data(self, **kwargs): for attr, value in kwargs.items(): if attr not in non_inline: - attr = 'pagepermission_set-2-0-{}'.format(attr) + attr = f'pagepermission_set-2-0-{attr}' data[attr] = value return data @@ -1643,7 +1640,7 @@ def _get_page_view_restrictions_data(self, **kwargs): for attr, value in kwargs.items(): if attr not in non_inline: - attr = 'pagepermission_set-0-{}'.format(attr) + attr = f'pagepermission_set-0-{attr}' data[attr] = value return data diff --git a/cms/tests/test_placeholder.py b/cms/tests/test_placeholder.py index 8f87875a3e3..2e704586c64 100644 --- a/cms/tests/test_placeholder.py +++ b/cms/tests/test_placeholder.py @@ -542,7 +542,7 @@ def test_nested_plugin_escapejs(self): ### # add the test plugin ### - test_plugin = add_plugin(ph1, u"EmptyPlugin", u"en") + test_plugin = add_plugin(ph1, "EmptyPlugin", "en") test_plugin.save() endpoint = self.get_change_plugin_uri(test_plugin) response = self.client.post(endpoint, {}) @@ -559,7 +559,7 @@ def test_nested_plugin_escapejs_page(self): ### # add the test plugin ### - test_plugin = add_plugin(ph1, u"EmptyPlugin", u"en") + test_plugin = add_plugin(ph1, "EmptyPlugin", "en") test_plugin.save() endpoint = self.get_change_plugin_uri(test_plugin) @@ -788,7 +788,7 @@ def test_placeholder_languages_model(self): # add the test plugin ### for lang in avail_langs: - add_plugin(ex.placeholder, u"EmptyPlugin", lang) + add_plugin(ex.placeholder, "EmptyPlugin", lang) # reload instance from database ex = Example1.objects.get(pk=ex.pk) # get languages @@ -811,7 +811,7 @@ def test_placeholder_languages_page(self): # add the test plugin ### for lang in avail_langs: - add_plugin(placeholder, u"EmptyPlugin", lang) + add_plugin(placeholder, "EmptyPlugin", lang) # reload placeholder from database placeholder = page.get_placeholders("en").get(slot='col_sidebar') # get languages @@ -1163,8 +1163,8 @@ def test_repr(self): self.assertIn("slot=''", repr(unsaved_ph)) saved_ph = Placeholder.objects.create(slot='test') - self.assertIn('id={}'.format(saved_ph.pk), repr(saved_ph)) - self.assertIn("slot='{}'".format(saved_ph.slot), repr(saved_ph)) + self.assertIn(f'id={saved_ph.pk}', repr(saved_ph)) + self.assertIn(f"slot='{saved_ph.slot}'", repr(saved_ph)) class PlaceholderConfTests(TestCase): diff --git a/cms/tests/test_placeholder_checks.py b/cms/tests/test_placeholder_checks.py index 665a2603a7a..01b2d58af9e 100644 --- a/cms/tests/test_placeholder_checks.py +++ b/cms/tests/test_placeholder_checks.py @@ -1,5 +1,6 @@ +from unittest.mock import Mock, call, patch + from django.forms.models import model_to_dict -from mock import Mock, call, patch from cms.api import create_page from cms.models import Placeholder, UserSettings, fields diff --git a/cms/tests/test_plugin_renderers.py b/cms/tests/test_plugin_renderers.py index 18fd2fbe175..02fc43f7e2d 100644 --- a/cms/tests/test_plugin_renderers.py +++ b/cms/tests/test_plugin_renderers.py @@ -51,7 +51,7 @@ def test_render_placeholder_toolbar_js(self): '"MultiColumnPlugin"', '"addPluginHelpTitle": "Add plugin to placeholder \\"Body\\""', '"name": "Body"', - '"placeholder_id": "{}"'.format(placeholder.pk), + f'"placeholder_id": "{placeholder.pk}"', ] for bit in expected_bits: @@ -71,7 +71,7 @@ def test_render_placeholder_toolbar_js_escaping(self): '"MultiColumnPlugin"', '"addPluginHelpTitle": "Add plugin to placeholder \\"Content-with-dash\\""', '"name": "Content-with-dash"', - '"placeholder_id": "{}"'.format(placeholder.pk), + f'"placeholder_id": "{placeholder.pk}"', ] for bit in expected_bits: diff --git a/cms/tests/test_plugins.py b/cms/tests/test_plugins.py index a342e2e78a4..19851d3d31e 100644 --- a/cms/tests/test_plugins.py +++ b/cms/tests/test_plugins.py @@ -644,8 +644,8 @@ def test_repr(self): self.assertIn("plugin_type=''", repr(non_saved_plugin)) saved_plugin = CMSPlugin.objects.create(plugin_type='TextPlugin') - self.assertIn('id={}'.format(saved_plugin.pk), repr(saved_plugin)) - self.assertIn("plugin_type='{}'".format(saved_plugin.plugin_type), repr(saved_plugin)) + self.assertIn(f'id={saved_plugin.pk}', repr(saved_plugin)) + self.assertIn(f"plugin_type='{saved_plugin.plugin_type}'", repr(saved_plugin)) def test_pickle(self): page = api.create_page("page", "nav_playground.html", "en") diff --git a/cms/tests/test_rendering.py b/cms/tests/test_rendering.py index faa2180f223..58e6615cb54 100644 --- a/cms/tests/test_rendering.py +++ b/cms/tests/test_rendering.py @@ -266,7 +266,7 @@ def insert_test_content(self): self.test_page10 = self.reload(p10) def strip_rendered(self, content): - return content.strip().replace(u"\n", u"") + return content.strip().replace("\n", "") @override_settings(CMS_TEMPLATES=[(TEMPLATE_NAME, '')]) def render(self, page, template=None, context_vars=None, request=None): @@ -396,7 +396,7 @@ def test_placeholder_or_in_edit_mode(self): page=self.test_page, editable=True, ) - expected = '|{}No content'.format(expected) + expected = f'|{expected}No content' rendered = self.render(self.test_page, template=t, request=request) self.assertEqual(rendered, self.strip_rendered(expected)) @@ -409,7 +409,7 @@ def test_render_placeholder_tag(self): char_4="char_4") ex1.save() - add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body) + add_plugin(ex1.placeholder, "TextPlugin", "en", body=render_placeholder_body) t = '''{% extends "base.html" %} {% load cms_tags %} @@ -445,7 +445,7 @@ def test_render_uncached_placeholder_tag(self): char_4="char_4") ex1.save() - add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_uncached_placeholder_body) + add_plugin(ex1.placeholder, "TextPlugin", "en", body=render_uncached_placeholder_body) t = '''{% extends "base.html" %} {% load cms_tags %} @@ -480,7 +480,7 @@ def test_render_uncached_placeholder_tag_no_use_cache(self): char_4="char_4") ex1.save() request = self.get_request('/') - add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_uncached_placeholder_body) + add_plugin(ex1.placeholder, "TextPlugin", "en", body=render_uncached_placeholder_body) template = '{% load cms_tags %}

{% render_uncached_placeholder ex1.placeholder %}

' @@ -500,7 +500,7 @@ def test_render_placeholder_tag_use_cache(self): char_4="char_4") ex1.save() request = self.get_request('/') - add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body) + add_plugin(ex1.placeholder, "TextPlugin", "en", body=render_placeholder_body) template = '{% load cms_tags %}

{% render_placeholder ex1.placeholder %}

' diff --git a/cms/tests/test_templatetags.py b/cms/tests/test_templatetags.py index 23f02c88e23..7b6e6c10b77 100644 --- a/cms/tests/test_templatetags.py +++ b/cms/tests/test_templatetags.py @@ -1,5 +1,6 @@ import os from copy import deepcopy +from unittest.mock import patch from django.conf import settings from django.contrib.auth.models import AnonymousUser @@ -14,7 +15,6 @@ from django.utils.timezone import now from django.utils.translation import override as force_language from djangocms_text_ckeditor.cms_plugins import TextPlugin -from mock import patch from sekizai.context import SekizaiContext import cms @@ -116,11 +116,11 @@ def test_unicode_placeholder_name_fails_fast(self): def test_page_attribute_tag_escapes_content(self): script = '' - class FakePage(): + class FakePage: def get_page_title(self, *args, **kwargs): return script - class FakeRequest(): + class FakeRequest: current_page = FakePage() GET = {'language': 'en'} diff --git a/cms/tests/test_toolbar.py b/cms/tests/test_toolbar.py index acac3a84cb7..87059beb337 100644 --- a/cms/tests/test_toolbar.py +++ b/cms/tests/test_toolbar.py @@ -11,12 +11,11 @@ from django.test import TestCase from django.test.client import RequestFactory from django.test.utils import override_settings -from django.urls import resolve, reverse +from django.urls import reverse from django.utils.encoding import force_str from django.utils.functional import lazy from django.utils.html import escape -from django.utils.translation import get_language, override -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import get_language, gettext_lazy as _, override from cms.admin.forms import RequestToolbarForm from cms.api import add_plugin, create_page, create_page_content @@ -608,7 +607,7 @@ def test_toolbar_login_redirect_validation(self): page = create_page("toolbar-page", "nav_playground.html", "en") page.set_as_homepage() login_url = reverse('cms_login') - endpoint = '{}?next=https://notyourdomain.com'.format(login_url) + endpoint = f'{login_url}?next=https://notyourdomain.com' response = self.client.post(endpoint, {'username': username, 'password': username}) self.assertRedirects(response, page.get_absolute_url(), fetch_redirect_response=False) @@ -865,14 +864,14 @@ def test_add_language(self): request = self.get_page_request(page, self.get_staff(), edit_url) self.assertMenuItems( request, LANGUAGE_MENU_IDENTIFIER, 'Add Translation', - [u'German...', u'Brazilian Portuguese...', u'French...', u'Espa\xf1ol...'] + ['German...', 'Brazilian Portuguese...', 'French...', 'Espa\xf1ol...'] ) create_page_content(title="de page", language="de", page=page) create_page_content(title="fr page", language="fr", page=page) self.assertMenuItems( request, LANGUAGE_MENU_IDENTIFIER, 'Add Translation', - [u'Brazilian Portuguese...', u'Espa\xf1ol...'] + ['Brazilian Portuguese...', 'Espa\xf1ol...'] ) def test_copy_plugins(self): @@ -890,7 +889,7 @@ def test_copy_plugins(self): request = self.get_page_request(page, staff, edit_url_en) self.assertMenuItems( request, LANGUAGE_MENU_IDENTIFIER, _('Copy all plugins'), - [u'from German', u'from French'] + ['from German', 'from French'] ) request = self.get_page_request(page, staff, edit_url_de, lang_code='de') @@ -937,7 +936,7 @@ def test_toolbar_logout(self): response = self.client.get(page_edit_url) toolbar = response.context['request'].toolbar admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER) - self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser))) + self.assertTrue(admin_menu.find_first(AjaxItem, name=_('Logout %s') % self.get_username(superuser))) # # Test that the logout shows the logged-in user's name, if it was @@ -954,7 +953,7 @@ def test_toolbar_logout(self): response = self.client.get(page_edit_url) toolbar = response.context['request'].toolbar admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER) - self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser))) + self.assertTrue(admin_menu.find_first(AjaxItem, name=_('Logout %s') % self.get_username(superuser))) @override_settings(CMS_PERMISSION=True) def test_toolbar_logout_redirect(self): @@ -988,7 +987,7 @@ def test_toolbar_logout_redirect(self): # Published page, no redirect response = self.client.get(page1_edit_url) toolbar = response.context['request'].toolbar - menu_name = _(u'Logout %s') % self.get_username(superuser) + menu_name = _('Logout %s') % self.get_username(superuser) admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER) self.assertTrue(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success) @@ -1127,7 +1126,7 @@ def test_edit_render_placeholder(self): render_placeholder_body = "I'm the render placeholder body" - plugin = add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body) + plugin = add_plugin(ex1.placeholder, "TextPlugin", "en", body=render_placeholder_body) template_text = '''{% extends "base.html" %} {% load cms_tags %} @@ -1142,15 +1141,13 @@ def test_edit_render_placeholder(self): response = detail_view(request, ex1.pk, template_string=template_text) self.assertContains( response, - '
'.format(ex1.placeholder.pk)) + f'
') self.assertContains( response, - '

' - '{1}' - ''.format( - plugin.pk, render_placeholder_body - ) + f'

' + f'{render_placeholder_body}' + f'' ) self.assertContains( @@ -1164,17 +1161,17 @@ def test_edit_render_placeholder(self): # self.assertContains( response, - '

{0}

'.format(render_placeholder_body) + f'

{render_placeholder_body}

' ) self.assertContains( response, - 'CMS._plugins.push(["cms-plugin-{0}"'.format(plugin.pk) + f'CMS._plugins.push(["cms-plugin-{plugin.pk}"' ) self.assertContains( response, - 'CMS._plugins.push(["cms-placeholder-{0}"'.format(ex1.placeholder.pk) + f'CMS._plugins.push(["cms-placeholder-{ex1.placeholder.pk}"' ) def test_filters(self): @@ -1679,10 +1676,10 @@ def test_invalid_attribute(self): response = detail_view(request, ex1.pk, template_string=template_text) self.assertContains( response, - ''.format(ex1.pk)) + f'') self.assertContains( response, - ''.format(ex1.pk)) + f'') def test_callable_item(self): user = self.get_staff() @@ -1975,13 +1972,11 @@ def test_edit_page(self): ) self.assertContains( response, - '