Refs #36500 -- Rewrapped long docstrings and block comments via a script.

Rewrapped long docstrings and block comments to 79 characters + newline
using script from https://github.com/medmunds/autofix-w505.
This commit is contained in:
django-bot 2025-07-22 20:41:41 -07:00 committed by nessita
parent 55b0cc2131
commit 69a93a88ed
378 changed files with 2781 additions and 1861 deletions

View file

@ -288,9 +288,9 @@ class Apps:
referred model is not swappable, return None. referred model is not swappable, return None.
This method is decorated with @functools.cache because it's performance This method is decorated with @functools.cache because it's performance
critical when it comes to migrations. Since the swappable settings don't critical when it comes to migrations. Since the swappable settings
change after Django has loaded the settings, there is no reason to get don't change after Django has loaded the settings, there is no reason
the respective settings attribute over and over again. to get the respective settings attribute over and over again.
""" """
to_string = to_string.lower() to_string = to_string.lower()
for model in self.get_models(include_swapped=True): for model in self.get_models(include_swapped=True):
@ -378,8 +378,9 @@ class Apps:
# the relation tree and the fields cache. # the relation tree and the fields cache.
self.get_models.cache_clear() self.get_models.cache_clear()
if self.ready: if self.ready:
# Circumvent self.get_models() to prevent that the cache is refilled. # Circumvent self.get_models() to prevent that the cache is
# This particularly prevents that an empty value is cached while cloning. # refilled. This particularly prevents that an empty value is
# cached while cloning.
for app_config in self.app_configs.values(): for app_config in self.app_configs.values():
for model in app_config.get_models(include_auto_created=True): for model in app_config.get_models(include_auto_created=True):
model._meta._expire_cache() model._meta._expire_cache()

View file

@ -77,7 +77,8 @@ class LazySettings(LazyObject):
val = getattr(_wrapped, name) val = getattr(_wrapped, name)
# Special case some settings which require further modification. # Special case some settings which require further modification.
# This is done here for performance reasons so the modified value is cached. # This is done here for performance reasons so the modified value is
# cached.
if name in {"MEDIA_URL", "STATIC_URL"} and val is not None: if name in {"MEDIA_URL", "STATIC_URL"} and val is not None:
val = self._add_script_prefix(val) val = self._add_script_prefix(val)
elif name == "SECRET_KEY" and not val: elif name == "SECRET_KEY" and not val:
@ -149,7 +150,8 @@ class LazySettings(LazyObject):
class Settings: class Settings:
def __init__(self, settings_module): def __init__(self, settings_module):
# update this dict from global settings (but only for ALL_CAPS settings) # update this dict from global settings (but only for ALL_CAPS
# settings)
for setting in dir(global_settings): for setting in dir(global_settings):
if setting.isupper(): if setting.isupper():
setattr(self, setting, getattr(global_settings, setting)) setattr(self, setting, getattr(global_settings, setting))

View file

@ -317,9 +317,9 @@ DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000
# before a SuspiciousOperation (TooManyFilesSent) is raised. # before a SuspiciousOperation (TooManyFilesSent) is raised.
DATA_UPLOAD_MAX_NUMBER_FILES = 100 DATA_UPLOAD_MAX_NUMBER_FILES = 100
# Directory in which upload streamed files will be temporarily saved. A value of # Directory in which upload streamed files will be temporarily saved. A value
# `None` will make Django use the operating system's default temporary directory # of `None` will make Django use the operating system's default temporary
# (i.e. "/tmp" on *nix systems). # directory (i.e. "/tmp" on *nix systems).
FILE_UPLOAD_TEMP_DIR = None FILE_UPLOAD_TEMP_DIR = None
# The numeric mode to set newly-uploaded files to. The value should be a mode # The numeric mode to set newly-uploaded files to. The value should be a mode
@ -327,9 +327,9 @@ FILE_UPLOAD_TEMP_DIR = None
# https://docs.python.org/library/os.html#files-and-directories. # https://docs.python.org/library/os.html#files-and-directories.
FILE_UPLOAD_PERMISSIONS = 0o644 FILE_UPLOAD_PERMISSIONS = 0o644
# The numeric mode to assign to newly-created directories, when uploading files. # The numeric mode to assign to newly-created directories, when uploading
# The value should be a mode as you'd pass to os.chmod; # files. The value should be a mode as you'd pass to os.chmod; see
# see https://docs.python.org/library/os.html#files-and-directories. # https://docs.python.org/library/os.html#files-and-directories.
FILE_UPLOAD_DIRECTORY_PERMISSIONS = None FILE_UPLOAD_DIRECTORY_PERMISSIONS = None
# Python module path where user will place custom format definition. # Python module path where user will place custom format definition.
@ -342,7 +342,8 @@ FORMAT_MODULE_PATH = None
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
DATE_FORMAT = "N j, Y" DATE_FORMAT = "N j, Y"
# Default formatting for datetime objects. See all available format strings here: # Default formatting for datetime objects. See all available format strings
# here:
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
DATETIME_FORMAT = "N j, Y, P" DATETIME_FORMAT = "N j, Y, P"
@ -350,8 +351,8 @@ DATETIME_FORMAT = "N j, Y, P"
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
TIME_FORMAT = "P" TIME_FORMAT = "P"
# Default formatting for date objects when only the year and month are relevant. # Default formatting for date objects when only the year and month are
# See all available format strings here: # relevant. See all available format strings here:
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
YEAR_MONTH_FORMAT = "F Y" YEAR_MONTH_FORMAT = "F Y"
@ -360,7 +361,8 @@ YEAR_MONTH_FORMAT = "F Y"
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
MONTH_DAY_FORMAT = "F j" MONTH_DAY_FORMAT = "F j"
# Default short formatting for date objects. See all available format strings here: # Default short formatting for date objects. See all available format strings
# here:
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
SHORT_DATE_FORMAT = "m/d/Y" SHORT_DATE_FORMAT = "m/d/Y"

View file

@ -1,10 +1,11 @@
""" """
LANG_INFO is a dictionary structure to provide meta information about languages. LANG_INFO is a dictionary structure to provide meta information about
languages.
About name_local: capitalize it as if your language name was appearing About name_local: capitalize it as if your language name was appearing
inside a sentence in your language. inside a sentence in your language.
The 'fallback' key can be used to specify a special fallback logic which doesn't The 'fallback' key can be used to specify a special fallback logic which
follow the traditional 'fr-ca' -> 'fr' fallback logic. doesn't follow the traditional 'fr-ca' -> 'fr' fallback logic.
""" """
LANG_INFO = { LANG_INFO = {

View file

@ -24,7 +24,8 @@ def delete_selected(modeladmin, request, queryset):
deletable objects, or, if the user has no permission one of the related deletable objects, or, if the user has no permission one of the related
childs (foreignkeys), a "permission denied" message. childs (foreignkeys), a "permission denied" message.
Next, it deletes all selected objects and redirects back to the change list. Next, it deletes all selected objects and redirects back to the change
list.
""" """
opts = modeladmin.model._meta opts = modeladmin.model._meta
app_label = opts.app_label app_label = opts.app_label

View file

@ -316,7 +316,8 @@ class BaseModelAdminChecks:
def _check_fields(self, obj): def _check_fields(self, obj):
"""Check that `fields` only refer to existing fields, doesn't contain """Check that `fields` only refer to existing fields, doesn't contain
duplicates. Check if at most one of `fields` and `fieldsets` is defined. duplicates. Check if at most one of `fields` and `fieldsets` is
defined.
""" """
if obj.fields is None: if obj.fields is None:

View file

@ -170,10 +170,10 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
# ForeignKey or ManyToManyFields # ForeignKey or ManyToManyFields
if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
# Combine the field kwargs with any options for formfield_overrides. # Combine the field kwargs with any options for
# Make sure the passed in **kwargs override anything in # formfield_overrides. Make sure the passed in **kwargs override
# formfield_overrides because **kwargs is more specific, and should # anything in formfield_overrides because **kwargs is more
# always win. # specific, and should always win.
if db_field.__class__ in self.formfield_overrides: if db_field.__class__ in self.formfield_overrides:
kwargs = {**self.formfield_overrides[db_field.__class__], **kwargs} kwargs = {**self.formfield_overrides[db_field.__class__], **kwargs}
@ -2182,8 +2182,8 @@ class ModelAdmin(BaseModelAdmin):
if obj is None: if obj is None:
return self._get_obj_does_not_exist_redirect(request, self.opts, object_id) return self._get_obj_does_not_exist_redirect(request, self.opts, object_id)
# Populate deleted_objects, a data structure of all related objects that # Populate deleted_objects, a data structure of all related objects
# will also be deleted. # that will also be deleted.
( (
deleted_objects, deleted_objects,
model_count, model_count,

View file

@ -29,11 +29,11 @@ all_sites = WeakSet()
class AdminSite: class AdminSite:
""" """
An AdminSite object encapsulates an instance of the Django admin application, ready An AdminSite object encapsulates an instance of the Django admin
to be hooked in to your URLconf. Models are registered with the AdminSite using the application, ready to be hooked in to your URLconf. Models are registered
register() method, and the get_urls() method can then be used to access Django view with the AdminSite using the register() method, and the get_urls() method
functions that present a full admin interface for the collection of registered can then be used to access Django view functions that present a full admin
models. interface for the collection of registered models.
""" """
# Text to put at the end of each page's <title>. # Text to put at the end of each page's <title>.
@ -136,9 +136,9 @@ class AdminSite:
# If we got **options then dynamically construct a subclass of # If we got **options then dynamically construct a subclass of
# admin_class with those **options. # admin_class with those **options.
if options: if options:
# For reasons I don't quite understand, without a __module__ # For reasons I don't quite understand, without a
# the created class appears to "live" in the wrong place, # __module__ the created class appears to "live" in the
# which causes issues later on. # wrong place, which causes issues later on.
options["__module__"] = __name__ options["__module__"] = __name__
admin_class = type( admin_class = type(
"%sAdmin" % model.__name__, (admin_class,), options "%sAdmin" % model.__name__, (admin_class,), options

View file

@ -256,7 +256,8 @@ def items_for_result(cl, result, form):
): ):
row_classes.append("nowrap") row_classes.append("nowrap")
row_class = mark_safe(' class="%s"' % " ".join(row_classes)) row_class = mark_safe(' class="%s"' % " ".join(row_classes))
# If list_display_links not defined, add the link tag to the first field # If list_display_links not defined, add the link tag to the first
# field
if link_to_changelist: if link_to_changelist:
table_tag = "th" if first else "td" table_tag = "th" if first else "td"
first = False first = False
@ -293,9 +294,9 @@ def items_for_result(cl, result, form):
"<{}{}>{}</{}>", table_tag, row_class, link_or_text, table_tag "<{}{}>{}</{}>", table_tag, row_class, link_or_text, table_tag
) )
else: else:
# By default the fields come from ModelAdmin.list_editable, but if we pull # By default the fields come from ModelAdmin.list_editable, but if
# the fields out of the form instead of list_editable custom admins # we pull the fields out of the form instead of list_editable
# can provide fields on a per request basis # custom admins can provide fields on a per request basis
if ( if (
form form
and field_name in form.fields and field_name in form.fields

View file

@ -218,9 +218,9 @@ class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase):
actual_values.append(option.get_attribute("value")) actual_values.append(option.get_attribute("value"))
self.assertEqual(values, actual_values) self.assertEqual(values, actual_values)
else: else:
# Prevent the `find_elements(By.CSS_SELECTOR, …)` call from blocking # Prevent the `find_elements(By.CSS_SELECTOR, …)` call from
# if the selector doesn't match any options as we expect it # blocking if the selector doesn't match any options as we expect
# to be the case. # it to be the case.
with self.disable_implicit_wait(): with self.disable_implicit_wait():
self.wait_until( self.wait_until(
lambda driver: not driver.find_elements( lambda driver: not driver.find_elements(

View file

@ -73,7 +73,8 @@ def prepare_lookup_value(key, value, separator=","):
# if key ends with __in, split parameter into separate values # if key ends with __in, split parameter into separate values
if key.endswith("__in"): if key.endswith("__in"):
value = value.split(separator) value = value.split(separator)
# if key ends with __isnull, special case '' and the string literals 'false' and '0' # if key ends with __isnull, special case '' and the string literals
# 'false' and '0'
elif key.endswith("__isnull"): elif key.endswith("__isnull"):
value = value.lower() not in ("", "false", "0") value = value.lower() not in ("", "false", "0")
return value return value
@ -558,9 +559,10 @@ def construct_change_message(form, formsets, add):
Translations are deactivated so that strings are stored untranslated. Translations are deactivated so that strings are stored untranslated.
Translation happens later on LogEntry access. Translation happens later on LogEntry access.
""" """
# Evaluating `form.changed_data` prior to disabling translations is required # Evaluating `form.changed_data` prior to disabling translations is
# to avoid fields affected by localization from being included incorrectly, # required to avoid fields affected by localization from being included
# e.g. where date formats differ such as MM/DD/YYYY vs DD/MM/YYYY. # incorrectly, e.g. where date formats differ such as MM/DD/YYYY vs
# DD/MM/YYYY.
changed_data = form.changed_data changed_data = form.changed_data
with translation_override(None): with translation_override(None):
# Deactivate translations while fetching verbose_name for form # Deactivate translations while fetching verbose_name for form

View file

@ -322,7 +322,8 @@ class ChangeList:
self.result_count = result_count self.result_count = result_count
self.show_full_result_count = self.model_admin.show_full_result_count self.show_full_result_count = self.model_admin.show_full_result_count
# Admin actions are shown if there is at least one entry # Admin actions are shown if there is at least one entry
# or if entries are not counted because show_full_result_count is disabled # or if entries are not counted because show_full_result_count is
# disabled
self.show_admin_actions = not self.show_full_result_count or bool( self.show_admin_actions = not self.show_full_result_count or bool(
full_result_count full_result_count
) )
@ -485,8 +486,8 @@ class ChangeList:
""" """
Return a dictionary of ordering field column numbers and asc/desc. Return a dictionary of ordering field column numbers and asc/desc.
""" """
# We must cope with more than one column having the same underlying sort # We must cope with more than one column having the same underlying
# field, so we base things on column numbers. # sort field, so we base things on column numbers.
ordering = self._get_default_ordering() ordering = self._get_default_ordering()
ordering_fields = {} ordering_fields = {}
if ORDER_VAR not in self.params: if ORDER_VAR not in self.params:

View file

@ -215,8 +215,8 @@ class ForeignKeyRawIdWidget(forms.TextInput):
class ManyToManyRawIdWidget(ForeignKeyRawIdWidget): class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
""" """
A Widget for displaying ManyToMany ids in the "raw_id" interface rather than A Widget for displaying ManyToMany ids in the "raw_id" interface rather
in a <select multiple> box. than in a <select multiple> box.
""" """
template_name = "admin/widgets/many_to_many_raw_id.html" template_name = "admin/widgets/many_to_many_raw_id.html"
@ -275,7 +275,8 @@ class RelatedFieldWidgetWrapper(forms.Widget):
if not isinstance(widget, AutocompleteMixin): if not isinstance(widget, AutocompleteMixin):
self.attrs["data-context"] = "available-source" self.attrs["data-context"] = "available-source"
self.can_change_related = not multiple and can_change_related self.can_change_related = not multiple and can_change_related
# XXX: The deletion UX can be confusing when dealing with cascading deletion. # XXX: The deletion UX can be confusing when dealing with cascading
# deletion.
cascade = getattr(rel, "on_delete", None) is CASCADE cascade = getattr(rel, "on_delete", None) is CASCADE
self.can_delete_related = not multiple and not cascade and can_delete_related self.can_delete_related = not multiple and not cascade and can_delete_related
self.can_view_related = not multiple and can_view_related self.can_view_related = not multiple and can_view_related

View file

@ -69,8 +69,8 @@ def parse_rst(text, default_reference_context, thing_being_parsed=None):
"file_insertion_enabled": False, "file_insertion_enabled": False,
} }
thing_being_parsed = thing_being_parsed and "<%s>" % thing_being_parsed thing_being_parsed = thing_being_parsed and "<%s>" % thing_being_parsed
# Wrap ``text`` in some reST that sets the default role to ``cmsreference``, # Wrap ``text`` in some reST that sets the default role to
# then restores it. # ``cmsreference``, then restores it.
source = """ source = """
.. default-role:: cmsreference .. default-role:: cmsreference

View file

@ -33,7 +33,8 @@ class AccessMixin:
def get_permission_denied_message(self): def get_permission_denied_message(self):
""" """
Override this method to override the permission_denied_message attribute. Override this method to override the permission_denied_message
attribute.
""" """
return self.permission_denied_message return self.permission_denied_message

View file

@ -227,7 +227,8 @@ class CommonPasswordValidator:
The password is rejected if it occurs in a provided list of passwords, The password is rejected if it occurs in a provided list of passwords,
which may be gzipped. The list Django ships with contains 20000 common which may be gzipped. The list Django ships with contains 20000 common
passwords (unhexed, lowercased and deduplicated), created by Royce Williams: passwords (unhexed, lowercased and deduplicated), created by Royce
Williams:
https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce
The password list must be lowercased to match the comparison in validate(). The password list must be lowercased to match the comparison in validate().
""" """

View file

@ -1,7 +1,7 @@
# The views used below are normally mapped in the AdminSite instance. # The views used below are normally mapped in the AdminSite instance.
# This URLs file is used to provide a reliable view deployment for test purposes. # This URLs file is used to provide a reliable view deployment for test
# It is also provided as a convenience to those who want to deploy these URLs # purposes. It is also provided as a convenience to those who want to deploy
# elsewhere. # these URLs elsewhere.
from django.contrib.auth import views from django.contrib.auth import views
from django.urls import path from django.urls import path

View file

@ -67,8 +67,8 @@ class GenericInlineModelAdminChecks(InlineModelAdminChecks):
) )
] ]
# There's one or more GenericForeignKeys; make sure that one of them # There's one or more GenericForeignKeys; make sure that one of
# uses the right ct_field and ct_fk_field. # them uses the right ct_field and ct_fk_field.
for gfk in gfks: for gfk in gfks:
if gfk.ct_field == obj.ct_field and gfk.fk_field == obj.ct_fk_field: if gfk.ct_field == obj.ct_field and gfk.fk_field == obj.ct_fk_field:
return [] return []

View file

@ -199,8 +199,9 @@ class GenericForeignKey(FieldCacheMixin, Field):
ct = self.get_content_type(id=ct_id, using=instance._state.db) ct = self.get_content_type(id=ct_id, using=instance._state.db)
ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys)) ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys))
# For doing the join in Python, we have to match both the FK val and the # For doing the join in Python, we have to match both the FK val and
# content type, so we use a callable that returns a (fk, class) pair. # the content type, so we use a callable that returns a (fk, class)
# pair.
def gfk_key(obj): def gfk_key(obj):
ct_id = getattr(obj, ct_attname) ct_id = getattr(obj, ct_attname)
if ct_id is None: if ct_id is None:

