kopia lustrzana https://github.com/wagtail/wagtail
Apply suggested rewrites from pyupgrade for Python 3.9 and up
``` git ls-files --others --cached --exclude-standard -- '*.py' | xargs pyupgrade --py39-plus ```pull/12156/head
rodzic
4ad2527824
commit
80b1ebe40b
|
@ -1,7 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
@ -47,7 +47,7 @@ class PublishRevisionAction:
|
|||
user=None,
|
||||
changed: bool = True,
|
||||
log_action: bool = True,
|
||||
previous_revision: Optional[Revision] = None,
|
||||
previous_revision: Revision | None = None,
|
||||
):
|
||||
self.revision = revision
|
||||
self.object = self.revision.as_object()
|
||||
|
@ -107,7 +107,7 @@ class PublishRevisionAction:
|
|||
user,
|
||||
changed,
|
||||
log_action: bool,
|
||||
previous_revision: Optional[Revision] = None,
|
||||
previous_revision: Revision | None = None,
|
||||
):
|
||||
from wagtail.models import Revision
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ def extract_panel_definitions_from_model_class(model, exclude=None):
|
|||
return panels
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
@functools.cache
|
||||
def get_edit_handler(model):
|
||||
"""
|
||||
Get the panel to use in the Wagtail admin when editing this model.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from collections.abc import Mapping
|
||||
from datetime import date, datetime, timezone
|
||||
from functools import wraps
|
||||
from typing import Any, List, Mapping, Optional
|
||||
from typing import Any, Optional
|
||||
from unittest import mock
|
||||
|
||||
from django import forms
|
||||
|
@ -846,7 +847,7 @@ class TestFieldPanel(TestCase):
|
|||
def _get_form(
|
||||
self,
|
||||
data: Optional[Mapping[str, Any]] = None,
|
||||
fields: Optional[List[str]] = None,
|
||||
fields: Optional[list[str]] = None,
|
||||
) -> WagtailAdminPageForm:
|
||||
cls = get_form_for_model(
|
||||
EventPage,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from typing import Any, List, Mapping
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from warnings import warn
|
||||
|
||||
from django import forms
|
||||
|
@ -152,7 +153,7 @@ class SubMenuItem(MenuItem):
|
|||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
menu_items: List[MenuItem],
|
||||
menu_items: list[MenuItem],
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
|
@ -262,7 +263,7 @@ class SearchModule:
|
|||
@adapter("wagtail.sidebar.MainMenuModule", base=BaseSidebarAdapter)
|
||||
class MainMenuModule:
|
||||
def __init__(
|
||||
self, menu_items: List[MenuItem], account_menu_items: List[MenuItem], user
|
||||
self, menu_items: list[MenuItem], account_menu_items: list[MenuItem], user
|
||||
):
|
||||
self.menu_items = menu_items
|
||||
self.account_menu_items = account_menu_items
|
||||
|
|
|
@ -317,7 +317,7 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|||
ActiveFilter(
|
||||
bound_field.auto_id,
|
||||
filter_def.label,
|
||||
"%s - %s" % (start_date_display, end_date_display),
|
||||
f"{start_date_display} - {end_date_display}",
|
||||
self.get_url_without_filter_param(
|
||||
[
|
||||
widget.suffixed(field_name, suffix)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from typing import Any, Mapping, Union
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
@ -165,7 +165,7 @@ class BaseSearchView(PermissionCheckedMixin, BaseListingView):
|
|||
kwargs["actions_next_url"] = self.get_index_url()
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update(
|
||||
{
|
||||
|
@ -182,7 +182,7 @@ class BaseSearchView(PermissionCheckedMixin, BaseListingView):
|
|||
class SearchView(BaseSearchView):
|
||||
template_name = "wagtailadmin/pages/search.html"
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["search_form"] = SearchForm(self.request.GET)
|
||||
return context
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
@ -68,7 +68,7 @@ class ContentTypeUseView(BaseListingView):
|
|||
],
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["page_class"] = self.page_class
|
||||
return context
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import logging
|
||||
from typing import Iterable, Set, Tuple
|
||||
from collections.abc import Iterable
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
|
@ -89,8 +89,8 @@ def autocreate_redirects_on_page_move(
|
|||
|
||||
|
||||
def _page_urls_for_sites(
|
||||
page: Page, sites: Tuple[Site], cache_target: Page
|
||||
) -> Set[Tuple[Site, str, str]]:
|
||||
page: Page, sites: tuple[Site], cache_target: Page
|
||||
) -> set[tuple[Site, str, str]]:
|
||||
urls = set()
|
||||
for site in sites:
|
||||
# use a `HttpRequest` to influence the return value
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
from typing import List
|
||||
|
||||
from django.core.exceptions import PermissionDenied, SuspiciousOperation
|
||||
from django.db import transaction
|
||||
|
@ -123,7 +122,7 @@ class IndexView(generic.IndexView):
|
|||
return super().get_base_queryset().select_related("redirect_page", "site")
|
||||
|
||||
@cached_property
|
||||
def header_more_buttons(self) -> List[Button]:
|
||||
def header_more_buttons(self) -> list[Button]:
|
||||
buttons = super().header_more_buttons.copy()
|
||||
buttons.append(
|
||||
Button(
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.admin.utils import quote
|
||||
from django.contrib.auth.models import Permission
|
||||
|
@ -118,7 +116,7 @@ def register_snippet_listing_buttons(snippet, user, next_url=None):
|
|||
|
||||
|
||||
@hooks.register("construct_translated_pages_to_cascade_actions")
|
||||
def construct_translated_pages_to_cascade_actions(pages: List[Page], action: str):
|
||||
def construct_translated_pages_to_cascade_actions(pages: list[Page], action: str):
|
||||
if not getattr(settings, "WAGTAILSIMPLETRANSLATION_SYNC_PAGE_TREE", False):
|
||||
return
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ import inspect
|
|||
import logging
|
||||
import re
|
||||
import unicodedata
|
||||
from collections.abc import Iterable
|
||||
from hashlib import md5
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, Union
|
||||
from typing import TYPE_CHECKING, Any, Union
|
||||
from warnings import warn
|
||||
|
||||
from anyascii import anyascii
|
||||
|
@ -256,7 +257,7 @@ def find_available_slug(parent, requested_slug, ignore_page_id=None):
|
|||
return slug
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
@functools.cache
|
||||
def get_content_languages():
|
||||
"""
|
||||
Cache of settings.WAGTAIL_CONTENT_LANGUAGES in a dictionary for easy lookups by key.
|
||||
|
@ -545,7 +546,7 @@ class BatchCreator(BatchProcessor):
|
|||
if self.max_size and len(self.items) == self.max_size:
|
||||
self.process()
|
||||
|
||||
def extend(self, iterable: Iterable[Union[Model, Dict[str, Any]]]) -> None:
|
||||
def extend(self, iterable: Iterable[Union[Model, dict[str, Any]]]) -> None:
|
||||
for value in iterable:
|
||||
if isinstance(value, self.model):
|
||||
self.add(instance=value)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from django.utils.html import escape
|
||||
|
||||
from wagtail.documents import get_document_model
|
||||
|
@ -20,7 +18,7 @@ class DocumentLinkHandler(LinkHandler):
|
|||
return cls.expand_db_attributes_many([attrs])[0]
|
||||
|
||||
@classmethod
|
||||
def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
|
||||
def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
|
||||
return [
|
||||
'<a href="%s">' % escape(doc.url) if doc else "<a>"
|
||||
for doc in cls.get_many(attrs_list)
|
||||
|
|
|
@ -8,10 +8,11 @@ import os.path
|
|||
import re
|
||||
import time
|
||||
from collections import OrderedDict, defaultdict
|
||||
from collections.abc import Iterable
|
||||
from contextlib import contextmanager
|
||||
from io import BytesIO
|
||||
from tempfile import SpooledTemporaryFile
|
||||
from typing import Any, Dict, Iterable, List, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import willow
|
||||
from django.apps import apps
|
||||
|
@ -442,12 +443,12 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
"""Get the Rendition model for this Image model"""
|
||||
return cls.renditions.rel.related_model
|
||||
|
||||
def _get_prefetched_renditions(self) -> Union[Iterable["AbstractRendition"], None]:
|
||||
def _get_prefetched_renditions(self) -> Iterable[AbstractRendition] | None:
|
||||
if "renditions" in getattr(self, "_prefetched_objects_cache", {}):
|
||||
return self.renditions.all()
|
||||
return getattr(self, "prefetched_renditions", None)
|
||||
|
||||
def _add_to_prefetched_renditions(self, rendition: "AbstractRendition") -> None:
|
||||
def _add_to_prefetched_renditions(self, rendition: AbstractRendition) -> None:
|
||||
# Reuse this rendition if requested again from this object
|
||||
try:
|
||||
self._prefetched_objects_cache["renditions"]._result_cache.append(rendition)
|
||||
|
@ -458,7 +459,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
except AttributeError:
|
||||
pass
|
||||
|
||||
def get_rendition(self, filter: Union["Filter", str]) -> "AbstractRendition":
|
||||
def get_rendition(self, filter: Filter | str) -> AbstractRendition:
|
||||
"""
|
||||
Returns a ``Rendition`` instance with a ``file`` field value (an
|
||||
image) reflecting the supplied ``filter`` value and focal point values
|
||||
|
@ -486,7 +487,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
|
||||
return rendition
|
||||
|
||||
def find_existing_rendition(self, filter: "Filter") -> "AbstractRendition":
|
||||
def find_existing_rendition(self, filter: Filter) -> AbstractRendition:
|
||||
"""
|
||||
Returns an existing ``Rendition`` instance with a ``file`` field value
|
||||
(an image) reflecting the supplied ``filter`` value and focal point
|
||||
|
@ -505,7 +506,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
except KeyError:
|
||||
raise Rendition.DoesNotExist
|
||||
|
||||
def create_rendition(self, filter: "Filter") -> "AbstractRendition":
|
||||
def create_rendition(self, filter: Filter) -> AbstractRendition:
|
||||
"""
|
||||
Creates and returns a ``Rendition`` instance with a ``file`` field
|
||||
value (an image) reflecting the supplied ``filter`` value and focal
|
||||
|
@ -526,9 +527,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
)
|
||||
return rendition
|
||||
|
||||
def get_renditions(
|
||||
self, *filters: Union["Filter", str]
|
||||
) -> Dict[str, "AbstractRendition"]:
|
||||
def get_renditions(self, *filters: Filter | str) -> dict[str, AbstractRendition]:
|
||||
"""
|
||||
Returns a ``dict`` of ``Rendition`` instances with image files reflecting
|
||||
the supplied ``filters``, keyed by filter spec patterns.
|
||||
|
@ -566,8 +565,8 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
return {filter.spec: renditions[filter] for filter in filters}
|
||||
|
||||
def find_existing_renditions(
|
||||
self, *filters: "Filter"
|
||||
) -> Dict["Filter", "AbstractRendition"]:
|
||||
self, *filters: Filter
|
||||
) -> dict[Filter, AbstractRendition]:
|
||||
"""
|
||||
Returns a dictionary of existing ``Rendition`` instances with ``file``
|
||||
values (images) reflecting the supplied ``filters`` and the focal point
|
||||
|
@ -578,8 +577,8 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
created before, the return value will be an empty dict.
|
||||
"""
|
||||
Rendition = self.get_rendition_model()
|
||||
filters_by_spec: Dict[str, Filter] = {f.spec: f for f in filters}
|
||||
found: Dict[Filter, AbstractRendition] = {}
|
||||
filters_by_spec: dict[str, Filter] = {f.spec: f for f in filters}
|
||||
found: dict[Filter, AbstractRendition] = {}
|
||||
|
||||
# Interrogate prefetched values first (where available)
|
||||
prefetched_renditions = self._get_prefetched_renditions()
|
||||
|
@ -589,7 +588,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
# prefetched value, and further cache/database lookups are avoided.
|
||||
|
||||
# group renditions by the filters of interest
|
||||
potential_matches: Dict[Filter, List[AbstractRendition]] = defaultdict(list)
|
||||
potential_matches: dict[Filter, list[AbstractRendition]] = defaultdict(list)
|
||||
for rendition in prefetched_renditions:
|
||||
try:
|
||||
filter = filters_by_spec[rendition.filter_spec]
|
||||
|
@ -637,9 +636,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
found[filter] = rendition
|
||||
return found
|
||||
|
||||
def create_renditions(
|
||||
self, *filters: "Filter"
|
||||
) -> Dict["Filter", "AbstractRendition"]:
|
||||
def create_renditions(self, *filters: Filter) -> dict[Filter, AbstractRendition]:
|
||||
"""
|
||||
Creates multiple ``Rendition`` instances with image files reflecting the supplied
|
||||
``filters``, and returns them as a ``dict`` keyed by the relevant ``Filter`` instance.
|
||||
|
@ -664,8 +661,8 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
filter = filters[0]
|
||||
return {filter: self.create_rendition(filter)}
|
||||
|
||||
return_value: Dict[Filter, AbstractRendition] = {}
|
||||
filter_map: Dict[str, Filter] = {f.spec: f for f in filters}
|
||||
return_value: dict[Filter, AbstractRendition] = {}
|
||||
filter_map: dict[str, Filter] = {f.spec: f for f in filters}
|
||||
|
||||
# Read file contents into memory
|
||||
with self.open_file() as file:
|
||||
|
@ -688,7 +685,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
# identical renditions in the meantime, we should find them to avoid clashes.
|
||||
# NB: Clashes can still occur, because there is no get_or_create() equivalent
|
||||
# for multiple objects. However, this will reduce that risk considerably.
|
||||
files_for_deletion: List[File] = []
|
||||
files_for_deletion: list[File] = []
|
||||
|
||||
# Assemble Q() to identify potential clashes
|
||||
lookup_q = Q()
|
||||
|
@ -724,8 +721,8 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
return return_value
|
||||
|
||||
def generate_rendition_instance(
|
||||
self, filter: "Filter", source: BytesIO
|
||||
) -> "AbstractRendition":
|
||||
self, filter: Filter, source: BytesIO
|
||||
) -> AbstractRendition:
|
||||
"""
|
||||
Use the supplied ``source`` image to create and return an
|
||||
**unsaved** ``Rendition`` instance, with a ``file`` value reflecting
|
||||
|
@ -740,7 +737,7 @@ class AbstractImage(ImageFileMixin, CollectionMember, index.Indexed, models.Mode
|
|||
),
|
||||
)
|
||||
|
||||
def generate_rendition_file(self, filter: "Filter", *, source: File = None) -> File:
|
||||
def generate_rendition_file(self, filter: Filter, *, source: File = None) -> File:
|
||||
"""
|
||||
Generates an in-memory image matching the supplied ``filter`` value
|
||||
and focal point value from this object, wraps it in a ``File`` object
|
||||
|
@ -877,7 +874,7 @@ class Filter:
|
|||
self.spec = spec
|
||||
|
||||
@classmethod
|
||||
def expand_spec(self, spec: Union["str", Iterable["str"]]) -> List["str"]:
|
||||
def expand_spec(self, spec: str | Iterable[str]) -> list[str]:
|
||||
"""
|
||||
Converts a spec pattern with brace-expansions, into a list of spec patterns.
|
||||
For example, "width-{100,200}" becomes ["width-100", "width-200"].
|
||||
|
@ -1092,14 +1089,14 @@ class ResponsiveImage:
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
renditions: Dict[str, "AbstractRendition"],
|
||||
attrs: Optional[Dict[str, Any]] = None,
|
||||
renditions: dict[str, AbstractRendition],
|
||||
attrs: dict[str, Any] | None = None,
|
||||
):
|
||||
self.renditions = list(renditions.values())
|
||||
self.attrs = attrs
|
||||
|
||||
@classmethod
|
||||
def get_width_srcset(cls, renditions_list: List["AbstractRendition"]):
|
||||
def get_width_srcset(cls, renditions_list: list[AbstractRendition]):
|
||||
if len(renditions_list) == 1:
|
||||
# No point in using width descriptors if there is a single image.
|
||||
return renditions_list[0].url
|
||||
|
@ -1122,7 +1119,7 @@ class ResponsiveImage:
|
|||
def __bool__(self):
|
||||
return bool(self.renditions)
|
||||
|
||||
def __eq__(self, other: "ResponsiveImage"):
|
||||
def __eq__(self, other: ResponsiveImage):
|
||||
if isinstance(other, ResponsiveImage):
|
||||
return self.renditions == other.renditions and self.attrs == other.attrs
|
||||
return False
|
||||
|
@ -1138,16 +1135,16 @@ class Picture(ResponsiveImage):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
renditions: Dict[str, "AbstractRendition"],
|
||||
attrs: Optional[Dict[str, Any]] = None,
|
||||
renditions: dict[str, AbstractRendition],
|
||||
attrs: dict[str, Any] | None = None,
|
||||
):
|
||||
super().__init__(renditions, attrs)
|
||||
# Store renditions grouped by format separately for access from templates.
|
||||
self.formats = self.get_formats(renditions)
|
||||
|
||||
def get_formats(
|
||||
self, renditions: Dict[str, "AbstractRendition"]
|
||||
) -> Dict[str, List["AbstractRendition"]]:
|
||||
self, renditions: dict[str, AbstractRendition]
|
||||
) -> dict[str, list[AbstractRendition]]:
|
||||
"""
|
||||
Group renditions by the format they are for, if any.
|
||||
If there is only one format, no grouping is required.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from wagtail.images import get_image_model
|
||||
from wagtail.images.formats import get_image_format
|
||||
from wagtail.rich_text import EmbedHandler
|
||||
|
@ -19,7 +17,7 @@ class ImageEmbedHandler(EmbedHandler):
|
|||
return cls.expand_db_attributes_many([attrs])[0]
|
||||
|
||||
@classmethod
|
||||
def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
|
||||
def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
|
||||
"""
|
||||
Given a dict of attributes from the <embed> tag, return the real HTML
|
||||
representation for use on the front-end.
|
||||
|
|
|
@ -193,7 +193,7 @@ def get_default_page_content_type():
|
|||
return ContentType.objects.get_for_model(Page)
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
@functools.cache
|
||||
def get_streamfield_names(model_class):
|
||||
return tuple(
|
||||
field.name
|
||||
|
@ -1295,7 +1295,7 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
|
|||
private_page_options = ["password", "groups", "login"]
|
||||
|
||||
@staticmethod
|
||||
def route_for_request(request: "HttpRequest", path: str) -> RouteResult | None:
|
||||
def route_for_request(request: HttpRequest, path: str) -> RouteResult | None:
|
||||
"""
|
||||
Find the page route for the given HTTP request object, and URL path. The route
|
||||
result (`page`, `args`, and `kwargs`) will be cached via
|
||||
|
@ -1322,7 +1322,7 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
|
|||
return request._wagtail_route_for_request
|
||||
|
||||
@staticmethod
|
||||
def find_for_request(request: "HttpRequest", path: str) -> "Page" | None:
|
||||
def find_for_request(request: HttpRequest, path: str) -> Page | None:
|
||||
"""
|
||||
Find the page for the given HTTP request object, and URL path. The full
|
||||
page route will be cached via `request._wagtail_route_for_request`
|
||||
|
|
|
@ -158,9 +158,7 @@ class BaseLogEntryManager(models.Manager):
|
|||
content_type = ContentType.objects.get_for_id(
|
||||
permission.content_type_id
|
||||
)
|
||||
if user.has_perm(
|
||||
"%s.%s" % (content_type.app_label, permission.codename)
|
||||
):
|
||||
if user.has_perm(f"{content_type.app_label}.{permission.codename}"):
|
||||
allowed_content_type_ids.add(permission.content_type_id)
|
||||
|
||||
user._allowed_content_type_ids = allowed_content_type_ids
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import uuid
|
||||
from typing import Dict
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
|
@ -98,7 +97,7 @@ class Locale(models.Model):
|
|||
def __str__(self):
|
||||
return force_str(self.get_display_name())
|
||||
|
||||
def _get_language_info(self) -> Dict[str, str]:
|
||||
def _get_language_info(self) -> dict[str, str]:
|
||||
return translation.get_language_info(self.language_code)
|
||||
|
||||
@property
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import posixpath
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from typing import Any, Dict, Iterable, Tuple
|
||||
from collections.abc import Iterable
|
||||
from typing import Any
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
@ -588,7 +589,7 @@ class SpecificIterable(BaseIterable):
|
|||
setattr(item, annotation, value)
|
||||
yield item
|
||||
|
||||
def _get_chunks(self, queryset) -> Iterable[Tuple[Dict[str, Any]]]:
|
||||
def _get_chunks(self, queryset) -> Iterable[tuple[dict[str, Any]]]:
|
||||
if not self.chunked_fetch:
|
||||
# The entire result will be stored in memory, so there is no
|
||||
# benefit to splitting the result
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import re
|
||||
from functools import lru_cache
|
||||
from html import unescape
|
||||
from typing import List
|
||||
|
||||
from django.core.validators import MaxLengthValidator
|
||||
from django.db.models import Model
|
||||
|
@ -132,7 +131,7 @@ class EntityHandler:
|
|||
return model._default_manager.get(id=attrs["id"])
|
||||
|
||||
@classmethod
|
||||
def get_many(cls, attrs_list: List[dict]) -> List[Model]:
|
||||
def get_many(cls, attrs_list: list[dict]) -> list[Model]:
|
||||
model = cls.get_model()
|
||||
instance_ids = [attrs.get("id") for attrs in attrs_list]
|
||||
instances_by_id = model._default_manager.in_bulk(instance_ids)
|
||||
|
@ -148,7 +147,7 @@ class EntityHandler:
|
|||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
|
||||
def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
|
||||
"""
|
||||
Given a list of attribute dicts from a list of entity tags stored in
|
||||
the database, return the real HTML representation of each one.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from django.db.models import Model
|
||||
from django.utils.html import escape
|
||||
|
||||
|
@ -15,7 +13,7 @@ class PageLinkHandler(LinkHandler):
|
|||
return Page
|
||||
|
||||
@classmethod
|
||||
def get_many(cls, attrs_list: List[dict]) -> List[Model]:
|
||||
def get_many(cls, attrs_list: list[dict]) -> list[Model]:
|
||||
# Override LinkHandler.get_many to reduce database queries through the
|
||||
# use of PageQuerySet.specific() instead of QuerySet.in_bulk().
|
||||
instance_ids = [attrs.get("id") for attrs in attrs_list]
|
||||
|
@ -28,7 +26,7 @@ class PageLinkHandler(LinkHandler):
|
|||
return cls.expand_db_attributes_many([attrs])[0]
|
||||
|
||||
@classmethod
|
||||
def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
|
||||
def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
|
||||
return [
|
||||
'<a href="%s">' % escape(page.localized.url) if page else "<a>"
|
||||
for page in cls.get_many(attrs_list)
|
||||
|
|
|
@ -4,7 +4,7 @@ Utility classes for rewriting elements of HTML-like strings
|
|||
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from typing import Callable, Dict, List
|
||||
from typing import Callable
|
||||
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
|
@ -101,7 +101,7 @@ class TagRewriter:
|
|||
|
||||
return html
|
||||
|
||||
def extract_tags(self, html: str) -> Dict[str, List[TagMatch]]:
|
||||
def extract_tags(self, html: str) -> dict[str, list[TagMatch]]:
|
||||
"""Helper method to extract and group HTML tags and their attributes.
|
||||
|
||||
Returns a dict of TagMatch objects, mapping tag types to a list of all TagMatch objects of that tag type.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import re
|
||||
from typing import Any, List, Tuple, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from django.db.backends.base.base import BaseDatabaseWrapper
|
||||
from django.db.models.expressions import CombinedExpression, Expression, Value
|
||||
|
@ -166,7 +166,7 @@ class SearchQuery(SearchQueryCombinable, Expression):
|
|||
compiler: SQLCompiler,
|
||||
connection: BaseDatabaseWrapper,
|
||||
**extra_context: Any,
|
||||
) -> Tuple[str, List[Any]]:
|
||||
) -> tuple[str, list[Any]]:
|
||||
sql, params = compiler.compile(self.value)
|
||||
return (sql, params)
|
||||
|
||||
|
@ -229,7 +229,7 @@ class MatchExpression(Expression):
|
|||
def __init__(
|
||||
self,
|
||||
query: SearchQueryCombinable,
|
||||
columns: List[str] = None,
|
||||
columns: list[str] = None,
|
||||
output_field: Field = BooleanField(),
|
||||
) -> None:
|
||||
super().__init__(output_field=output_field)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, List, Tuple
|
||||
from typing import Any
|
||||
|
||||
from django.db.backends.base.base import BaseDatabaseWrapper
|
||||
from django.db.models.expressions import CombinedExpression, Expression, Func, Value
|
||||
|
@ -149,7 +149,7 @@ class SearchQueryExpression(SearchQueryCombinable, Expression):
|
|||
compiler: SQLCompiler,
|
||||
connection: BaseDatabaseWrapper,
|
||||
**extra_context: Any,
|
||||
) -> Tuple[str, List[Any]]:
|
||||
) -> tuple[str, list[Any]]:
|
||||
sql, params = compiler.compile(self.value)
|
||||
return (sql, params)
|
||||
|
||||
|
@ -172,7 +172,7 @@ class MatchExpression(Expression):
|
|||
)
|
||||
output_field = BooleanField()
|
||||
|
||||
def __init__(self, columns: List[str], query: SearchQueryCombinable) -> None:
|
||||
def __init__(self, columns: list[str], query: SearchQueryCombinable) -> None:
|
||||
super().__init__(output_field=self.output_field)
|
||||
self.columns = columns
|
||||
self.query = query
|
||||
|
@ -211,7 +211,7 @@ class AndNot(SearchQuery):
|
|||
return f"<{repr(self.subquery_a)} AndNot {repr(self.subquery_b)}>"
|
||||
|
||||
|
||||
def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
|
||||
def normalize(search_query: SearchQuery) -> tuple[SearchQuery]:
|
||||
"""
|
||||
Turns this query into a normalized version.
|
||||
For example, And(Not(PlainText("Arepa")), PlainText("Crepe")) would be turned into AndNot(PlainText("Crepe"), PlainText("Arepa")): "Crepe AND NOT Arepa".
|
||||
|
@ -222,7 +222,7 @@ def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
|
|||
if isinstance(search_query, PlainText):
|
||||
return search_query # We can't normalize a PlainText.
|
||||
if isinstance(search_query, And):
|
||||
normalized_subqueries: List[SearchQuery] = [
|
||||
normalized_subqueries: list[SearchQuery] = [
|
||||
normalize(subquery) for subquery in search_query.subqueries
|
||||
] # This builds a list of normalized subqueries.
|
||||
|
||||
|
@ -255,7 +255,7 @@ def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
|
|||
|
||||
return AndNot(And(not_negated_subqueries), Or(negated_subqueries))
|
||||
if isinstance(search_query, Or):
|
||||
normalized_subqueries: List[SearchQuery] = [
|
||||
normalized_subqueries: list[SearchQuery] = [
|
||||
normalize(subquery) for subquery in search_query.subqueries
|
||||
] # This builds a list of (subquery, negated) tuples.
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class CustomRichTextArea(widgets.Textarea):
|
|||
# mock rendering for individual custom widget
|
||||
|
||||
return mark_safe(
|
||||
'<template data-controller="custom-editor" data-id="{0}">{1}</template>'.format(
|
||||
'<template data-controller="custom-editor" data-id="{}">{}</template>'.format(
|
||||
attrs["id"],
|
||||
super().render(name, value, attrs),
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ class LegacyRichTextArea(widgets.Textarea):
|
|||
def render(self, name, value, attrs=None, renderer=None):
|
||||
# mock rendering for individual custom widget
|
||||
return mark_safe(
|
||||
'<template data-controller="legacy-editor" data-id="{0}">{1}</template>'.format(
|
||||
'<template data-controller="legacy-editor" data-id="{}">{}</template>'.format(
|
||||
attrs["id"],
|
||||
super().render(name, value, attrs),
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Optional
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -217,8 +217,8 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
|
|||
self,
|
||||
page: Page,
|
||||
route_path: Optional[str] = "/",
|
||||
query_data: Optional[Dict[str, Any]] = None,
|
||||
post_data: Optional[Dict[str, Any]] = None,
|
||||
query_data: Optional[dict[str, Any]] = None,
|
||||
post_data: Optional[dict[str, Any]] = None,
|
||||
user: Optional[AbstractBaseUser] = None,
|
||||
accept_404: Optional[bool] = False,
|
||||
accept_redirect: Optional[bool] = False,
|
||||
|
@ -297,7 +297,7 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
|
|||
def assertPageIsEditable(
|
||||
self,
|
||||
page: Page,
|
||||
post_data: Optional[Dict[str, Any]] = None,
|
||||
post_data: Optional[dict[str, Any]] = None,
|
||||
user: Optional[AbstractBaseUser] = None,
|
||||
msg: Optional[str] = None,
|
||||
):
|
||||
|
@ -379,7 +379,7 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
|
|||
self,
|
||||
page: Page,
|
||||
mode: Optional[str] = "",
|
||||
post_data: Optional[Dict[str, Any]] = None,
|
||||
post_data: Optional[dict[str, Any]] = None,
|
||||
user: Optional[AbstractBaseUser] = None,
|
||||
msg: Optional[str] = None,
|
||||
):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Dict, List, Union
|
||||
from typing import Union
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
@ -10,7 +10,7 @@ class AdminTemplateTestUtils:
|
|||
|
||||
def assertBreadcrumbsItemsRendered(
|
||||
self: Union[WagtailTestUtils, SimpleTestCase],
|
||||
items: List[Dict[str, str]],
|
||||
items: list[dict[str, str]],
|
||||
html: Union[str, bytes],
|
||||
):
|
||||
soup = self.get_soup(html)
|
||||
|
|
Ładowanie…
Reference in New Issue