View file

@ -8,10 +8,12 @@ from .operations import BaseSpatialOperations
class BaseSpatialFeatures: class BaseSpatialFeatures:
gis_enabled = True gis_enabled = True
# Does the database contain a SpatialRefSys model to store SRID information? # Does the database contain a SpatialRefSys model to store SRID
# information?
has_spatialrefsys_table = True has_spatialrefsys_table = True
# Does the backend support the django.contrib.gis.utils.add_srs_entry() utility? # Does the backend support the django.contrib.gis.utils.add_srs_entry()
# utility?
supports_add_srs_entry = True supports_add_srs_entry = True
# Does the backend introspect GeometryField to its subtypes? # Does the backend introspect GeometryField to its subtypes?
supports_geometry_field_introspection = True supports_geometry_field_introspection = True

View file

@ -28,8 +28,8 @@ class BaseSpatialOperations:
geom_func_prefix = "" geom_func_prefix = ""
# Mapping between Django function names and backend names, when names do not # Mapping between Django function names and backend names, when names do
# match; used in spatial_function_name(). # not match; used in spatial_function_name().
function_names = {} function_names = {}
# Set of known unsupported functions of the backend # Set of known unsupported functions of the backend
@ -79,8 +79,8 @@ class BaseSpatialOperations:
# Constructors # Constructors
from_text = False from_text = False
# Default conversion functions for aggregates; will be overridden if implemented # Default conversion functions for aggregates; will be overridden if
# for the spatial backend. # implemented for the spatial backend.
def convert_extent(self, box, srid): def convert_extent(self, box, srid):
raise NotImplementedError( raise NotImplementedError(
"Aggregate extent not implemented for this spatial backend." "Aggregate extent not implemented for this spatial backend."

View file

@ -17,5 +17,6 @@ class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
@cached_property @cached_property
def supports_geometry_field_unique_index(self): def supports_geometry_field_unique_index(self):
# Not supported in MySQL since https://dev.mysql.com/worklog/task/?id=11808 # Not supported in MySQL since
# https://dev.mysql.com/worklog/task/?id=11808
return self.connection.mysql_is_mariadb return self.connection.mysql_is_mariadb

View file

@ -19,9 +19,9 @@ class MySQLIntrospection(DatabaseIntrospection):
# column. # column.
for column, typ, null, key, default, extra in cursor.fetchall(): for column, typ, null, key, default, extra in cursor.fetchall():
if column == description.name: if column == description.name:
# Using OGRGeomType to convert from OGC name to Django field. # Using OGRGeomType to convert from OGC name to Django
# MySQL does not support 3D or SRIDs, so the field params # field. MySQL does not support 3D or SRIDs, so the field
# are empty. # params are empty.
field_type = OGRGeomType(typ).django field_type = OGRGeomType(typ).django
field_params = {} field_params = {}
break break

View file

@ -17,7 +17,8 @@ class OracleIntrospection(DatabaseIntrospection):
def get_geometry_type(self, table_name, description): def get_geometry_type(self, table_name, description):
with self.connection.cursor() as cursor: with self.connection.cursor() as cursor:
# Querying USER_SDO_GEOM_METADATA to get the SRID and dimension information. # Querying USER_SDO_GEOM_METADATA to get the SRID and dimension
# information.
try: try:
cursor.execute( cursor.execute(
'SELECT "DIMINFO", "SRID" FROM "USER_SDO_GEOM_METADATA" ' 'SELECT "DIMINFO", "SRID" FROM "USER_SDO_GEOM_METADATA" '
@ -31,8 +32,8 @@ class OracleIntrospection(DatabaseIntrospection):
'corresponding to "%s"."%s"' % (table_name, description.name) 'corresponding to "%s"."%s"' % (table_name, description.name)
) from exc ) from exc
# TODO: Research way to find a more specific geometry field type for # TODO: Research way to find a more specific geometry field type
# the column's contents. # for the column's contents.
field_type = "GeometryField" field_type = "GeometryField"
# Getting the field parameters. # Getting the field parameters.

View file

@ -227,8 +227,8 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
return OracleSpatialRefSys return OracleSpatialRefSys
def modify_insert_params(self, placeholder, params): def modify_insert_params(self, placeholder, params):
"""Drop out insert parameters for NULL placeholder. Needed for Oracle Spatial """Drop out insert parameters for NULL placeholder. Needed for Oracle
backend due to #10888. Spatial backend due to #10888.
""" """
if placeholder == "NULL": if placeholder == "NULL":
return [] return []

View file

@ -61,7 +61,8 @@ class PostGISIntrospection(DatabaseIntrospection):
# OGRGeomType does not require GDAL and makes it easy to convert # OGRGeomType does not require GDAL and makes it easy to convert
# from OGC geom type name to Django field. # from OGC geom type name to Django field.
field_type = OGRGeomType(field_type).django field_type = OGRGeomType(field_type).django
# Getting any GeometryField keyword arguments that are not the default. # Getting any GeometryField keyword arguments that are not the
# default.
field_params = {} field_params = {}
if self.postgis_oid_lookup.get(description.type_code) == "geography": if self.postgis_oid_lookup.get(description.type_code) == "geography":
field_params["geography"] = True field_params["geography"] = True

View file

@ -328,7 +328,8 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
def _get_postgis_func(self, func): def _get_postgis_func(self, func):
""" """
Helper routine for calling PostGIS functions and returning their result. Helper routine for calling PostGIS functions and returning their
result.
""" """
# Close out the connection. See #9437. # Close out the connection. See #9437.
with self.connection.temporary_connection() as cursor: with self.connection.temporary_connection() as cursor:
@ -340,7 +341,9 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
return self._get_postgis_func("postgis_geos_version") return self._get_postgis_func("postgis_geos_version")
def postgis_lib_version(self): def postgis_lib_version(self):
"Return the version number of the PostGIS library used with PostgreSQL." """
Return the version number of the PostGIS library used with PostgreSQL.
"""
return self._get_postgis_func("postgis_lib_version") return self._get_postgis_func("postgis_lib_version")
def postgis_proj_version(self): def postgis_proj_version(self):

View file

@ -100,8 +100,9 @@ class PostGISSchemaEditor(DatabaseSchemaEditor):
opclasses = None opclasses = None
fields = [field] fields = [field]
if field.geom_type == "RASTER": if field.geom_type == "RASTER":
# For raster fields, wrap index creation SQL statement with ST_ConvexHull. # For raster fields, wrap index creation SQL statement with
# Indexes on raster columns are based on the convex hull of the raster. # ST_ConvexHull. Indexes on raster columns are based on the convex
# hull of the raster.
expressions = Func(Col(None, field), template=self.rast_index_template) expressions = Func(Col(None, field), template=self.rast_index_template)
fields = None fields = None
elif field.dim > 2 and not field.geography: elif field.dim > 2 and not field.geography:

View file

@ -52,7 +52,8 @@ class SpatiaLiteIntrospection(DatabaseIntrospection):
ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit
field_type = OGRGeomType(ogr_type).django field_type = OGRGeomType(ogr_type).django
# Getting any GeometryField keyword arguments that are not the default. # Getting any GeometryField keyword arguments that are not the
# default.
dim = row[0] dim = row[0]
srid = row[1] srid = row[1]
field_params = {} field_params = {}

View file

@ -48,9 +48,11 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
"relate": SpatialiteNullCheckOperator(func="Relate"), "relate": SpatialiteNullCheckOperator(func="Relate"),
"coveredby": SpatialiteNullCheckOperator(func="CoveredBy"), "coveredby": SpatialiteNullCheckOperator(func="CoveredBy"),
"covers": SpatialiteNullCheckOperator(func="Covers"), "covers": SpatialiteNullCheckOperator(func="Covers"),
# Returns true if B's bounding box completely contains A's bounding box. # Returns true if B's bounding box completely contains A's bounding
# box.
"contained": SpatialOperator(func="MbrWithin"), "contained": SpatialOperator(func="MbrWithin"),
# Returns true if A's bounding box completely contains B's bounding box. # Returns true if A's bounding box completely contains B's bounding
# box.
"bbcontains": SpatialOperator(func="MbrContains"), "bbcontains": SpatialOperator(func="MbrContains"),
# Returns true if A's bounding box overlaps B's bounding box. # Returns true if A's bounding box overlaps B's bounding box.
"bboverlaps": SpatialOperator(func="MbrOverlaps"), "bboverlaps": SpatialOperator(func="MbrOverlaps"),

View file

@ -91,7 +91,8 @@ class SpatialiteSchemaEditor(DatabaseSchemaEditor):
def delete_model(self, model, **kwargs): def delete_model(self, model, **kwargs):
from django.contrib.gis.db.models import GeometryField from django.contrib.gis.db.models import GeometryField
# Drop spatial metadata (dropping the table does not automatically remove them) # Drop spatial metadata (dropping the table does not automatically
# remove them)
for field in model._meta.local_fields: for field in model._meta.local_fields:
if isinstance(field, GeometryField): if isinstance(field, GeometryField):
self.remove_geometry_metadata(model, field) self.remove_geometry_metadata(model, field)
@ -126,9 +127,9 @@ class SpatialiteSchemaEditor(DatabaseSchemaEditor):
# NOTE: If the field is a geometry field, the table is just recreated, # NOTE: If the field is a geometry field, the table is just recreated,
# the parent's remove_field can't be used cause it will skip the # the parent's remove_field can't be used cause it will skip the
# recreation if the field does not have a database type. Geometry fields # recreation if the field does not have a database type. Geometry
# do not have a db type cause they are added and removed via stored # fields do not have a db type cause they are added and removed via
# procedures. # stored procedures.
if isinstance(field, GeometryField): if isinstance(field, GeometryField):
self._remake_table(model, delete_field=field) self._remake_table(model, delete_field=field)
else: else:

View file

@ -6,7 +6,8 @@ backends.
class SpatialOperator: class SpatialOperator:
""" """
Class encapsulating the behavior specific to a GIS operation (used by lookups). Class encapsulating the behavior specific to a GIS operation (used by
lookups).
""" """
sql_template = None sql_template = None

View file

@ -81,8 +81,8 @@ class BaseSpatialField(Field):
def __init__(self, verbose_name=None, srid=4326, spatial_index=True, **kwargs): def __init__(self, verbose_name=None, srid=4326, spatial_index=True, **kwargs):
""" """
The initialization function for base spatial fields. Takes the following The initialization function for base spatial fields. Takes the
as keyword arguments: following as keyword arguments:
srid: srid:
The spatial reference system identifier, an OGC standard. The spatial reference system identifier, an OGC standard.
@ -195,7 +195,8 @@ class BaseSpatialField(Field):
if isinstance(obj, GEOSGeometry): if isinstance(obj, GEOSGeometry):
pass pass
else: else:
# Check if input is a candidate for conversion to raster or geometry. # Check if input is a candidate for conversion to raster or
# geometry.
is_candidate = isinstance(obj, (bytes, str)) or hasattr( is_candidate = isinstance(obj, (bytes, str)) or hasattr(
obj, "__geo_interface__" obj, "__geo_interface__"
) )
@ -395,7 +396,8 @@ class RasterField(BaseSpatialField):
geography = False geography = False
def _check_connection(self, connection): def _check_connection(self, connection):
# Make sure raster fields are used only on backends with raster support. # Make sure raster fields are used only on backends with raster
# support.
if ( if (
not connection.features.gis_enabled not connection.features.gis_enabled
or not connection.features.supports_raster or not connection.features.supports_raster

View file

@ -121,8 +121,8 @@ class GeomOutputGeoFunc(GeoFunc):
class SQLiteDecimalToFloatMixin: class SQLiteDecimalToFloatMixin:
""" """
By default, Decimal values are converted to str by the SQLite backend, which By default, Decimal values are converted to str by the SQLite backend,
is not acceptable by the GIS functions expecting numeric values. which is not acceptable by the GIS functions expecting numeric values.
""" """
def as_sqlite(self, compiler, connection, **extra_context): def as_sqlite(self, compiler, connection, **extra_context):
@ -483,7 +483,8 @@ class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc):
if self.source_is_geography(): if self.source_is_geography():
clone.source_expressions.append(Value(self.spheroid)) clone.source_expressions.append(Value(self.spheroid))
elif self.geo_field.geodetic(connection): elif self.geo_field.geodetic(connection):
# Geometry fields with geodetic (lon/lat) coordinates need length_spheroid # Geometry fields with geodetic (lon/lat) coordinates need
# length_spheroid
function = connection.ops.spatial_function_name("LengthSpheroid") function = connection.ops.spatial_function_name("LengthSpheroid")
clone.source_expressions.append(Value(self.geo_field.spheroid(connection))) clone.source_expressions.append(Value(self.geo_field.spheroid(connection)))
else: else:

View file

@ -70,9 +70,9 @@ class GISLookup(Lookup):
return placeholder % rhs, rhs_params return placeholder % rhs, rhs_params
def get_rhs_op(self, connection, rhs): def get_rhs_op(self, connection, rhs):
# Unlike BuiltinLookup, the GIS get_rhs_op() implementation should return # Unlike BuiltinLookup, the GIS get_rhs_op() implementation should
# an object (SpatialOperator) with an as_sql() method to allow for more # return an object (SpatialOperator) with an as_sql() method to allow
# complex computations (where the lhs part can be mixed in). # for more complex computations (where the lhs part can be mixed in).
return connection.ops.gis_operators[self.lookup_name] return connection.ops.gis_operators[self.lookup_name]
def as_sql(self, compiler, connection): def as_sql(self, compiler, connection):
@ -98,8 +98,8 @@ class GISLookup(Lookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class OverlapsLeftLookup(GISLookup): class OverlapsLeftLookup(GISLookup):
""" """
The overlaps_left operator returns true if A's bounding box overlaps or is to the The overlaps_left operator returns true if A's bounding box overlaps or is
left of B's bounding box. to the left of B's bounding box.
""" """
lookup_name = "overlaps_left" lookup_name = "overlaps_left"
@ -108,8 +108,8 @@ class OverlapsLeftLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class OverlapsRightLookup(GISLookup): class OverlapsRightLookup(GISLookup):
""" """
The 'overlaps_right' operator returns true if A's bounding box overlaps or is to the The 'overlaps_right' operator returns true if A's bounding box overlaps or
right of B's bounding box. is to the right of B's bounding box.
""" """
lookup_name = "overlaps_right" lookup_name = "overlaps_right"
@ -118,8 +118,8 @@ class OverlapsRightLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class OverlapsBelowLookup(GISLookup): class OverlapsBelowLookup(GISLookup):
""" """
The 'overlaps_below' operator returns true if A's bounding box overlaps or is below The 'overlaps_below' operator returns true if A's bounding box overlaps or
B's bounding box. is below B's bounding box.
""" """
lookup_name = "overlaps_below" lookup_name = "overlaps_below"
@ -128,8 +128,8 @@ class OverlapsBelowLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class OverlapsAboveLookup(GISLookup): class OverlapsAboveLookup(GISLookup):
""" """
The 'overlaps_above' operator returns true if A's bounding box overlaps or is above The 'overlaps_above' operator returns true if A's bounding box overlaps or
B's bounding box. is above B's bounding box.
""" """
lookup_name = "overlaps_above" lookup_name = "overlaps_above"
@ -138,8 +138,8 @@ class OverlapsAboveLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class LeftLookup(GISLookup): class LeftLookup(GISLookup):
""" """
The 'left' operator returns true if A's bounding box is strictly to the left The 'left' operator returns true if A's bounding box is strictly to the
of B's bounding box. left of B's bounding box.
""" """
lookup_name = "left" lookup_name = "left"
@ -148,8 +148,8 @@ class LeftLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class RightLookup(GISLookup): class RightLookup(GISLookup):
""" """
The 'right' operator returns true if A's bounding box is strictly to the right The 'right' operator returns true if A's bounding box is strictly to the
of B's bounding box. right of B's bounding box.
""" """
lookup_name = "right" lookup_name = "right"
@ -158,8 +158,8 @@ class RightLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class StrictlyBelowLookup(GISLookup): class StrictlyBelowLookup(GISLookup):
""" """
The 'strictly_below' operator returns true if A's bounding box is strictly below B's The 'strictly_below' operator returns true if A's bounding box is strictly
bounding box. below B's bounding box.
""" """
lookup_name = "strictly_below" lookup_name = "strictly_below"
@ -168,8 +168,8 @@ class StrictlyBelowLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class StrictlyAboveLookup(GISLookup): class StrictlyAboveLookup(GISLookup):
""" """
The 'strictly_above' operator returns true if A's bounding box is strictly above B's The 'strictly_above' operator returns true if A's bounding box is strictly
bounding box. above B's bounding box.
""" """
lookup_name = "strictly_above" lookup_name = "strictly_above"
@ -192,8 +192,8 @@ BaseSpatialField.register_lookup(SameAsLookup, "exact")
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class BBContainsLookup(GISLookup): class BBContainsLookup(GISLookup):
""" """
The 'bbcontains' operator returns true if A's bounding box completely contains The 'bbcontains' operator returns true if A's bounding box completely
by B's bounding box. contains by B's bounding box.
""" """
lookup_name = "bbcontains" lookup_name = "bbcontains"
@ -212,8 +212,8 @@ class BBOverlapsLookup(GISLookup):
@BaseSpatialField.register_lookup @BaseSpatialField.register_lookup
class ContainedLookup(GISLookup): class ContainedLookup(GISLookup):
""" """
The 'contained' operator returns true if A's bounding box is completely contained The 'contained' operator returns true if A's bounding box is completely
by B's bounding box. contained by B's bounding box.
""" """
lookup_name = "contained" lookup_name = "contained"

View file

@ -39,8 +39,8 @@ class Envelope:
def __init__(self, *args): def __init__(self, *args):
""" """
The initialization function may take an OGREnvelope structure, 4-element The initialization function may take an OGREnvelope structure,
tuple or list, or 4 individual arguments. 4-element tuple or list, or 4 individual arguments.
""" """
if len(args) == 1: if len(args) == 1:

View file

@ -30,7 +30,8 @@ Example:
>>> print(mpnt.proj) >>> print(mpnt.proj)
+proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs
>>> print(mpnt) >>> print(mpnt)
MULTIPOINT (-89.99993037860248 29.99979788655764,-89.99993037860248 29.99979788655764) MULTIPOINT (-89.99993037860248 29.99979788655764,-89.99993037860248
29.99979788655764)
The OGRGeomType class is to make it easy to specify an OGR geometry type: The OGRGeomType class is to make it easy to specify an OGR geometry type:
>>> from django.contrib.gis.gdal import OGRGeomType >>> from django.contrib.gis.gdal import OGRGeomType
@ -248,7 +249,10 @@ class OGRGeometry(GDALBase):
@property @property
def area(self): def area(self):
"Return the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise." """
Return the area for a LinearRing, Polygon, or MultiPolygon; 0
otherwise.
"""
return capi.get_area(self.ptr) return capi.get_area(self.ptr)
@property @property
@ -411,7 +415,8 @@ class OGRGeometry(GDALBase):
else: else:
byteorder = 0 # wkbXDR byteorder = 0 # wkbXDR
sz = self.wkb_size sz = self.wkb_size
# Creating the unsigned character buffer, and passing it in by reference. # Creating the unsigned character buffer, and passing it in by
# reference.
buf = (c_ubyte * sz)() buf = (c_ubyte * sz)()
# For backward compatibility, export old-style 99-402 extended # For backward compatibility, export old-style 99-402 extended
# dimension types when geometry does not have an M dimension. # dimension types when geometry does not have an M dimension.
@ -483,8 +488,8 @@ class OGRGeometry(GDALBase):
# #### Topology Methods #### # #### Topology Methods ####
def _topology(self, func, other): def _topology(self, func, other):
"""A generalized function for topology operations, takes a GDAL function and """A generalized function for topology operations, takes a GDAL
the other geometry to perform the operation on.""" function and the other geometry to perform the operation on."""
if not isinstance(other, OGRGeometry): if not isinstance(other, OGRGeometry):
raise TypeError( raise TypeError(
"Must use another OGRGeometry object for topology operations!" "Must use another OGRGeometry object for topology operations!"

View file

@ -71,8 +71,8 @@ class GDALBand(GDALRasterBase):
If approximate=True, the statistics may be computed based on overviews If approximate=True, the statistics may be computed based on overviews
or a subset of image tiles. or a subset of image tiles.
If refresh=True, the statistics will be computed from the data directly, If refresh=True, the statistics will be computed from the data
and the cache will be updated where applicable. directly, and the cache will be updated where applicable.
For empty bands (where all pixel values are nodata), all statistics For empty bands (where all pixel values are nodata), all statistics
values are returned as None. values are returned as None.

View file

@ -204,7 +204,8 @@ class GDALRaster(GDALRasterBase):
if "skew" in ds_input: if "skew" in ds_input:
self.skew.x, self.skew.y = ds_input["skew"] self.skew.x, self.skew.y = ds_input["skew"]
elif isinstance(ds_input, c_void_p): elif isinstance(ds_input, c_void_p):
# Instantiate the object using an existing pointer to a gdal raster. # Instantiate the object using an existing pointer to a gdal
# raster.
self._ptr = ds_input self._ptr = ds_input
else: else:
raise GDALException( raise GDALException(
@ -410,11 +411,12 @@ class GDALRaster(GDALRasterBase):
name of the source raster will be used and appended with name of the source raster will be used and appended with
_copy. + source_driver_name. _copy. + source_driver_name.
In addition, the resampling algorithm can be specified with the "resampling" In addition, the resampling algorithm can be specified with the
input parameter. The default is NearestNeighbor. For a list of all options "resampling" input parameter. The default is NearestNeighbor. For a
consult the GDAL_RESAMPLE_ALGORITHMS constant. list of all options consult the GDAL_RESAMPLE_ALGORITHMS constant.
""" """
# Get the parameters defining the geotransform, srid, and size of the raster # Get the parameters defining the geotransform, srid, and size of the
# raster
ds_input.setdefault("width", self.width) ds_input.setdefault("width", self.width)
ds_input.setdefault("height", self.height) ds_input.setdefault("height", self.height)
ds_input.setdefault("srid", self.srs.srid) ds_input.setdefault("srid", self.srs.srid)

View file

@ -44,9 +44,9 @@ class AxisOrder(IntEnum):
class SpatialReference(GDALBase): class SpatialReference(GDALBase):
""" """
A wrapper for the OGRSpatialReference object. According to the GDAL web site, A wrapper for the OGRSpatialReference object. According to the GDAL web
the SpatialReference object "provide[s] services to represent coordinate site, the SpatialReference object "provide[s] services to represent
systems (projections and datums) and to transform between them." coordinate systems (projections and datums) and to transform between them."
""" """
destructor = capi.release_srs destructor = capi.release_srs
@ -150,8 +150,8 @@ class SpatialReference(GDALBase):
# #### SpatialReference Methods #### # #### SpatialReference Methods ####
def attr_value(self, target, index=0): def attr_value(self, target, index=0):
""" """
The attribute value for the given target node (e.g. 'PROJCS'). The index The attribute value for the given target node (e.g. 'PROJCS'). The
keyword specifies an index of the child node to return. index keyword specifies an index of the child node to return.
""" """
if not isinstance(target, str) or not isinstance(index, int): if not isinstance(target, str) or not isinstance(index, int):
raise TypeError raise TypeError
@ -288,7 +288,9 @@ class SpatialReference(GDALBase):
@property @property
def local(self): def local(self):
"Return True if this SpatialReference is local (root node is LOCAL_CS)." """
Return True if this SpatialReference is local (root node is LOCAL_CS).
"""
return bool(capi.islocal(self.ptr)) return bool(capi.islocal(self.ptr))
@property @property

View file

@ -27,8 +27,8 @@ class GeometryCollection(GEOSGeometry):
else: else:
init_geoms = args init_geoms = args
# Ensuring that only the permitted geometries are allowed in this collection # Ensuring that only the permitted geometries are allowed in this
# this is moved to list mixin super class # collection this is moved to list mixin super class
self._check_allowed(init_geoms) self._check_allowed(init_geoms)
# Creating the geometry pointer array. # Creating the geometry pointer array.
@ -61,14 +61,19 @@ class GeometryCollection(GEOSGeometry):
return capi.get_geomn(self.ptr, index) return capi.get_geomn(self.ptr, index)
def _get_single_external(self, index): def _get_single_external(self, index):
"Return the Geometry from this Collection at the given index (0-based)." """
Return the Geometry from this Collection at the given index (0-based).
"""
# Checking the index and returning the corresponding GEOS geometry. # Checking the index and returning the corresponding GEOS geometry.
return GEOSGeometry( return GEOSGeometry(
capi.geom_clone(self._get_single_internal(index)), srid=self.srid capi.geom_clone(self._get_single_internal(index)), srid=self.srid
) )
def _set_list(self, length, items): def _set_list(self, length, items):
"Create a new collection, and destroy the contents of the previous pointer." """
Create a new collection, and destroy the contents of the previous
pointer.
"""
prev_ptr = self.ptr prev_ptr = self.ptr
srid = self.srid srid = self.srid
self.ptr = self._create_collection(length, items) self.ptr = self._create_collection(length, items)

View file

@ -180,7 +180,8 @@ class GEOSCoordSeq(GEOSBase):
@property @property
def kml(self): def kml(self):
"Return the KML representation for the coordinates." "Return the KML representation for the coordinates."
# Getting the substitution string depending on whether the coordinates have # Getting the substitution string depending on whether the coordinates
# have
# a Z dimension. # a Z dimension.
if self.hasz: if self.hasz:
substr = "%s,%s,%s " substr = "%s,%s,%s "

View file

@ -76,9 +76,10 @@ class GEOSGeometryBase(GEOSBase):
def __deepcopy__(self, memodict): def __deepcopy__(self, memodict):
""" """
The `deepcopy` routine is used by the `Node` class of django.utils.tree; The `deepcopy` routine is used by the `Node` class of
thus, the protocol routine needs to be implemented to return correct django.utils.tree; thus, the protocol routine needs to be implemented
copies (clones) of these GEOS objects, which use C pointers. to return correct copies (clones) of these GEOS objects, which use C
pointers.
""" """
return self.clone() return self.clone()
@ -343,7 +344,8 @@ class GEOSGeometryBase(GEOSBase):
def overlaps(self, other): def overlaps(self, other):
""" """
Return true if the DE-9IM intersection matrix for the two Geometries Return true if the DE-9IM intersection matrix for the two Geometries
is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves). is T*T***T** (for two points or two surfaces) 1*T***T** (for two
curves).
""" """
return capi.geos_overlaps(self.ptr, other.ptr) return capi.geos_overlaps(self.ptr, other.ptr)
@ -542,9 +544,9 @@ class GEOSGeometryBase(GEOSBase):
""" """
Return a geometry that represents all points whose distance from this Return a geometry that represents all points whose distance from this
Geometry is less than or equal to distance. Calculations are in the Geometry is less than or equal to distance. Calculations are in the
Spatial Reference System of this Geometry. The optional third parameter sets Spatial Reference System of this Geometry. The optional third parameter
the number of segment used to approximate a quarter circle (defaults to 8). sets the number of segment used to approximate a quarter circle
(Text from PostGIS documentation at ch. 6.1.3) (defaults to 8). (Text from PostGIS documentation at ch. 6.1.3)
""" """
return self._topology(capi.geos_buffer(self.ptr, width, quadsegs)) return self._topology(capi.geos_buffer(self.ptr, width, quadsegs))
@ -567,9 +569,9 @@ class GEOSGeometryBase(GEOSBase):
@property @property
def centroid(self): def centroid(self):
""" """
The centroid is equal to the centroid of the set of component Geometries The centroid is equal to the centroid of the set of component
of highest dimension (since the lower-dimension geometries contribute zero Geometries of highest dimension (since the lower-dimension geometries
"weight" to the centroid). contribute zero "weight" to the centroid).
""" """
return self._topology(capi.geos_centroid(self.ptr)) return self._topology(capi.geos_centroid(self.ptr))
@ -594,7 +596,10 @@ class GEOSGeometryBase(GEOSBase):
return self._topology(capi.geos_envelope(self.ptr)) return self._topology(capi.geos_envelope(self.ptr))
def intersection(self, other): def intersection(self, other):
"Return a Geometry representing the points shared by this Geometry and other." """
Return a Geometry representing the points shared by this Geometry and
other.
"""
return self._topology(capi.geos_intersection(self.ptr, other.ptr)) return self._topology(capi.geos_intersection(self.ptr, other.ptr))
@property @property
@ -603,7 +608,9 @@ class GEOSGeometryBase(GEOSBase):
return self._topology(capi.geos_pointonsurface(self.ptr)) return self._topology(capi.geos_pointonsurface(self.ptr))
def relate(self, other): def relate(self, other):
"Return the DE-9IM intersection matrix for this Geometry and the other." """
Return the DE-9IM intersection matrix for this Geometry and the other.
"""
return capi.geos_relate(self.ptr, other.ptr).decode() return capi.geos_relate(self.ptr, other.ptr).decode()
def simplify(self, tolerance=0.0, preserve_topology=False): def simplify(self, tolerance=0.0, preserve_topology=False):
@ -636,7 +643,10 @@ class GEOSGeometryBase(GEOSBase):
return self._topology(capi.geos_unary_union(self.ptr)) return self._topology(capi.geos_unary_union(self.ptr))
def union(self, other): def union(self, other):
"Return a Geometry representing all the points in this Geometry and other." """
Return a Geometry representing all the points in this Geometry and
other.
"""
return self._topology(capi.geos_union(self.ptr, other.ptr)) return self._topology(capi.geos_union(self.ptr, other.ptr))
# #### Other Routines #### # #### Other Routines ####

View file

@ -57,7 +57,8 @@ def load_geos():
) )
# Getting the GEOS C library. The C interface (CDLL) is used for # Getting the GEOS C library. The C interface (CDLL) is used for
# both *NIX and Windows. # both *NIX and Windows.
# See the GEOS C API source code for more details on the library function calls: # See the GEOS C API source code for more details on the library function
# calls:
# https://libgeos.org/doxygen/geos__c_8h_source.html # https://libgeos.org/doxygen/geos__c_8h_source.html
_lgeos = CDLL(lib_path) _lgeos = CDLL(lib_path)
# Here we set up the prototypes for the initGEOS_r and finishGEOS_r # Here we set up the prototypes for the initGEOS_r and finishGEOS_r

View file

@ -26,7 +26,8 @@ class Point(GEOSGeometry):
# Here a tuple or list was passed in under the `x` parameter. # Here a tuple or list was passed in under the `x` parameter.
coords = x coords = x
elif isinstance(x, (float, int)) and isinstance(y, (float, int)): elif isinstance(x, (float, int)) and isinstance(y, (float, int)):
# Here X, Y, and (optionally) Z were passed in individually, as parameters. # Here X, Y, and (optionally) Z were passed in individually, as
# parameters.
if isinstance(z, (float, int)): if isinstance(z, (float, int)):
coords = [x, y, z] coords = [x, y, z]
else: else:

View file

@ -69,8 +69,8 @@ class Polygon(GEOSGeometry):
# ### These routines are needed for list-like operation w/ListMixin ### # ### These routines are needed for list-like operation w/ListMixin ###
def _create_polygon(self, length, items): def _create_polygon(self, length, items):
# Instantiate LinearRing objects if necessary, but don't clone them yet # Instantiate LinearRing objects if necessary, but don't clone them yet
# _construct_ring will throw a TypeError if a parameter isn't a valid ring # _construct_ring will throw a TypeError if a parameter isn't a valid
# If we cloned the pointers here, we wouldn't be able to clean up # ring If we cloned the pointers here, we wouldn't be able to clean up
# in case of error. # in case of error.
if not length: if not length:
return capi.create_empty_polygon() return capi.create_empty_polygon()

View file

@ -19,7 +19,9 @@ def last_arg_byref(args):
def check_dbl(result, func, cargs): def check_dbl(result, func, cargs):
"Check the status code and returns the double value passed in by reference." """
Check the status code and returns the double value passed in by reference.
"""
# Checking the status code # Checking the status code
if result != 1: if result != 1:
return None return None

View file

@ -1,8 +1,8 @@
# Copyright (c) 2007, Robert Coup <robert.coup@onetrackmind.co.nz> # Copyright (c) 2007, Robert Coup <robert.coup@onetrackmind.co.nz>
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without modification, # Redistribution and use in source and binary forms, with or without
# are permitted provided that the following conditions are met: # modification, are permitted provided that the following conditions are met:
# #
# 1. Redistributions of source code must retain the above copyright notice, # 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer. # this list of conditions and the following disclaimer.
@ -11,20 +11,21 @@
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # documentation and/or other materials provided with the distribution.
# #
# 3. Neither the name of Distance nor the names of its contributors may be used # 3. Neither the name of Distance nor the names of its contributors may be
# to endorse or promote products derived from this software without # used to endorse or promote products derived from this software without
# specific prior written permission. # specific prior written permission.
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# #
""" """
Distance and Area objects to allow for sensible and convenient calculation Distance and Area objects to allow for sensible and convenient calculation

View file

@ -107,10 +107,10 @@ class LayerMapping:
using=None, using=None,
): ):
""" """
A LayerMapping object is initialized using the given Model (not an instance), A LayerMapping object is initialized using the given Model (not an
a DataSource (or string path to an OGR-supported data file), and a mapping instance), a DataSource (or string path to an OGR-supported data file),
dictionary. See the module level docstring for more details and keyword and a mapping dictionary. See the module level docstring for more
argument usage. details and keyword argument usage.
""" """
# Getting the DataSource and the associated Layer. # Getting the DataSource and the associated Layer.
if isinstance(data, (str, Path)): if isinstance(data, (str, Path)):
@ -227,7 +227,8 @@ class LayerMapping:
'Given mapping field "%s" not in given Model fields.' % field_name 'Given mapping field "%s" not in given Model fields.' % field_name
) )
# Getting the string name for the Django field class (e.g., 'PointField'). # Getting the string name for the Django field class (e.g.,
# 'PointField').
fld_name = model_field.__class__.__name__ fld_name = model_field.__class__.__name__
if isinstance(model_field, GeometryField): if isinstance(model_field, GeometryField):
@ -262,9 +263,9 @@ class LayerMapping:
% (fld_name, "(dim=3)" if coord_dim == 3 else "", ltype) % (fld_name, "(dim=3)" if coord_dim == 3 else "", ltype)
) )
# Setting the `geom_field` attribute w/the name of the model field # Setting the `geom_field` attribute w/the name of the model
# that is a Geometry. Also setting the coordinate dimension # field that is a Geometry. Also setting the coordinate
# attribute. # dimension attribute.
self.geom_field = field_name self.geom_field = field_name
self.coord_dim = coord_dim self.coord_dim = coord_dim
fields_val = model_field fields_val = model_field
@ -424,7 +425,8 @@ class LayerMapping:
digits = dtup[1] digits = dtup[1]
d_idx = dtup[2] # index where the decimal is d_idx = dtup[2] # index where the decimal is
# Maximum amount of precision, or digits to the left of the decimal. # Maximum amount of precision, or digits to the left of the
# decimal.
max_prec = model_field.max_digits - model_field.decimal_places max_prec = model_field.max_digits - model_field.decimal_places
# Getting the digits to the left of the decimal place for the # Getting the digits to the left of the decimal place for the
@ -446,7 +448,8 @@ class LayerMapping:
elif isinstance(ogr_field, (OFTReal, OFTString)) and isinstance( elif isinstance(ogr_field, (OFTReal, OFTString)) and isinstance(
model_field, models.IntegerField model_field, models.IntegerField
): ):
# Attempt to convert any OFTReal and OFTString value to an OFTInteger. # Attempt to convert any OFTReal and OFTString value to an
# OFTInteger.
try: try:
val = int(ogr_field.value) val = int(ogr_field.value)
except ValueError: except ValueError:
@ -533,7 +536,10 @@ class LayerMapping:
) from exc ) from exc
def geometry_field(self): def geometry_field(self):
"Return the GeometryField instance associated with the geographic column." """
Return the GeometryField instance associated with the geographic
column.
"""
# Use `get_field()` on the model's options so that we # Use `get_field()` on the model's options so that we
# get the correct field instance if there's model inheritance. # get the correct field instance if there's model inheritance.
opts = self.model._meta opts = self.model._meta
@ -542,7 +548,8 @@ class LayerMapping:
def make_multi(self, geom_type, model_field): def make_multi(self, geom_type, model_field):
""" """
Given the OGRGeomType for a geometry and its associated GeometryField, Given the OGRGeomType for a geometry and its associated GeometryField,
determine whether the geometry should be turned into a GeometryCollection. determine whether the geometry should be turned into a
GeometryCollection.
""" """
return ( return (
geom_type.num in self.MULTI_TYPES geom_type.num in self.MULTI_TYPES
@ -583,12 +590,13 @@ class LayerMapping:
When this keyword is set, status information will be printed giving When this keyword is set, status information will be printed giving
the number of features processed and successfully saved. By default, the number of features processed and successfully saved. By default,
progress information will pe printed every 1000 features processed, progress information will pe printed every 1000 features processed,
however, this default may be overridden by setting this keyword with an however, this default may be overridden by setting this keyword with
integer for the desired interval. an integer for the desired interval.
stream: stream:
Status information will be written to this file handle. Defaults to Status information will be written to this file handle. Defaults to
using `sys.stdout`, but any object with a `write` method is supported. using `sys.stdout`, but any object with a `write` method is
supported.
silent: silent:
By default, non-fatal error notifications are printed to stdout, but By default, non-fatal error notifications are printed to stdout, but
@ -631,8 +639,8 @@ class LayerMapping:
# Constructing the model using the keyword args # Constructing the model using the keyword args
is_update = False is_update = False
if self.unique: if self.unique:
# If we want unique models on a particular field, handle the # If we want unique models on a particular field,
# geometry appropriately. # handle the geometry appropriately.
try: try:
# Getting the keyword arguments and retrieving # Getting the keyword arguments and retrieving
# the unique model. # the unique model.
@ -688,8 +696,8 @@ class LayerMapping:
"Processed %d features, saved %d ...\n" % (num_feat, num_saved) "Processed %d features, saved %d ...\n" % (num_feat, num_saved)
) )
# Only used for status output purposes -- incremental saving uses the # Only used for status output purposes -- incremental saving uses
# values returned here. # the values returned here.
return num_saved, num_feat return num_saved, num_feat
if self.transaction_decorator is not None: if self.transaction_decorator is not None:
@ -708,8 +716,8 @@ class LayerMapping:
n_i = len(indices) n_i = len(indices)
for i, end in enumerate(indices): for i, end in enumerate(indices):
# Constructing the slice to use for this step; the last slice is # Constructing the slice to use for this step; the last slice
# special (e.g, [100:] instead of [90:100]). # is special (e.g, [100:] instead of [90:100]).
if i + 1 == n_i: if i + 1 == n_i:
step_slice = slice(beg, None) step_slice = slice(beg, None)
else: else:

View file

@ -141,8 +141,9 @@ def _ogrinspect(
null=False, null=False,
): ):
""" """
Helper routine for `ogrinspect` that generates GeoDjango models corresponding Helper routine for `ogrinspect` that generates GeoDjango models
to the given data source. See the `ogrinspect` docstring for more details. corresponding to the given data source. See the `ogrinspect` docstring for
more details.
""" """
# Getting the DataSource # Getting the DataSource
if isinstance(data_source, str): if isinstance(data_source, str):

View file

@ -39,11 +39,14 @@ def ordinal(value):
templates = ( templates = (
# Translators: Ordinal format when value ends with 0, e.g. 80th. # Translators: Ordinal format when value ends with 0, e.g. 80th.
pgettext("ordinal 0", "{}th"), pgettext("ordinal 0", "{}th"),
# Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. # Translators: Ordinal format when value ends with 1, e.g. 81st,
# except 11.
pgettext("ordinal 1", "{}st"), pgettext("ordinal 1", "{}st"),
# Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. # Translators: Ordinal format when value ends with 2, e.g. 82nd,
# except 12.
pgettext("ordinal 2", "{}nd"), pgettext("ordinal 2", "{}nd"),
# Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. # Translators: Ordinal format when value ends with 3, e.g. 83rd,
# except 13.
pgettext("ordinal 3", "{}rd"), pgettext("ordinal 3", "{}rd"),
# Translators: Ordinal format when value ends with 4, e.g. 84th. # Translators: Ordinal format when value ends with 4, e.g. 84th.
pgettext("ordinal 4", "{}th"), pgettext("ordinal 4", "{}th"),
@ -212,7 +215,8 @@ def naturaltime(value):
class NaturalTimeFormatter: class NaturalTimeFormatter:
time_strings = { time_strings = {
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' # Translators: delta will contain a string like '2 months' or '1 month,
# 2 weeks'
"past-day": gettext_lazy("%(delta)s ago"), "past-day": gettext_lazy("%(delta)s ago"),
# Translators: please keep a non-breaking space (U+00A0) between count # Translators: please keep a non-breaking space (U+00A0) between count
# and time unit. # and time unit.
@ -225,25 +229,27 @@ class NaturalTimeFormatter:
"past-second": ngettext_lazy("a second ago", "%(count)s seconds ago", "count"), "past-second": ngettext_lazy("a second ago", "%(count)s seconds ago", "count"),
"now": gettext_lazy("now"), "now": gettext_lazy("now"),
# fmt: off # fmt: off
# fmt turned off to avoid black splitting the ngettext_lazy calls to multiple # fmt turned off to avoid black splitting the ngettext_lazy calls to
# lines, as this results in gettext missing the 'Translators:' comments. # multiple lines, as this results in gettext missing the 'Translators:'
# comments.
"future-second": ngettext_lazy( "future-second": ngettext_lazy(
# Translators: please keep a non-breaking space (U+00A0) between count # Translators: please keep a non-breaking space (U+00A0) between
# and time unit. # count and time unit.
"a second from now", "%(count)s seconds from now", "count" "a second from now", "%(count)s seconds from now", "count"
), ),
"future-minute": ngettext_lazy( "future-minute": ngettext_lazy(
# Translators: please keep a non-breaking space (U+00A0) between count # Translators: please keep a non-breaking space (U+00A0) between
# and time unit. # count and time unit.
"a minute from now", "%(count)s minutes from now", "count", "a minute from now", "%(count)s minutes from now", "count",
), ),
"future-hour": ngettext_lazy( "future-hour": ngettext_lazy(
# Translators: please keep a non-breaking space (U+00A0) between count # Translators: please keep a non-breaking space (U+00A0) between
# and time unit. # count and time unit.
"an hour from now", "%(count)s hours from now", "count", "an hour from now", "%(count)s hours from now", "count",
), ),
# fmt: on # fmt: on
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' # Translators: delta will contain a string like '2 months' or '1 month,
# 2 weeks'
"future-day": gettext_lazy("%(delta)s from now"), "future-day": gettext_lazy("%(delta)s from now"),
} }
past_substrings = { past_substrings = {

View file

@ -58,12 +58,12 @@ else:
oids, array_oids = get_hstore_oids(connection.alias) oids, array_oids = get_hstore_oids(connection.alias)
# Don't register handlers when hstore is not available on the database. # Don't register handlers when hstore is not available on the database.
# #
# If someone tries to create an hstore field it will error there. This is # If someone tries to create an hstore field it will error there. This
# necessary as someone may be using PSQL without extensions installed but # is necessary as someone may be using PSQL without extensions
# be using other features of contrib.postgres. # installed but be using other features of contrib.postgres.
# #
# This is also needed in order to create the connection in order to install # This is also needed in order to create the connection in order to
# the hstore extension. # install the hstore extension.
if oids: if oids:
register_hstore( register_hstore(
connection.connection, globally=True, oid=oids, array_oid=array_oids connection.connection, globally=True, oid=oids, array_oid=array_oids
@ -72,7 +72,8 @@ else:
oids, citext_oids = get_citext_oids(connection.alias) oids, citext_oids = get_citext_oids(connection.alias)
# Don't register handlers when citext is not available on the database. # Don't register handlers when citext is not available on the database.
# #
# The same comments in the above call to register_hstore() also apply here. # The same comments in the above call to register_hstore() also apply
# here.
if oids: if oids:
array_type = psycopg2.extensions.new_array_type( array_type = psycopg2.extensions.new_array_type(
citext_oids, "citext[]", psycopg2.STRING citext_oids, "citext[]", psycopg2.STRING

View file

@ -120,7 +120,9 @@ class SessionBase:
del (await self._aget_session())[self.TEST_COOKIE_NAME] del (await self._aget_session())[self.TEST_COOKIE_NAME]
def encode(self, session_dict): def encode(self, session_dict):
"Return the given session dictionary serialized and encoded as a string." """
Return the given session dictionary serialized and encoded as a string.
"""
return signing.dumps( return signing.dumps(
session_dict, session_dict,
salt=self.key_salt, salt=self.key_salt,

View file

@ -51,7 +51,8 @@ class Sitemap:
def _items(self): def _items(self):
if self.i18n: if self.i18n:
# Create (item, lang_code) tuples for all items and languages. # Create (item, lang_code) tuples for all items and languages.
# This is necessary to paginate with all languages already considered. # This is necessary to paginate with all languages already
# considered.
items = [ items = [
(item, lang_code) (item, lang_code)
for item in self.items() for item in self.items()
@ -63,7 +64,8 @@ class Sitemap:
def _location(self, item, force_lang_code=None): def _location(self, item, force_lang_code=None):
if self.i18n: if self.i18n:
obj, lang_code = item obj, lang_code = item
# Activate language from item-tuple or forced one before calling location. # Activate language from item-tuple or forced one before calling
# location.
with translation.override(force_lang_code or lang_code): with translation.override(force_lang_code or lang_code):
return self._get("location", item) return self._get("location", item)
return self._get("location", item) return self._get("location", item)

View file

@ -239,15 +239,18 @@ class HashedFilesMixin:
return matched return matched
if url_path.startswith("/"): if url_path.startswith("/"):
# Otherwise the condition above would have returned prematurely. # Otherwise the condition above would have returned
# prematurely.
assert url_path.startswith(settings.STATIC_URL) assert url_path.startswith(settings.STATIC_URL)
target_name = url_path.removeprefix(settings.STATIC_URL) target_name = url_path.removeprefix(settings.STATIC_URL)
else: else:
# We're using the posixpath module to mix paths and URLs conveniently. # We're using the posixpath module to mix paths and URLs
# conveniently.
source_name = name if os.sep == "/" else name.replace(os.sep, "/") source_name = name if os.sep == "/" else name.replace(os.sep, "/")
target_name = posixpath.join(posixpath.dirname(source_name), url_path) target_name = posixpath.join(posixpath.dirname(source_name), url_path)
# Determine the hashed name of the target file with the storage backend. # Determine the hashed name of the target file with the storage
# backend.
hashed_url = self._url( hashed_url = self._url(
self._stored_name, self._stored_name,
unquote(target_name), unquote(target_name),
@ -280,8 +283,8 @@ class HashedFilesMixin:
2. adjusting files which contain references to other files so they 2. adjusting files which contain references to other files so they
refer to the cache-busting filenames. refer to the cache-busting filenames.
If either of these are performed on a file, then that file is considered If either of these are performed on a file, then that file is
post-processed. considered post-processed.
""" """
# don't even dare to process the files if we're in dry run mode # don't even dare to process the files if we're in dry run mode
if dry_run: if dry_run:
@ -448,7 +451,8 @@ class HashedFilesMixin:
# Move on to the next intermediate file. # Move on to the next intermediate file.
intermediate_name = cache_name intermediate_name = cache_name
# If the cache name can't be determined after the max number of passes, # If the cache name can't be determined after the max number of passes,
# the intermediate files on disk may be corrupt; avoid an infinite loop. # the intermediate files on disk may be corrupt; avoid an infinite
# loop.
raise ValueError("The name '%s' could not be hashed with %r." % (name, self)) raise ValueError("The name '%s' could not be hashed with %r." % (name, self))

View file

@ -283,8 +283,8 @@ class BaseCache:
def decr(self, key, delta=1, version=None): def decr(self, key, delta=1, version=None):
""" """
Subtract delta from value in the cache. If the key does not exist, raise Subtract delta from value in the cache. If the key does not exist,
a ValueError exception. raise a ValueError exception.
""" """
return self.incr(key, -delta, version=version) return self.incr(key, -delta, version=version)

View file

@ -136,9 +136,9 @@ class DatabaseCache(BaseDatabaseCache):
b64encoded = base64.b64encode(pickled).decode("latin1") b64encoded = base64.b64encode(pickled).decode("latin1")
try: try:
# Note: typecasting for datetimes is needed by some 3rd party # Note: typecasting for datetimes is needed by some 3rd party
# database backends. All core backends work without typecasting, # database backends. All core backends work without
# so be careful about changes here - test suite will NOT pick # typecasting, so be careful about changes here - test suite
# regressions. # will NOT pick regressions.
with transaction.atomic(using=db): with transaction.atomic(using=db):
cursor.execute( cursor.execute(
"SELECT %s, %s FROM %s WHERE %s = %%s" "SELECT %s, %s FROM %s WHERE %s = %%s"
@ -198,7 +198,8 @@ class DatabaseCache(BaseDatabaseCache):
else: else:
return False # touch failed. return False # touch failed.
except DatabaseError: except DatabaseError:
# To be threadsafe, updates/inserts are allowed to fail silently # To be threadsafe, updates/inserts are allowed to fail
# silently
return False return False
else: else:
return True return True

View file

@ -29,7 +29,8 @@ class CheckMessage:
obj = "?" obj = "?"
elif isinstance(self.obj, models.base.ModelBase): elif isinstance(self.obj, models.base.ModelBase):
# We need to hardcode ModelBase and Field cases because its __str__ # We need to hardcode ModelBase and Field cases because its __str__
# method doesn't return "applabel.modellabel" and cannot be changed. # method doesn't return "applabel.modellabel" and cannot be
# changed.
obj = self.obj._meta.label obj = self.obj._meta.label
else: else:
obj = str(self.obj) obj = str(self.obj)

View file

@ -266,7 +266,8 @@ def check_referrer_policy(app_configs, **kwargs):
if _security_middleware(): if _security_middleware():
if settings.SECURE_REFERRER_POLICY is None: if settings.SECURE_REFERRER_POLICY is None:
return [W022] return [W022]
# Support a comma-separated string or iterable of values to allow fallback. # Support a comma-separated string or iterable of values to allow
# fallback.
if isinstance(settings.SECURE_REFERRER_POLICY, str): if isinstance(settings.SECURE_REFERRER_POLICY, str):
values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(",")} values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(",")}
else: else:

View file

@ -67,8 +67,8 @@ class File(FileProxyMixin):
Return ``True`` if you can expect multiple chunks. Return ``True`` if you can expect multiple chunks.
NB: If a particular file representation is in memory, subclasses should NB: If a particular file representation is in memory, subclasses should
always return ``False`` -- there's no good reason to read from memory in always return ``False`` -- there's no good reason to read from memory
chunks. in chunks.
""" """
return self.size > (chunk_size or self.DEFAULT_CHUNK_SIZE) return self.size > (chunk_size or self.DEFAULT_CHUNK_SIZE)

View file

@ -19,8 +19,9 @@ def file_move_safe(
""" """
Move a file from one location to another in the safest way possible. Move a file from one location to another in the safest way possible.
First, try ``os.rename``, which is simple but will break across filesystems. First, try ``os.rename``, which is simple but will break across
If that fails, stream manually from one file to another in pure Python. filesystems. If that fails, stream manually from one file to another in
pure Python.
If the destination file exists and ``allow_overwrite`` is ``False``, raise If the destination file exists and ``allow_overwrite`` is ``False``, raise
``FileExistsError``. ``FileExistsError``.

View file

@ -149,8 +149,8 @@ class Storage:
def exists(self, name): def exists(self, name):
""" """
Return True if a file referenced by the given name already exists in the Return True if a file referenced by the given name already exists in
storage system, or False if the name is available for a new file. the storage system, or False if the name is available for a new file.
""" """
raise NotImplementedError( raise NotImplementedError(
"subclasses of Storage must provide an exists() method" "subclasses of Storage must provide an exists() method"

View file

@ -104,8 +104,9 @@ class FileSystemStorage(Storage, StorageSettingsMixin):
# This is a normal uploadedfile that we can stream. # This is a normal uploadedfile that we can stream.
else: else:
# The combination of O_CREAT and O_EXCL makes os.open() raises an # The combination of O_CREAT and O_EXCL makes os.open()
# OSError if the file already exists before it's opened. # raises an OSError if the file already exists before it's
# opened.
open_flags = ( open_flags = (
os.O_WRONLY os.O_WRONLY
| os.O_CREAT | os.O_CREAT

View file

@ -54,7 +54,8 @@ class UploadedFile(File):
# Just use the basename of the file -- anything else is dangerous. # Just use the basename of the file -- anything else is dangerous.
name = os.path.basename(name) name = os.path.basename(name)
# File names longer than 255 characters can cause problems on older OSes. # File names longer than 255 characters can cause problems on older
# OSes.
if len(name) > 255: if len(name) > 255:
name, ext = os.path.splitext(name) name, ext = os.path.splitext(name)
ext = ext[:255] ext = ext[:255]
@ -126,7 +127,8 @@ class InMemoryUploadedFile(UploadedFile):
class SimpleUploadedFile(InMemoryUploadedFile): class SimpleUploadedFile(InMemoryUploadedFile):
""" """
A simple representation of a file, which just has content, size, and a name. A simple representation of a file, which just has content, size, and a
name.
""" """
def __init__(self, name, content, content_type="text/plain"): def __init__(self, name, content, content_type="text/plain"):

View file

@ -37,8 +37,8 @@ class StopUpload(UploadFileException):
def __init__(self, connection_reset=False): def __init__(self, connection_reset=False):
""" """
If ``connection_reset`` is ``True``, Django knows will halt the upload If ``connection_reset`` is ``True``, Django knows will halt the upload
without consuming the rest of the upload. This will cause the browser to without consuming the rest of the upload. This will cause the browser
show a "connection reset" error. to show a "connection reset" error.
""" """
self.connection_reset = connection_reset self.connection_reset = connection_reset
@ -51,7 +51,8 @@ class StopUpload(UploadFileException):
class SkipFile(UploadFileException): class SkipFile(UploadFileException):
""" """
This exception is raised by an upload handler that wants to skip a given file. This exception is raised by an upload handler that wants to skip a given
file.
""" """
pass pass

View file

@ -331,8 +331,8 @@ class ASGIHandler(base.BaseHandler):
) )
# Streaming responses need to be pinned to their iterator. # Streaming responses need to be pinned to their iterator.
if response.streaming: if response.streaming:
# - Consume via `__aiter__` and not `streaming_content` directly, to # - Consume via `__aiter__` and not `streaming_content` directly,
# allow mapping of a sync iterator. # to allow mapping of a sync iterator.
# - Use aclosing() when consuming aiter. See # - Use aclosing() when consuming aiter. See
# https://github.com/python/cpython/commit/6e8dcdaaa49d4313bf9fab9f9923ca5828fbb10e # https://github.com/python/cpython/commit/6e8dcdaaa49d4313bf9fab9f9923ca5828fbb10e
async with aclosing(aiter(response)) as content: async with aclosing(aiter(response)) as content:
@ -342,8 +342,9 @@ class ASGIHandler(base.BaseHandler):
{ {
"type": "http.response.body", "type": "http.response.body",
"body": chunk, "body": chunk,
# Ignore "more" as there may be more parts; instead, # Ignore "more" as there may be more parts;
# use an empty final closing message with False. # instead, use an empty final closing message
# with False.
"more_body": True, "more_body": True,
} }
) )

View file

@ -27,7 +27,8 @@ class BaseHandler:
""" """
Populate middleware lists from settings.MIDDLEWARE. Populate middleware lists from settings.MIDDLEWARE.
Must be called after the environment is fixed (see __call__ in subclasses). Must be called after the environment is fixed (see __call__ in
subclasses).
""" """
self._view_middleware = [] self._view_middleware = []
self._template_response_middleware = [] self._template_response_middleware = []

View file

@ -153,7 +153,8 @@ class MIMEMixin:
class SafeMIMEMessage(MIMEMixin, MIMEMessage): class SafeMIMEMessage(MIMEMixin, MIMEMessage):
def __setitem__(self, name, val): def __setitem__(self, name, val):
# Per RFC 2046 Section 5.2.1, message/rfc822 attachment headers must be ASCII. # Per RFC 2046 Section 5.2.1, message/rfc822 attachment headers must be
# ASCII.
name, val = forbid_multi_line_headers(name, val, "ascii") name, val = forbid_multi_line_headers(name, val, "ascii")
MIMEMessage.__setitem__(self, name, val) MIMEMessage.__setitem__(self, name, val)

View file

@ -117,7 +117,8 @@ def call_command(command_name, *args, **options):
else: else:
command = load_command_class(app_name, command_name) command = load_command_class(app_name, command_name)
# Simulate argument parsing to get the option defaults (see #10080 for details). # Simulate argument parsing to get the option defaults (see #10080 for
# details).
parser = command.create_parser("", command_name) parser = command.create_parser("", command_name)
# Use the `dest` option name from the parser option # Use the `dest` option name from the parser option
opt_mapping = { opt_mapping = {
@ -256,9 +257,9 @@ class ManagementUtility:
except KeyError: except KeyError:
if os.environ.get("DJANGO_SETTINGS_MODULE"): if os.environ.get("DJANGO_SETTINGS_MODULE"):
# If `subcommand` is missing due to misconfigured settings, the # If `subcommand` is missing due to misconfigured settings, the
# following line will retrigger an ImproperlyConfigured exception # following line will retrigger an ImproperlyConfigured
# (get_commands() swallows the original one) so the user is # exception (get_commands() swallows the original one) so the
# informed about it. # user is informed about it.
settings.INSTALLED_APPS settings.INSTALLED_APPS
elif not settings.configured: elif not settings.configured:
sys.stderr.write("No Django settings specified.\n") sys.stderr.write("No Django settings specified.\n")

View file

@ -45,7 +45,8 @@ class Command(BaseCommand):
def handle(self, **options): def handle(self, **options):
from django.conf import Settings, global_settings, settings from django.conf import Settings, global_settings, settings
# Because settings are imported lazily, we need to explicitly load them. # Because settings are imported lazily, we need to explicitly load
# them.
if not settings.configured: if not settings.configured:
settings._setup() settings._setup()

View file

@ -229,7 +229,8 @@ class Command(BaseCommand):
self.stdout.ending = None self.stdout.ending = None
progress_output = None progress_output = None
object_count = 0 object_count = 0
# If dumpdata is outputting to stdout, there is no way to display progress # If dumpdata is outputting to stdout, there is no way to display
# progress
if output and self.stdout.isatty() and options["verbosity"] > 0: if output and self.stdout.isatty() and options["verbosity"] > 0:
progress_output = self.stdout progress_output = self.stdout
object_count = sum(get_objects(count_only=True)) object_count = sum(get_objects(count_only=True))

View file

@ -86,8 +86,9 @@ Are you sure you want to do this?
# Empty sql_list may signify an empty database and post_migrate # Empty sql_list may signify an empty database and post_migrate
# would then crash. # would then crash.
if sql_list and not inhibit_post_migrate: if sql_list and not inhibit_post_migrate:
# Emit the post migrate signal. This allows individual applications to # Emit the post migrate signal. This allows individual
# respond as if the database had been migrated from scratch. # applications to respond as if the database had been migrated
# from scratch.
emit_post_migrate_signal(verbosity, interactive, database) emit_post_migrate_signal(verbosity, interactive, database)
else: else:
self.stdout.write("Flush cancelled.") self.stdout.write("Flush cancelled.")

View file

@ -193,8 +193,8 @@ class Command(BaseCommand):
) )
used_relations.add(rel_to) used_relations.add(rel_to)
else: else:
# Calling `get_field_type` to get the field type string and any # Calling `get_field_type` to get the field type string
# additional parameters and notes. # and any additional parameters and notes.
field_type, field_params, field_notes = self.get_field_type( field_type, field_params, field_notes = self.get_field_type(
connection, table_name, row connection, table_name, row
) )
@ -203,8 +203,8 @@ class Command(BaseCommand):
field_type += "(" field_type += "("
# Don't output 'id = meta.AutoField(primary_key=True)', because # Don't output 'id = meta.AutoField(primary_key=True)',
# that's assumed if it doesn't exist. # because that's assumed if it doesn't exist.
if att_name == "id" and extra_params == {"primary_key": True}: if att_name == "id" and extra_params == {"primary_key": True}:
if field_type == "AutoField(": if field_type == "AutoField(":
continue continue
@ -215,8 +215,8 @@ class Command(BaseCommand):
): ):
comment_notes.append("AutoField?") comment_notes.append("AutoField?")
# Add 'null' and 'blank', if the 'null_ok' flag was present in the # Add 'null' and 'blank', if the 'null_ok' flag was present
# table description. # in the table description.
if row.null_ok: # If it's NULL... if row.null_ok: # If it's NULL...
extra_params["blank"] = True extra_params["blank"] = True
extra_params["null"] = True extra_params["null"] = True
@ -287,7 +287,8 @@ class Command(BaseCommand):
while new_name.find(LOOKUP_SEP) >= 0: while new_name.find(LOOKUP_SEP) >= 0:
new_name = new_name.replace(LOOKUP_SEP, "_") new_name = new_name.replace(LOOKUP_SEP, "_")
if col_name.lower().find(LOOKUP_SEP) >= 0: if col_name.lower().find(LOOKUP_SEP) >= 0:
# Only add the comment if the double underscore was in the original name # Only add the comment if the double underscore was in the
# original name
field_notes.append( field_notes.append(
"Field renamed because it contained more than one '_' in a row." "Field renamed because it contained more than one '_' in a row."
) )

View file

@ -420,9 +420,11 @@ class Command(BaseCommand):
for locale in locales: for locale in locales:
if not is_valid_locale(locale): if not is_valid_locale(locale):
# Try to guess what valid locale it could be # Try to guess what valid locale it could be
# Valid examples are: en_GB, shi_Latn_MA and nl_NL-x-informal # Valid examples are: en_GB, shi_Latn_MA and
# nl_NL-x-informal
# Search for characters followed by a non character (i.e. separator) # Search for characters followed by a non character (i.e.
# separator)
match = re.match( match = re.match(
r"^(?P<language>[a-zA-Z]+)" r"^(?P<language>[a-zA-Z]+)"
r"(?P<separator>[^a-zA-Z])" r"(?P<separator>[^a-zA-Z])"
@ -464,8 +466,9 @@ class Command(BaseCommand):
@cached_property @cached_property
def gettext_version(self): def gettext_version(self):
# Gettext tools will output system-encoded bytestrings instead of UTF-8, # Gettext tools will output system-encoded bytestrings instead of
# when looking up the version. It's especially a problem on Windows. # UTF-8, when looking up the version. It's especially a problem on
# Windows.
out, err, status = popen_wrapper( out, err, status = popen_wrapper(
["xgettext", "--version"], ["xgettext", "--version"],
stdout_encoding=DEFAULT_LOCALE_ENCODING, stdout_encoding=DEFAULT_LOCALE_ENCODING,

View file

@ -139,7 +139,8 @@ class Command(BaseCommand):
# the loader doesn't try to resolve replaced migrations from DB. # the loader doesn't try to resolve replaced migrations from DB.
loader = MigrationLoader(None, ignore_no_migrations=True) loader = MigrationLoader(None, ignore_no_migrations=True)
# Raise an error if any migrations are applied before their dependencies. # Raise an error if any migrations are applied before their
# dependencies.
consistency_check_labels = {config.label for config in apps.get_app_configs()} consistency_check_labels = {config.label for config in apps.get_app_configs()}
# Non-default databases are only checked if database routers used. # Non-default databases are only checked if database routers used.
aliases_to_check = ( aliases_to_check = (
@ -186,7 +187,8 @@ class Command(BaseCommand):
"'python manage.py makemigrations --merge'" % name_str "'python manage.py makemigrations --merge'" % name_str
) )
# If they want to merge and there's nothing to merge, then politely exit # If they want to merge and there's nothing to merge, then politely
# exit
if self.merge and not conflicts: if self.merge and not conflicts:
self.log("No conflicts detected to merge.") self.log("No conflicts detected to merge.")
return return
@ -505,9 +507,9 @@ class Command(BaseCommand):
if self.scriptable: if self.scriptable:
self.stdout.write(writer.path) self.stdout.write(writer.path)
elif self.verbosity == 3: elif self.verbosity == 3:
# Alternatively, makemigrations --merge --dry-run --verbosity 3 # Alternatively, makemigrations --merge --dry-run
# will log the merge migrations rather than saving the file # --verbosity 3 will log the merge migrations rather than
# to the disk. # saving the file to the disk.
self.log( self.log(
self.style.MIGRATE_HEADING( self.style.MIGRATE_HEADING(
"Full merge migrations file '%s':" % writer.filename "Full merge migrations file '%s':" % writer.filename

View file

@ -113,7 +113,8 @@ class Command(BaseCommand):
# Work out which apps have migrations and which do not # Work out which apps have migrations and which do not
executor = MigrationExecutor(connection, self.migration_progress_callback) executor = MigrationExecutor(connection, self.migration_progress_callback)
# Raise an error if any migrations are applied before their dependencies. # Raise an error if any migrations are applied before their
# dependencies.
executor.loader.check_consistent_history(connection) executor.loader.check_consistent_history(connection)
# Before anything else, see if there's conflicting apps and drop out # Before anything else, see if there's conflicting apps and drop out
@ -357,8 +358,8 @@ class Command(BaseCommand):
fake=fake, fake=fake,
fake_initial=fake_initial, fake_initial=fake_initial,
) )
# post_migrate signals have access to all models. Ensure that all models # post_migrate signals have access to all models. Ensure that all
# are reloaded in case any are delayed. # models are reloaded in case any are delayed.
post_migrate_state.clear_delayed_apps_cache() post_migrate_state.clear_delayed_apps_cache()
post_migrate_apps = post_migrate_state.apps post_migrate_apps = post_migrate_state.apps
@ -375,8 +376,8 @@ class Command(BaseCommand):
[ModelState.from_model(apps.get_model(*model)) for model in model_keys] [ModelState.from_model(apps.get_model(*model)) for model in model_keys]
) )
# Send the post_migrate signal, so individual apps can do whatever they need # Send the post_migrate signal, so individual apps can do whatever they
# to do at this point. # need to do at this point.
emit_post_migrate_signal( emit_post_migrate_signal(
self.verbosity, self.verbosity,
self.interactive, self.interactive,

View file

@ -70,8 +70,8 @@ class Command(BaseCommand):
# Set up a dictionary to serve as the environment for the shell. # Set up a dictionary to serve as the environment for the shell.
imported_objects = self.get_namespace(**options) imported_objects = self.get_namespace(**options)
# We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow
# conventions and get $PYTHONSTARTUP first then .pythonrc.py. # system conventions and get $PYTHONSTARTUP first then .pythonrc.py.
if not options["no_startup"]: if not options["no_startup"]:
for pythonrc in OrderedSet( for pythonrc in OrderedSet(
[os.environ.get("PYTHONSTARTUP"), os.path.expanduser("~/.pythonrc.py")] [os.environ.get("PYTHONSTARTUP"), os.path.expanduser("~/.pythonrc.py")]
@ -89,9 +89,9 @@ class Command(BaseCommand):
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
# By default, this will set up readline to do tab completion and to read and # By default, this will set up readline to do tab completion and to
# write history to the .python_history file, but this can be overridden by # read and write history to the .python_history file, but this can be
# $PYTHONSTARTUP or ~/.pythonrc.py. # overridden by $PYTHONSTARTUP or ~/.pythonrc.py.
try: try:
hook = sys.__interactivehook__ hook = sys.__interactivehook__
except AttributeError: except AttributeError:

View file

@ -74,8 +74,8 @@ class Command(BaseCommand):
migration.atomic and connection.features.can_rollback_ddl migration.atomic and connection.features.can_rollback_ddl
) )
# Make a plan that represents just the requested migrations and show SQL # Make a plan that represents just the requested migrations and show
# for it # SQL for it
plan = [(loader.graph.nodes[target], options["backwards"])] plan = [(loader.graph.nodes[target], options["backwards"])]
sql_statements = loader.collect_sql(plan) sql_statements = loader.collect_sql(plan)
if not sql_statements and options["verbosity"] >= 1: if not sql_statements and options["verbosity"] >= 1:

View file

@ -56,7 +56,8 @@ class BasePaginator:
else self.default_error_messages | error_messages else self.default_error_messages | error_messages
) )
if self.per_page <= self.orphans: if self.per_page <= self.orphans:
# RemovedInDjango70Warning: When the deprecation ends, replace with: # RemovedInDjango70Warning: When the deprecation ends, replace
# with:
# raise ValueError( # raise ValueError(
# "The orphans argument cannot be larger than or equal to the " # "The orphans argument cannot be larger than or equal to the "
# "per_page argument." # "per_page argument."

View file

@ -225,8 +225,9 @@ def sort_dependencies(app_list, allow_cycles=False):
model, deps = model_dependencies.pop() model, deps = model_dependencies.pop()
# If all of the models in the dependency list are either already # If all of the models in the dependency list are either already
# on the final model list, or not on the original serialization list, # on the final model list, or not on the original serialization
# then we've found another model with all it's dependencies satisfied. # list, then we've found another model with all it's dependencies
# satisfied.
if all(d not in models or d in model_list for d in deps): if all(d not in models or d in model_list for d in deps):
model_list.append(model) model_list.append(model)
changed = True changed = True

View file

@ -108,8 +108,9 @@ class Serializer:
self.first = True self.first = True
for count, obj in enumerate(queryset, start=1): for count, obj in enumerate(queryset, start=1):
self.start_object(obj) self.start_object(obj)
# Use the concrete parent class' _meta instead of the object's _meta # Use the concrete parent class' _meta instead of the object's
# This is to avoid local_fields problems for proxy models. Refs #17717. # _meta This is to avoid local_fields problems for proxy models.
# Refs #17717.
concrete_model = obj._meta.concrete_model concrete_model = obj._meta.concrete_model
# When using natural primary keys, retrieve the pk field of the # When using natural primary keys, retrieve the pk field of the
# parent for multi-table inheritance child models. That field must # parent for multi-table inheritance child models. That field must

View file

@ -1,7 +1,7 @@
""" """
A Python "serializer". Doesn't do much serializing per se -- just converts to A Python "serializer". Doesn't do much serializing per se -- just converts to
and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for and from basic Python data types (lists, dicts, strings, etc.). Useful as a
other serializers. basis for other serializers.
""" """
from django.apps import apps from django.apps import apps

View file

@ -46,11 +46,12 @@ class Serializer(PythonSerializer):
def _value_from_field(self, obj, field): def _value_from_field(self, obj, field):
# A nasty special case: base YAML doesn't support serialization of time # A nasty special case: base YAML doesn't support serialization of time
# types (as opposed to dates or datetimes, which it does support). Since # types (as opposed to dates or datetimes, which it does support).
# we want to use the "safe" serializer for better interoperability, we # Since we want to use the "safe" serializer for better
# need to do something with those pesky times. Converting 'em to strings # interoperability, we need to do something with those pesky times.
# isn't perfect, but it's better than a "!!python/time" type which would # Converting 'em to strings isn't perfect, but it's better than a
# halt deserialization under any other language. # "!!python/time" type which would halt deserialization under any other
# language.
value = super()._value_from_field(obj, field) value = super()._value_from_field(obj, field)
if isinstance(value, datetime.time): if isinstance(value, datetime.time):
value = str(value) value = str(value)

View file

@ -250,7 +250,8 @@ class Deserializer(base.Deserializer):
continue continue
field = Model._meta.get_field(field_name) field = Model._meta.get_field(field_name)
# As is usually the case, relation fields get the special treatment. # As is usually the case, relation fields get the special
# treatment.
if field.remote_field and isinstance( if field.remote_field and isinstance(
field.remote_field, models.ManyToManyRel field.remote_field, models.ManyToManyRel
): ):
@ -303,7 +304,8 @@ class Deserializer(base.Deserializer):
if hasattr(model._default_manager, "get_by_natural_key"): if hasattr(model._default_manager, "get_by_natural_key"):
keys = node.getElementsByTagName("natural") keys = node.getElementsByTagName("natural")
if keys: if keys:
# If there are 'natural' subelements, it must be a natural key # If there are 'natural' subelements, it must be a natural
# key
field_value = [getInnerText(k).strip() for k in keys] field_value = [getInnerText(k).strip() for k in keys]
try: try:
obj = model._default_manager.db_manager( obj = model._default_manager.db_manager(
@ -343,7 +345,8 @@ class Deserializer(base.Deserializer):
def m2m_convert(n): def m2m_convert(n):
keys = n.getElementsByTagName("natural") keys = n.getElementsByTagName("natural")
if keys: if keys:
# If there are 'natural' subelements, it must be a natural key # If there are 'natural' subelements, it must be a natural
# key
field_value = [getInnerText(k).strip() for k in keys] field_value = [getInnerText(k).strip() for k in keys]
obj_pk = ( obj_pk = (
default_manager.db_manager(self.db) default_manager.db_manager(self.db)
@ -394,7 +397,8 @@ class Deserializer(base.Deserializer):
def getInnerText(node): def getInnerText(node):
"""Get all the inner text of a DOM node (recursively).""" """Get all the inner text of a DOM node (recursively)."""
# inspired by https://mail.python.org/pipermail/xml-sig/2005-March/011022.html # inspired by
# https://mail.python.org/pipermail/xml-sig/2005-March/011022.html
inner_text = [] inner_text = []
for child in node.childNodes: for child in node.childNodes:
if ( if (

View file

@ -234,7 +234,9 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler):
pass pass
def handle_one_request(self): def handle_one_request(self):
"""Copy of WSGIRequestHandler.handle() but with different ServerHandler""" """
Copy of WSGIRequestHandler.handle() but with different ServerHandler
"""
self.raw_requestline = self.rfile.readline(65537) self.raw_requestline = self.rfile.readline(65537)
if len(self.raw_requestline) > 65536: if len(self.raw_requestline) > 65536:
self.requestline = "" self.requestline = ""

View file

@ -17,7 +17,8 @@ If the signature fails, a BadSignature exception is raised.
'hello' 'hello'
>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified") >>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified")
... ...
BadSignature: Signature "ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified" does not match BadSignature: Signature "ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified" does
not match
You can optionally compress the JSON prior to base64 encoding it to save You can optionally compress the JSON prior to base64 encoding it to save
space, using the compress=True argument. This checks if compression actually space, using the compress=True argument. This checks if compression actually

View file

@ -595,8 +595,8 @@ class BaseDatabaseWrapper:
""" """
if self.connection is not None: if self.connection is not None:
self.health_check_done = False self.health_check_done = False
# If the application didn't restore the original autocommit setting, # If the application didn't restore the original autocommit
# don't take chances, drop the connection. # setting, don't take chances, drop the connection.
if self.get_autocommit() != self.settings_dict["AUTOCOMMIT"]: if self.get_autocommit() != self.settings_dict["AUTOCOMMIT"]:
self.close() self.close()
return return

View file

@ -94,9 +94,10 @@ class BaseDatabaseCreation:
settings.MIGRATION_MODULES = old_migration_modules settings.MIGRATION_MODULES = old_migration_modules
# We then serialize the current state of the database into a string # We then serialize the current state of the database into a string
# and store it on the connection. This slightly horrific process is so people # and store it on the connection. This slightly horrific process is so
# who are testing on databases without transactions or who are using # people who are testing on databases without transactions or who are
# a TransactionTestCase still get a clean database on every test run. # using a TransactionTestCase still get a clean database on every test
# run.
if serialize is not None: if serialize is not None:
warnings.warn( warnings.warn(
"DatabaseCreation.create_test_db(serialize) is deprecated. Call " "DatabaseCreation.create_test_db(serialize) is deprecated. Call "
@ -112,7 +113,8 @@ class BaseDatabaseCreation:
call_command("createcachetable", database=self.connection.alias) call_command("createcachetable", database=self.connection.alias)
# Ensure a connection for the side effect of initializing the test database. # Ensure a connection for the side effect of initializing the test
# database.
self.connection.ensure_connection() self.connection.ensure_connection()
if os.environ.get("RUNNING_DJANGOS_TEST_SUITE") == "true": if os.environ.get("RUNNING_DJANGOS_TEST_SUITE") == "true":
@ -220,8 +222,8 @@ class BaseDatabaseCreation:
try: try:
self._execute_create_test_db(cursor, test_db_params, keepdb) self._execute_create_test_db(cursor, test_db_params, keepdb)
except Exception as e: except Exception as e:
# if we want to keep the db, then no need to do any of the below, # if we want to keep the db, then no need to do any of the
# just return and skip it all. # below, just return and skip it all.
if keepdb: if keepdb:
return test_database_name return test_database_name
@ -365,7 +367,8 @@ class BaseDatabaseCreation:
for test_name in tests: for test_name in tests:
test_case_name, _, test_method_name = test_name.rpartition(".") test_case_name, _, test_method_name = test_name.rpartition(".")
test_app = test_name.split(".")[0] test_app = test_name.split(".")[0]
# Importing a test app that isn't installed raises RuntimeError. # Importing a test app that isn't installed raises
# RuntimeError.
if test_app in settings.INSTALLED_APPS: if test_app in settings.INSTALLED_APPS:
test_case = import_string(test_case_name) test_case = import_string(test_case_name)
test_method = getattr(test_case, test_method_name) test_method = getattr(test_case, test_method_name)

View file

@ -201,7 +201,8 @@ class BaseDatabaseFeatures:
# supported by the Python driver # supported by the Python driver
supports_paramstyle_pyformat = True supports_paramstyle_pyformat = True
# Does the backend require literal defaults, rather than parameterized ones? # Does the backend require literal defaults, rather than parameterized
# ones?
requires_literal_defaults = False requires_literal_defaults = False
# Does the backend support functions in defaults? # Does the backend support functions in defaults?
@ -213,7 +214,8 @@ class BaseDatabaseFeatures:
# Does the backend support the DEFAULT keyword in bulk insert queries? # Does the backend support the DEFAULT keyword in bulk insert queries?
supports_default_keyword_in_bulk_insert = True supports_default_keyword_in_bulk_insert = True
# Does the backend require a connection reset after each material schema change? # Does the backend require a connection reset after each material schema
# change?
connection_persists_old_columns = False connection_persists_old_columns = False
# What kind of error does the backend throw when accessing closed cursor? # What kind of error does the backend throw when accessing closed cursor?
@ -228,11 +230,12 @@ class BaseDatabaseFeatures:
# If NULL is implied on columns without needing to be explicitly specified # If NULL is implied on columns without needing to be explicitly specified
implied_column_null = False implied_column_null = False
# Does the backend support "select for update" queries with limit (and offset)? # Does the backend support "select for update" queries with limit (and
# offset)?
supports_select_for_update_with_limit = True supports_select_for_update_with_limit = True
# Does the backend ignore null expressions in GREATEST and LEAST queries unless # Does the backend ignore null expressions in GREATEST and LEAST queries
# every expression is null? # unless every expression is null?
greatest_least_ignores_nulls = False greatest_least_ignores_nulls = False
# Can the backend clone databases for parallel test execution? # Can the backend clone databases for parallel test execution?
@ -261,10 +264,10 @@ class BaseDatabaseFeatures:
# Does the database support ORDER BY in aggregate expressions? # Does the database support ORDER BY in aggregate expressions?
supports_aggregate_order_by_clause = False supports_aggregate_order_by_clause = False
# Does the database backend support DISTINCT when using multiple arguments in an # Does the database backend support DISTINCT when using multiple arguments
# aggregate expression? For example, Sqlite treats the "delimiter" argument of # in an aggregate expression? For example, Sqlite treats the "delimiter"
# STRING_AGG/GROUP_CONCAT as an extra argument and does not allow using a custom # argument of STRING_AGG/GROUP_CONCAT as an extra argument and does not
# delimiter along with DISTINCT. # allow using a custom delimiter along with DISTINCT.
supports_aggregate_distinct_multiple_argument = True supports_aggregate_distinct_multiple_argument = True
# Does the database support SQL 2023 ANY_VALUE in GROUP BY? # Does the database support SQL 2023 ANY_VALUE in GROUP BY?

View file

@ -158,8 +158,9 @@ class BaseDatabaseIntrospection:
def get_sequences(self, cursor, table_name, table_fields=()): def get_sequences(self, cursor, table_name, table_fields=()):
""" """
Return a list of introspected sequences for table_name. Each sequence Return a list of introspected sequences for table_name. Each sequence
is a dict: {'table': <table_name>, 'column': <column_name>}. An optional is a dict: {'table': <table_name>, 'column': <column_name>}. An
'name' key can be added if the backend supports named sequences. optional 'name' key can be added if the backend supports named
sequences.
""" """
raise NotImplementedError( raise NotImplementedError(
"subclasses of BaseDatabaseIntrospection may require a get_sequences() " "subclasses of BaseDatabaseIntrospection may require a get_sequences() "
@ -168,8 +169,8 @@ class BaseDatabaseIntrospection:
def get_relations(self, cursor, table_name): def get_relations(self, cursor, table_name):
""" """
Return a dictionary of {field_name: (field_name_other_table, other_table)} Return a dictionary of {field_name: (field_name_other_table,
representing all foreign keys in the given table. other_table)} representing all foreign keys in the given table.
""" """
raise NotImplementedError( raise NotImplementedError(
"subclasses of BaseDatabaseIntrospection may require a " "subclasses of BaseDatabaseIntrospection may require a "

View file

@ -546,8 +546,8 @@ class BaseDatabaseOperations:
def adapt_datetimefield_value(self, value): def adapt_datetimefield_value(self, value):
""" """
Transform a datetime value to an object compatible with what is expected Transform a datetime value to an object compatible with what is
by the backend driver for datetime columns. expected by the backend driver for datetime columns.
""" """
if value is None: if value is None:
return None return None

View file

@ -494,8 +494,8 @@ class BaseDatabaseSchemaEditor:
Return a quoted version of the value so it's safe to use in an SQL Return a quoted version of the value so it's safe to use in an SQL
string. This is not safe against injection from user code; it is string. This is not safe against injection from user code; it is
intended only for use in making SQL scripts or preparing default values intended only for use in making SQL scripts or preparing default values
for particularly tricky backends (defaults are not user-defined, though, for particularly tricky backends (defaults are not user-defined,
so this is safe). though, so this is safe).
""" """
raise NotImplementedError() raise NotImplementedError()
@ -1234,7 +1234,8 @@ class BaseDatabaseSchemaEditor:
self.execute(self._create_primary_key_sql(model, new_field)) self.execute(self._create_primary_key_sql(model, new_field))
# Update all referencing columns # Update all referencing columns
rels_to_update.extend(_related_non_m2m_objects(old_field, new_field)) rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))
# Handle our type alters on the other end of rels from the PK stuff above # Handle our type alters on the other end of rels from the PK stuff
# above
for old_rel, new_rel in rels_to_update: for old_rel, new_rel in rels_to_update:
rel_db_params = new_rel.field.db_parameters(connection=self.connection) rel_db_params = new_rel.field.db_parameters(connection=self.connection)
rel_type = rel_db_params["type"] rel_type = rel_db_params["type"]
@ -1483,7 +1484,8 @@ class BaseDatabaseSchemaEditor:
) )
self.alter_field( self.alter_field(
new_field.remote_field.through, new_field.remote_field.through,
# for self-referential models we need to alter field from the other end too # for self-referential models we need to alter field from the other
# end too
old_field.remote_field.through._meta.get_field(old_field.m2m_field_name()), old_field.remote_field.through._meta.get_field(old_field.m2m_field_name()),
new_field.remote_field.through._meta.get_field(new_field.m2m_field_name()), new_field.remote_field.through._meta.get_field(new_field.m2m_field_name()),
) )

View file

@ -1,7 +1,8 @@
""" """
Dummy database backend for Django. Dummy database backend for Django.
Django uses this if the database ENGINE setting is empty (None or empty string). Django uses this if the database ENGINE setting is empty (None or empty
string).
Each of these API functions, except connection.close(), raise Each of these API functions, except connection.close(), raise
ImproperlyConfigured. ImproperlyConfigured.

View file

@ -22,7 +22,8 @@ except ImportError as err:
from MySQLdb.constants import CLIENT, FIELD_TYPE from MySQLdb.constants import CLIENT, FIELD_TYPE
from MySQLdb.converters import conversions from MySQLdb.converters import conversions
# Some of these import MySQLdb, so import them after checking if it's installed. # Some of these import MySQLdb, so import them after checking if it's
# installed.
from .client import DatabaseClient from .client import DatabaseClient
from .creation import DatabaseCreation from .creation import DatabaseCreation
from .features import DatabaseFeatures from .features import DatabaseFeatures
@ -57,7 +58,8 @@ class CursorWrapper:
exception instances and reraises them with the correct types. exception instances and reraises them with the correct types.
Implemented as a wrapper, rather than a subclass, so that it isn't stuck Implemented as a wrapper, rather than a subclass, so that it isn't stuck
to the particular underlying representation returned by Connection.cursor(). to the particular underlying representation returned by
Connection.cursor().
""" """
codes_for_integrityerror = ( codes_for_integrityerror = (
@ -101,9 +103,10 @@ class CursorWrapper:
class DatabaseWrapper(BaseDatabaseWrapper): class DatabaseWrapper(BaseDatabaseWrapper):
vendor = "mysql" vendor = "mysql"
# This dictionary maps Field objects to their associated MySQL column # This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll # types, as strings. Column-type strings can contain format strings;
# be interpolated against the values of Field.__dict__ before being output. # they'll be interpolated against the values of Field.__dict__ before being
# If a column type is set to None, it won't be included in the output. # output. If a column type is set to None, it won't be included in the
# output.
_data_types = { _data_types = {
"AutoField": "integer AUTO_INCREMENT", "AutoField": "integer AUTO_INCREMENT",
@ -175,13 +178,13 @@ class DatabaseWrapper(BaseDatabaseWrapper):
} }
# The patterns below are used to generate SQL pattern lookup clauses when # The patterns below are used to generate SQL pattern lookup clauses when
# the right-hand side of the lookup isn't a raw string (it might be an expression # the right-hand side of the lookup isn't a raw string (it might be an
# or the result of a bilateral transformation). # expression or the result of a bilateral transformation). In those cases,
# In those cases, special characters for LIKE operators (e.g. \, *, _) should be # special characters for LIKE operators (e.g. \, *, _) should be escaped on
# escaped on database side. # database side.
# #
# Note: we use str.format() here for readability as '%' is used as a wildcard for # Note: we use str.format() here for readability as '%' is used as a
# the LIKE operator. # wildcard for the LIKE operator.
pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\\', '\\\\'), '%%', '\%%'), '_', '\_')" pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\\', '\\\\'), '%%', '\%%'), '_', '\_')"
pattern_ops = { pattern_ops = {
"contains": "LIKE BINARY CONCAT('%%', {}, '%%')", "contains": "LIKE BINARY CONCAT('%%', {}, '%%')",

View file

@ -137,7 +137,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@cached_property @cached_property
def _mysql_storage_engine(self): def _mysql_storage_engine(self):
"Internal method used in Django tests. Don't rely on this from your code" """
Internal method used in Django tests. Don't rely on this from your code
"""
return self.connection.mysql_server_data["default_storage_engine"] return self.connection.mysql_server_data["default_storage_engine"]
@cached_property @cached_property

View file

@ -131,9 +131,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
) )
row = cursor.fetchone() row = cursor.fetchone()
default_column_collation = row[0] if row else "" default_column_collation = row[0] if row else ""
# information_schema database gives more accurate results for some figures: # information_schema database gives more accurate results for some
# - varchar length returned by cursor.description is an internal length, # figures:
# not visible length (#5725) # - varchar length returned by cursor.description is an internal
# length, not visible length (#5725)
# - precision and scale (for decimal fields) (#5014) # - precision and scale (for decimal fields) (#5014)
# - auto_increment is not available in cursor.description # - auto_increment is not available in cursor.description
cursor.execute( cursor.execute(
@ -195,8 +196,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
def get_relations(self, cursor, table_name): def get_relations(self, cursor, table_name):
""" """
Return a dictionary of {field_name: (field_name_other_table, other_table)} Return a dictionary of {field_name: (field_name_other_table,
representing all foreign keys in the given table. other_table)} representing all foreign keys in the given table.
""" """
cursor.execute( cursor.execute(
""" """

View file

@ -359,7 +359,8 @@ class DatabaseOperations(BaseDatabaseOperations):
return "TIMESTAMPDIFF(MICROSECOND, %s, %s)" % (rhs_sql, lhs_sql), params return "TIMESTAMPDIFF(MICROSECOND, %s, %s)" % (rhs_sql, lhs_sql), params
def explain_query_prefix(self, format=None, **options): def explain_query_prefix(self, format=None, **options):
# Alias MySQL's TRADITIONAL to TEXT for consistency with other backends. # Alias MySQL's TRADITIONAL to TEXT for consistency with other
# backends.
if format and format.upper() == "TEXT": if format and format.upper() == "TEXT":
format = "TRADITIONAL" format = "TRADITIONAL"
elif ( elif (

View file

@ -49,8 +49,8 @@ _setup_environment(
[ [
# Oracle takes client-side character set encoding from the environment. # Oracle takes client-side character set encoding from the environment.
("NLS_LANG", ".AL32UTF8"), ("NLS_LANG", ".AL32UTF8"),
# This prevents Unicode from getting mangled by getting encoded into the # This prevents Unicode from getting mangled by getting encoded into
# potentially non-Unicode database character set. # the potentially non-Unicode database character set.
("ORA_NCHAR_LITERAL_REPLACE", "TRUE"), ("ORA_NCHAR_LITERAL_REPLACE", "TRUE"),
] ]
) )
@ -110,12 +110,13 @@ class DatabaseWrapper(BaseDatabaseWrapper):
vendor = "oracle" vendor = "oracle"
display_name = "Oracle" display_name = "Oracle"
# This dictionary maps Field objects to their associated Oracle column # This dictionary maps Field objects to their associated Oracle column
# types, as strings. Column-type strings can contain format strings; they'll # types, as strings. Column-type strings can contain format strings;
# be interpolated against the values of Field.__dict__ before being output. # they'll be interpolated against the values of Field.__dict__ before being
# If a column type is set to None, it won't be included in the output. # output. If a column type is set to None, it won't be included in the
# output.
# #
# Any format strings starting with "qn_" are quoted before being used in the # Any format strings starting with "qn_" are quoted before being used in
# output (the "qn_" prefix is stripped before the lookup is performed. # the output (the "qn_" prefix is stripped before the lookup is performed.
data_types = { data_types = {
"AutoField": "NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY", "AutoField": "NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY",
"BigAutoField": "NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY", "BigAutoField": "NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY",
@ -200,13 +201,13 @@ class DatabaseWrapper(BaseDatabaseWrapper):
} }
# The patterns below are used to generate SQL pattern lookup clauses when # The patterns below are used to generate SQL pattern lookup clauses when
# the right-hand side of the lookup isn't a raw string (it might be an expression # the right-hand side of the lookup isn't a raw string (it might be an
# or the result of a bilateral transformation). # expression or the result of a bilateral transformation). In those cases,
# In those cases, special characters for LIKE operators (e.g. \, %, _) # special characters for LIKE operators (e.g. \, %, _) should be escaped on
# should be escaped on the database side. # the database side.
# #
# Note: we use str.format() here for readability as '%' is used as a wildcard for # Note: we use str.format() here for readability as '%' is used as a
# the LIKE operator. # wildcard for the LIKE operator.
pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\', '\\'), '%%', '\%%'), '_', '\_')" pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\', '\\'), '%%', '\%%'), '_', '\_')"
_pattern_ops = { _pattern_ops = {
"contains": "'%%' || {} || '%%'", "contains": "'%%' || {} || '%%'",

View file

@ -36,7 +36,8 @@ class DatabaseCreation(BaseDatabaseCreation):
) )
except Exception as e: except Exception as e:
if "ORA-01543" not in str(e): if "ORA-01543" not in str(e):
# All errors except "tablespace already exists" cancel tests # All errors except "tablespace already exists" cancel
# tests
self.log("Got an error creating the test database: %s" % e) self.log("Got an error creating the test database: %s" % e)
sys.exit(2) sys.exit(2)
if not autoclobber: if not autoclobber:
@ -406,7 +407,8 @@ class DatabaseCreation(BaseDatabaseCreation):
def _test_database_passwd(self): def _test_database_passwd(self):
password = self._test_settings_get("PASSWORD") password = self._test_settings_get("PASSWORD")
if password is None and self._test_user_create(): if password is None and self._test_user_create():
# Oracle passwords are limited to 30 chars and can't contain symbols. # Oracle passwords are limited to 30 chars and can't contain
# symbols.
password = get_random_string(30) password = get_random_string(30)
return password return password

View file

@ -254,8 +254,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
def get_relations(self, cursor, table_name): def get_relations(self, cursor, table_name):
""" """
Return a dictionary of {field_name: (field_name_other_table, other_table)} Return a dictionary of {field_name: (field_name_other_table,
representing all foreign keys in the given table. other_table)} representing all foreign keys in the given table.
""" """
table_name = table_name.upper() table_name = table_name.upper()
cursor.execute( cursor.execute(

Some files were not shown because too many files have changed in this diff Show more