mirror of
https://github.com/django/django.git
synced 2024-12-22 09:05:43 +00:00
Refs #33476 -- Refactored code to strictly match 88 characters line length.
This commit is contained in:
parent
9c19aff7c7
commit
7119f40c98
@ -224,9 +224,9 @@ class Apps:
|
||||
and model.__module__ == app_models[model_name].__module__
|
||||
):
|
||||
warnings.warn(
|
||||
"Model '%s.%s' was already registered. "
|
||||
"Reloading models is not advised as it can lead to inconsistencies, "
|
||||
"most notably with related models." % (app_label, model_name),
|
||||
"Model '%s.%s' was already registered. Reloading models is not "
|
||||
"advised as it can lead to inconsistencies, most notably with "
|
||||
"related models." % (app_label, model_name),
|
||||
RuntimeWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
@ -21,8 +21,8 @@ DEBUG = False
|
||||
# on a live site.
|
||||
DEBUG_PROPAGATE_EXCEPTIONS = False
|
||||
|
||||
# People who get code error notifications.
|
||||
# In the format [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')]
|
||||
# People who get code error notifications. In the format
|
||||
# [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')]
|
||||
ADMINS = []
|
||||
|
||||
# List of IP addresses, as strings, that:
|
||||
@ -319,7 +319,8 @@ DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000
|
||||
FILE_UPLOAD_TEMP_DIR = None
|
||||
|
||||
# The numeric mode to set newly-uploaded files to. The value should be a mode
|
||||
# you'd pass directly to os.chmod; see https://docs.python.org/library/os.html#files-and-directories.
|
||||
# you'd pass directly to os.chmod; see
|
||||
# https://docs.python.org/library/os.html#files-and-directories.
|
||||
FILE_UPLOAD_PERMISSIONS = 0o644
|
||||
|
||||
# The numeric mode to assign to newly-created directories, when uploading files.
|
||||
|
@ -447,9 +447,9 @@ class BaseModelAdminChecks:
|
||||
):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' cannot include the ManyToManyField '%s', "
|
||||
"because that field manually specifies a relationship model."
|
||||
% (label, field_name),
|
||||
"The value of '%s' cannot include the ManyToManyField "
|
||||
"'%s', because that field manually specifies a "
|
||||
"relationship model." % (label, field_name),
|
||||
obj=obj.__class__,
|
||||
id="admin.E013",
|
||||
)
|
||||
@ -568,8 +568,8 @@ class BaseModelAdminChecks:
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to '%s', which is not an "
|
||||
"instance of ForeignKey, and does not have a 'choices' definition."
|
||||
% (label, field_name),
|
||||
"instance of ForeignKey, and does not have a 'choices' "
|
||||
"definition." % (label, field_name),
|
||||
obj=obj.__class__,
|
||||
id="admin.E023",
|
||||
)
|
||||
@ -585,8 +585,8 @@ class BaseModelAdminChecks:
|
||||
if val not in (HORIZONTAL, VERTICAL):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' must be either admin.HORIZONTAL or admin.VERTICAL."
|
||||
% label,
|
||||
"The value of '%s' must be either admin.HORIZONTAL or "
|
||||
"admin.VERTICAL." % label,
|
||||
obj=obj.__class__,
|
||||
id="admin.E024",
|
||||
)
|
||||
@ -598,7 +598,8 @@ class BaseModelAdminChecks:
|
||||
if not callable(obj.view_on_site) and not isinstance(obj.view_on_site, bool):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of 'view_on_site' must be a callable or a boolean value.",
|
||||
"The value of 'view_on_site' must be a callable or a boolean "
|
||||
"value.",
|
||||
obj=obj.__class__,
|
||||
id="admin.E025",
|
||||
)
|
||||
@ -643,9 +644,9 @@ class BaseModelAdminChecks:
|
||||
):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to '%s', which must not be a DateTimeField, "
|
||||
"a ForeignKey, a OneToOneField, or a ManyToManyField."
|
||||
% (label, field_name),
|
||||
"The value of '%s' refers to '%s', which must not be a "
|
||||
"DateTimeField, a ForeignKey, a OneToOneField, or a "
|
||||
"ManyToManyField." % (label, field_name),
|
||||
obj=obj.__class__,
|
||||
id="admin.E028",
|
||||
)
|
||||
@ -955,8 +956,8 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||
if field_name not in obj.list_display:
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to '%s', which is not defined in 'list_display'."
|
||||
% (label, field_name),
|
||||
"The value of '%s' refers to '%s', which is not defined in "
|
||||
"'list_display'." % (label, field_name),
|
||||
obj=obj.__class__,
|
||||
id="admin.E111",
|
||||
)
|
||||
@ -1027,8 +1028,8 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||
except (NotRelationField, FieldDoesNotExist):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to '%s', which does not refer to a Field."
|
||||
% (label, field),
|
||||
"The value of '%s' refers to '%s', which does not refer to a "
|
||||
"Field." % (label, field),
|
||||
obj=obj.__class__,
|
||||
id="admin.E116",
|
||||
)
|
||||
@ -1107,8 +1108,8 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||
elif obj.list_display_links and field_name in obj.list_display_links:
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' cannot be in both 'list_editable' and 'list_display_links'."
|
||||
% field_name,
|
||||
"The value of '%s' cannot be in both 'list_editable' and "
|
||||
"'list_display_links'." % field_name,
|
||||
obj=obj.__class__,
|
||||
id="admin.E123",
|
||||
)
|
||||
@ -1122,9 +1123,9 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||
):
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to the first field in 'list_display' ('%s'), "
|
||||
"which cannot be used unless 'list_display_links' is set."
|
||||
% (label, obj.list_display[0]),
|
||||
"The value of '%s' refers to the first field in 'list_display' "
|
||||
"('%s'), which cannot be used unless 'list_display_links' is "
|
||||
"set." % (label, obj.list_display[0]),
|
||||
obj=obj.__class__,
|
||||
id="admin.E124",
|
||||
)
|
||||
@ -1132,8 +1133,8 @@ class ModelAdminChecks(BaseModelAdminChecks):
|
||||
elif not field.editable:
|
||||
return [
|
||||
checks.Error(
|
||||
"The value of '%s' refers to '%s', which is not editable through the admin."
|
||||
% (label, field_name),
|
||||
"The value of '%s' refers to '%s', which is not editable "
|
||||
"through the admin." % (label, field_name),
|
||||
obj=obj.__class__,
|
||||
id="admin.E125",
|
||||
)
|
||||
|
@ -64,7 +64,8 @@ class LogEntry(models.Model):
|
||||
null=True,
|
||||
)
|
||||
object_id = models.TextField(_("object id"), blank=True, null=True)
|
||||
# Translators: 'repr' means representation (https://docs.python.org/library/functions.html#repr)
|
||||
# Translators: 'repr' means representation
|
||||
# (https://docs.python.org/library/functions.html#repr)
|
||||
object_repr = models.CharField(_("object repr"), max_length=200)
|
||||
action_flag = models.PositiveSmallIntegerField(
|
||||
_("action flag"), choices=ACTION_FLAG_CHOICES
|
||||
|
@ -1276,7 +1276,9 @@ class ModelAdmin(BaseModelAdmin):
|
||||
"has_add_permission": self.has_add_permission(request),
|
||||
"has_change_permission": self.has_change_permission(request, obj),
|
||||
"has_delete_permission": self.has_delete_permission(request, obj),
|
||||
"has_editable_inline_admin_formsets": has_editable_inline_admin_formsets,
|
||||
"has_editable_inline_admin_formsets": (
|
||||
has_editable_inline_admin_formsets
|
||||
),
|
||||
"has_file_field": context["adminform"].form.is_multipart()
|
||||
or any(
|
||||
admin_formset.formset.is_multipart()
|
||||
@ -1383,7 +1385,8 @@ class ModelAdmin(BaseModelAdmin):
|
||||
elif "_addanother" in request.POST:
|
||||
msg = format_html(
|
||||
_(
|
||||
"The {name} “{obj}” was added successfully. You may add another {name} below."
|
||||
"The {name} “{obj}” was added successfully. You may add another "
|
||||
"{name} below."
|
||||
),
|
||||
**msg_dict,
|
||||
)
|
||||
@ -1444,7 +1447,8 @@ class ModelAdmin(BaseModelAdmin):
|
||||
if "_continue" in request.POST:
|
||||
msg = format_html(
|
||||
_(
|
||||
"The {name} “{obj}” was changed successfully. You may edit it again below."
|
||||
"The {name} “{obj}” was changed successfully. You may edit it "
|
||||
"again below."
|
||||
),
|
||||
**msg_dict,
|
||||
)
|
||||
@ -1458,7 +1462,8 @@ class ModelAdmin(BaseModelAdmin):
|
||||
elif "_saveasnew" in request.POST:
|
||||
msg = format_html(
|
||||
_(
|
||||
"The {name} “{obj}” was added successfully. You may edit it again below."
|
||||
"The {name} “{obj}” was added successfully. You may edit it again "
|
||||
"below."
|
||||
),
|
||||
**msg_dict,
|
||||
)
|
||||
@ -1476,7 +1481,8 @@ class ModelAdmin(BaseModelAdmin):
|
||||
elif "_addanother" in request.POST:
|
||||
msg = format_html(
|
||||
_(
|
||||
"The {name} “{obj}” was changed successfully. You may add another {name} below."
|
||||
"The {name} “{obj}” was changed successfully. You may add another "
|
||||
"{name} below."
|
||||
),
|
||||
**msg_dict,
|
||||
)
|
||||
@ -2389,8 +2395,9 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||
objs = []
|
||||
for p in collector.protected:
|
||||
objs.append(
|
||||
# Translators: Model verbose name and instance representation,
|
||||
# suitable to be an item in a list.
|
||||
# Translators: Model verbose name and instance
|
||||
# representation, suitable to be an item in a
|
||||
# list.
|
||||
_("%(class_name)s %(instance)s")
|
||||
% {"class_name": p._meta.verbose_name, "instance": p}
|
||||
)
|
||||
|
@ -32,7 +32,7 @@ def get_admin_log(parser, token):
|
||||
|
||||
Usage::
|
||||
|
||||
{% get_admin_log [limit] as [varname] for_user [context_var_containing_user_obj] %}
|
||||
{% get_admin_log [limit] as [varname] for_user [context_var_with_user_obj] %}
|
||||
|
||||
Examples::
|
||||
|
||||
|
@ -70,12 +70,14 @@ def authenticate(request=None, **credentials):
|
||||
try:
|
||||
backend_signature.bind(request, **credentials)
|
||||
except TypeError:
|
||||
# This backend doesn't accept these credentials as arguments. Try the next one.
|
||||
# This backend doesn't accept these credentials as arguments. Try
|
||||
# the next one.
|
||||
continue
|
||||
try:
|
||||
user = backend.authenticate(request, **credentials)
|
||||
except PermissionDenied:
|
||||
# This backend says to stop in our tracks - this user should not be allowed in at all.
|
||||
# This backend says to stop in our tracks - this user should not be
|
||||
# allowed in at all.
|
||||
break
|
||||
if user is None:
|
||||
continue
|
||||
|
@ -61,8 +61,8 @@ def check_user_model(app_configs=None, **kwargs):
|
||||
]:
|
||||
errors.append(
|
||||
checks.Error(
|
||||
"'%s.%s' must be unique because it is named as the 'USERNAME_FIELD'."
|
||||
% (cls._meta.object_name, cls.USERNAME_FIELD),
|
||||
"'%s.%s' must be unique because it is named as the "
|
||||
"'USERNAME_FIELD'." % (cls._meta.object_name, cls.USERNAME_FIELD),
|
||||
obj=cls,
|
||||
id="auth.E003",
|
||||
)
|
||||
@ -72,7 +72,10 @@ def check_user_model(app_configs=None, **kwargs):
|
||||
checks.Warning(
|
||||
"'%s.%s' is named as the 'USERNAME_FIELD', but it is not unique."
|
||||
% (cls._meta.object_name, cls.USERNAME_FIELD),
|
||||
hint="Ensure that your authentication backend(s) can handle non-unique usernames.",
|
||||
hint=(
|
||||
"Ensure that your authentication backend(s) can handle "
|
||||
"non-unique usernames."
|
||||
),
|
||||
obj=cls,
|
||||
id="auth.W004",
|
||||
)
|
||||
@ -197,8 +200,8 @@ def check_models_permissions(app_configs=None, **kwargs):
|
||||
if codename in builtin_permissions:
|
||||
errors.append(
|
||||
checks.Error(
|
||||
"The permission codenamed '%s' clashes with a builtin permission "
|
||||
"for model '%s'." % (codename, opts.label),
|
||||
"The permission codenamed '%s' clashes with a builtin "
|
||||
"permission for model '%s'." % (codename, opts.label),
|
||||
obj=model,
|
||||
id="auth.E005",
|
||||
)
|
||||
|
@ -24,7 +24,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"username",
|
||||
nargs="?",
|
||||
help="Username to change password for; by default, it's the current username.",
|
||||
help=(
|
||||
"Username to change password for; by default, it's the current "
|
||||
"username."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
|
@ -102,14 +102,20 @@ class Migration(migrations.Migration):
|
||||
"is_superuser",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
||||
help_text=(
|
||||
"Designates that this user has all permissions without "
|
||||
"explicitly assigning them."
|
||||
),
|
||||
verbose_name="superuser status",
|
||||
),
|
||||
),
|
||||
(
|
||||
"username",
|
||||
models.CharField(
|
||||
help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
help_text=(
|
||||
"Required. 30 characters or fewer. Letters, digits and "
|
||||
"@/./+/-/_ only."
|
||||
),
|
||||
unique=True,
|
||||
max_length=30,
|
||||
verbose_name="username",
|
||||
@ -138,7 +144,9 @@ class Migration(migrations.Migration):
|
||||
"is_staff",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates whether the user can log into this admin site.",
|
||||
help_text=(
|
||||
"Designates whether the user can log into this admin site."
|
||||
),
|
||||
verbose_name="staff status",
|
||||
),
|
||||
),
|
||||
@ -148,8 +156,8 @@ class Migration(migrations.Migration):
|
||||
default=True,
|
||||
verbose_name="active",
|
||||
help_text=(
|
||||
"Designates whether this user should be treated as active. Unselect this instead of deleting "
|
||||
"accounts."
|
||||
"Designates whether this user should be treated as active. "
|
||||
"Unselect this instead of deleting accounts."
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -168,8 +176,8 @@ class Migration(migrations.Migration):
|
||||
related_name="user_set",
|
||||
related_query_name="user",
|
||||
help_text=(
|
||||
"The groups this user belongs to. A user will get all permissions granted to each of their "
|
||||
"groups."
|
||||
"The groups this user belongs to. A user will get all "
|
||||
"permissions granted to each of their groups."
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -17,7 +17,10 @@ class Migration(migrations.Migration):
|
||||
error_messages={"unique": "A user with that username already exists."},
|
||||
max_length=30,
|
||||
validators=[validators.UnicodeUsernameValidator()],
|
||||
help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
help_text=(
|
||||
"Required. 30 characters or fewer. Letters, digits and @/./+/-/_ "
|
||||
"only."
|
||||
),
|
||||
unique=True,
|
||||
verbose_name="username",
|
||||
),
|
||||
|
@ -14,7 +14,10 @@ class Migration(migrations.Migration):
|
||||
name="username",
|
||||
field=models.CharField(
|
||||
error_messages={"unique": "A user with that username already exists."},
|
||||
help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
help_text=(
|
||||
"Required. 30 characters or fewer. Letters, digits and @/./+/-/_ "
|
||||
"only."
|
||||
),
|
||||
max_length=30,
|
||||
unique=True,
|
||||
validators=[validators.UnicodeUsernameValidator()],
|
||||
|
@ -14,7 +14,10 @@ class Migration(migrations.Migration):
|
||||
name="username",
|
||||
field=models.CharField(
|
||||
error_messages={"unique": "A user with that username already exists."},
|
||||
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
help_text=(
|
||||
"Required. 150 characters or fewer. Letters, digits and @/./+/-/_ "
|
||||
"only."
|
||||
),
|
||||
max_length=150,
|
||||
unique=True,
|
||||
validators=[validators.UnicodeUsernameValidator()],
|
||||
|
@ -25,8 +25,9 @@ class AccessMixin:
|
||||
login_url = self.login_url or settings.LOGIN_URL
|
||||
if not login_url:
|
||||
raise ImproperlyConfigured(
|
||||
"{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override "
|
||||
"{0}.get_login_url().".format(self.__class__.__name__)
|
||||
f"{self.__class__.__name__} is missing the login_url attribute. Define "
|
||||
f"{self.__class__.__name__}.login_url, settings.LOGIN_URL, or override "
|
||||
f"{self.__class__.__name__}.get_login_url()."
|
||||
)
|
||||
return str(login_url)
|
||||
|
||||
@ -84,8 +85,10 @@ class PermissionRequiredMixin(AccessMixin):
|
||||
"""
|
||||
if self.permission_required is None:
|
||||
raise ImproperlyConfigured(
|
||||
"{0} is missing the permission_required attribute. Define {0}.permission_required, or override "
|
||||
"{0}.get_permission_required().".format(self.__class__.__name__)
|
||||
f"{self.__class__.__name__} is missing the "
|
||||
f"permission_required attribute. Define "
|
||||
f"{self.__class__.__name__}.permission_required, or override "
|
||||
f"{self.__class__.__name__}.get_permission_required()."
|
||||
)
|
||||
if isinstance(self.permission_required, str):
|
||||
perms = (self.permission_required,)
|
||||
|
@ -435,7 +435,8 @@ class AnonymousUser:
|
||||
|
||||
def __int__(self):
|
||||
raise TypeError(
|
||||
"Cannot cast AnonymousUser to int. Are you trying to use it in place of User?"
|
||||
"Cannot cast AnonymousUser to int. Are you trying to use it in place of "
|
||||
"User?"
|
||||
)
|
||||
|
||||
def save(self):
|
||||
|
@ -28,7 +28,10 @@ def get_password_validators(validator_config):
|
||||
try:
|
||||
klass = import_string(validator["NAME"])
|
||||
except ImportError:
|
||||
msg = "The module in NAME could not be imported: %s. Check your AUTH_PASSWORD_VALIDATORS setting."
|
||||
msg = (
|
||||
"The module in NAME could not be imported: %s. Check your "
|
||||
"AUTH_PASSWORD_VALIDATORS setting."
|
||||
)
|
||||
raise ImproperlyConfigured(msg % validator["NAME"])
|
||||
validators.append(klass(**validator.get("OPTIONS", {})))
|
||||
|
||||
@ -105,8 +108,10 @@ class MinimumLengthValidator:
|
||||
if len(password) < self.min_length:
|
||||
raise ValidationError(
|
||||
ngettext(
|
||||
"This password is too short. It must contain at least %(min_length)d character.",
|
||||
"This password is too short. It must contain at least %(min_length)d characters.",
|
||||
"This password is too short. It must contain at least "
|
||||
"%(min_length)d character.",
|
||||
"This password is too short. It must contain at least "
|
||||
"%(min_length)d characters.",
|
||||
self.min_length,
|
||||
),
|
||||
code="password_too_short",
|
||||
|
@ -19,8 +19,8 @@ class GenericInlineModelAdminChecks(InlineModelAdminChecks):
|
||||
return []
|
||||
|
||||
def _check_relation(self, obj, parent_model):
|
||||
# There's no FK, but we do need to confirm that the ct_field and ct_fk_field are valid,
|
||||
# and that they are part of a GenericForeignKey.
|
||||
# There's no FK, but we do need to confirm that the ct_field and
|
||||
# ct_fk_field are valid, and that they are part of a GenericForeignKey.
|
||||
|
||||
gfks = [
|
||||
f
|
||||
@ -75,7 +75,8 @@ class GenericInlineModelAdminChecks(InlineModelAdminChecks):
|
||||
|
||||
return [
|
||||
checks.Error(
|
||||
"'%s' has no GenericForeignKey using content type field '%s' and object ID field '%s'."
|
||||
"'%s' has no GenericForeignKey using content type field '%s' and "
|
||||
"object ID field '%s'."
|
||||
% (
|
||||
obj.model._meta.label,
|
||||
obj.ct_field,
|
||||
|
@ -120,8 +120,9 @@ class ContentTypeManager(models.Manager):
|
||||
|
||||
def _add_to_cache(self, using, ct):
|
||||
"""Insert a ContentType into the cache."""
|
||||
# Note it's possible for ContentType objects to be stale; model_class() will return None.
|
||||
# Hence, there is no reliance on model._meta.app_label here, just using the model fields instead.
|
||||
# Note it's possible for ContentType objects to be stale; model_class()
|
||||
# will return None. Hence, there is no reliance on
|
||||
# model._meta.app_label here, just using the model fields instead.
|
||||
key = (ct.app_label, ct.model)
|
||||
self._cache.setdefault(using, {})[key] = ct
|
||||
self._cache.setdefault(using, {})[ct.id] = ct
|
||||
|
@ -12,7 +12,8 @@ class FlatpageForm(forms.ModelForm):
|
||||
max_length=100,
|
||||
regex=r"^[-\w/\.~]+$",
|
||||
help_text=_(
|
||||
"Example: “/about/contact/”. Make sure to have leading and trailing slashes."
|
||||
"Example: “/about/contact/”. Make sure to have leading and trailing "
|
||||
"slashes."
|
||||
),
|
||||
error_messages={
|
||||
"invalid": _(
|
||||
|
@ -34,8 +34,8 @@ class Migration(migrations.Migration):
|
||||
"template_name",
|
||||
models.CharField(
|
||||
help_text=(
|
||||
"Example: “flatpages/contact_page.html”. If this isn’t provided, the system will use "
|
||||
"“flatpages/default.html”."
|
||||
"Example: “flatpages/contact_page.html”. If this isn’t "
|
||||
"provided, the system will use “flatpages/default.html”."
|
||||
),
|
||||
max_length=70,
|
||||
verbose_name="template name",
|
||||
@ -46,7 +46,10 @@ class Migration(migrations.Migration):
|
||||
"registration_required",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="If this is checked, only logged-in users will be able to view the page.",
|
||||
help_text=(
|
||||
"If this is checked, only logged-in users will be able to "
|
||||
"view the page."
|
||||
),
|
||||
verbose_name="registration required",
|
||||
),
|
||||
),
|
||||
|
@ -158,12 +158,14 @@ class BaseSpatialOperations:
|
||||
# Routines for getting the OGC-compliant models.
|
||||
def geometry_columns(self):
|
||||
raise NotImplementedError(
|
||||
"Subclasses of BaseSpatialOperations must provide a geometry_columns() method."
|
||||
"Subclasses of BaseSpatialOperations must provide a geometry_columns() "
|
||||
"method."
|
||||
)
|
||||
|
||||
def spatial_ref_sys(self):
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseSpatialOperations must a provide spatial_ref_sys() method"
|
||||
"subclasses of BaseSpatialOperations must a provide spatial_ref_sys() "
|
||||
"method"
|
||||
)
|
||||
|
||||
distance_expr_for_lookup = staticmethod(Distance)
|
||||
|
@ -20,7 +20,8 @@ class DatabaseFeatures(BaseSpatialFeatures, OracleDatabaseFeatures):
|
||||
skips.update(
|
||||
{
|
||||
"Oracle doesn't support spatial operators in constraints.": {
|
||||
"gis_tests.gis_migrations.test_operations.OperationTests.test_add_check_constraint",
|
||||
"gis_tests.gis_migrations.test_operations.OperationTests."
|
||||
"test_add_check_constraint",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -40,7 +40,10 @@ class SDORelate(SpatialOperator):
|
||||
sql_template = "SDO_RELATE(%(lhs)s, %(rhs)s, 'mask=%(mask)s') = 'TRUE'"
|
||||
|
||||
def check_relate_argument(self, arg):
|
||||
masks = "TOUCH|OVERLAPBDYDISJOINT|OVERLAPBDYINTERSECT|EQUAL|INSIDE|COVEREDBY|CONTAINS|COVERS|ANYINTERACT|ON"
|
||||
masks = (
|
||||
"TOUCH|OVERLAPBDYDISJOINT|OVERLAPBDYINTERSECT|EQUAL|INSIDE|COVEREDBY|"
|
||||
"CONTAINS|COVERS|ANYINTERACT|ON"
|
||||
)
|
||||
mask_regex = re.compile(r"^(%s)(\+(%s))*$" % (masks, masks), re.I)
|
||||
if not isinstance(arg, str) or not mask_regex.match(arg):
|
||||
raise ValueError('Invalid SDO_RELATE mask: "%s"' % arg)
|
||||
@ -105,7 +108,8 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
||||
"exact": SDOOperator(func="SDO_EQUAL"),
|
||||
"overlaps": SDOOperator(func="SDO_OVERLAPS"),
|
||||
"same_as": SDOOperator(func="SDO_EQUAL"),
|
||||
"relate": SDORelate(), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
|
||||
# Oracle uses a different syntax, e.g., 'mask=inside+touch'
|
||||
"relate": SDORelate(),
|
||||
"touches": SDOOperator(func="SDO_TOUCH"),
|
||||
"within": SDOOperator(func="SDO_INSIDE"),
|
||||
"dwithin": SDODWithin(),
|
||||
|
@ -16,7 +16,10 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
||||
),
|
||||
%(srid)s
|
||||
)"""
|
||||
sql_add_spatial_index = "CREATE INDEX %(index)s ON %(table)s(%(column)s) INDEXTYPE IS MDSYS.SPATIAL_INDEX"
|
||||
sql_add_spatial_index = (
|
||||
"CREATE INDEX %(index)s ON %(table)s(%(column)s) "
|
||||
"INDEXTYPE IS MDSYS.SPATIAL_INDEX"
|
||||
)
|
||||
sql_drop_spatial_index = "DROP INDEX %(index)s"
|
||||
sql_clear_geometry_table_metadata = (
|
||||
"DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s"
|
||||
|
@ -56,7 +56,7 @@ STRUCT_SIZE = {
|
||||
# whether the band data is stored as part of the datum or is to be found on the
|
||||
# server's filesystem. There are currently 11 supported pixel value types, so 4
|
||||
# bits are enough to account for all. Reserve the upper 4 bits for generic
|
||||
# flags.
|
||||
# See https://trac.osgeo.org/postgis/wiki/WKTRaster/RFC/RFC1_V0SerialFormat#Pixeltypeandstorageflag
|
||||
# flags. See
|
||||
# https://trac.osgeo.org/postgis/wiki/WKTRaster/RFC/RFC1_V0SerialFormat#Pixeltypeandstorageflag
|
||||
BANDTYPE_PIXTYPE_MASK = 0x0F
|
||||
BANDTYPE_FLAG_HASNODATA = 1 << 6
|
||||
|
@ -22,7 +22,9 @@ class PostGISIntrospection(DatabaseIntrospection):
|
||||
# dictionary isn't updated until introspection is performed here.
|
||||
with self.connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography')"
|
||||
"SELECT oid, typname "
|
||||
"FROM pg_type "
|
||||
"WHERE typname IN ('geometry', 'geography')"
|
||||
)
|
||||
self.postgis_oid_lookup = dict(cursor.fetchall())
|
||||
self.data_types_reverse.update(
|
||||
|
@ -56,7 +56,8 @@ class PostGISOperator(SpatialOperator):
|
||||
if lookup.band_lhs is not None and lhs_is_raster:
|
||||
if not self.func:
|
||||
raise ValueError(
|
||||
"Band indices are not allowed for this operator, it works on bbox only."
|
||||
"Band indices are not allowed for this operator, it works on bbox "
|
||||
"only."
|
||||
)
|
||||
template_params["lhs"] = "%s, %s" % (
|
||||
template_params["lhs"],
|
||||
@ -66,7 +67,8 @@ class PostGISOperator(SpatialOperator):
|
||||
if lookup.band_rhs is not None and rhs_is_raster:
|
||||
if not self.func:
|
||||
raise ValueError(
|
||||
"Band indices are not allowed for this operator, it works on bbox only."
|
||||
"Band indices are not allowed for this operator, it works on bbox "
|
||||
"only."
|
||||
)
|
||||
template_params["rhs"] = "%s, %s" % (
|
||||
template_params["rhs"],
|
||||
|
@ -317,9 +317,11 @@ class Distance(DistanceResultMixin, OracleToleranceMixin, GeoFunc):
|
||||
)
|
||||
|
||||
if not geography and self.geo_field.geodetic(connection):
|
||||
# Geometry fields with geodetic (lon/lat) coordinates need special distance functions
|
||||
# Geometry fields with geodetic (lon/lat) coordinates need special
|
||||
# distance functions.
|
||||
if self.spheroid:
|
||||
# DistanceSpheroid is more accurate and resource intensive than DistanceSphere
|
||||
# DistanceSpheroid is more accurate and resource intensive than
|
||||
# DistanceSphere.
|
||||
function = connection.ops.spatial_function_name("DistanceSpheroid")
|
||||
# Replace boolean param by the real spheroid of the base field
|
||||
clone.source_expressions.append(
|
||||
|
@ -202,7 +202,8 @@ class BBContainsLookup(GISLookup):
|
||||
@BaseSpatialField.register_lookup
|
||||
class BBOverlapsLookup(GISLookup):
|
||||
"""
|
||||
The 'bboverlaps' operator returns true if A's bounding box overlaps B's bounding box.
|
||||
The 'bboverlaps' operator returns true if A's bounding box overlaps B's
|
||||
bounding box.
|
||||
"""
|
||||
|
||||
lookup_name = "bboverlaps"
|
||||
@ -307,7 +308,8 @@ class DistanceLookupBase(GISLookup):
|
||||
)
|
||||
elif len(self.rhs_params) == 3 and self.rhs_params[2] != "spheroid":
|
||||
raise ValueError(
|
||||
"For 4-element tuples the last argument must be the 'spheroid' directive."
|
||||
"For 4-element tuples the last argument must be the 'spheroid' "
|
||||
"directive."
|
||||
)
|
||||
|
||||
# Check if the second parameter is a band index.
|
||||
|
@ -28,7 +28,7 @@
|
||||
>>> print(mpnt.proj)
|
||||
+proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs
|
||||
>>> print(mpnt)
|
||||
MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641)
|
||||
MULTIPOINT (-89.99993037860248 29.99979788655764,-89.99993037860248 29.99979788655764)
|
||||
|
||||
The OGRGeomType class is to make it easy to specify an OGR geometry type:
|
||||
>>> from django.contrib.gis.gdal import OGRGeomType
|
||||
|
@ -19,7 +19,10 @@ from django.utils.encoding import force_bytes, force_str
|
||||
#
|
||||
# The OGR_L_* routines are relevant here.
|
||||
class Layer(GDALBase):
|
||||
"A class that wraps an OGR Layer, needs to be instantiated from a DataSource object."
|
||||
"""
|
||||
A class that wraps an OGR Layer, needs to be instantiated from a DataSource
|
||||
object.
|
||||
"""
|
||||
|
||||
def __init__(self, layer_ptr, ds):
|
||||
"""
|
||||
@ -192,7 +195,8 @@ class Layer(GDALBase):
|
||||
capi.set_spatial_filter(self.ptr, None)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Spatial filter must be either an OGRGeometry instance, a 4-tuple, or None."
|
||||
"Spatial filter must be either an OGRGeometry instance, a 4-tuple, or "
|
||||
"None."
|
||||
)
|
||||
|
||||
spatial_filter = property(_get_spatial_filter, _set_spatial_filter)
|
||||
|
@ -131,7 +131,8 @@ class SpatialReference(GDALBase):
|
||||
4326
|
||||
>>> print(srs['TOWGS84', 4]) # the fourth value in this wkt
|
||||
0
|
||||
>>> print(srs['UNIT|AUTHORITY']) # For the units authority, have to use the pipe symbole.
|
||||
>>> # For the units authority, have to use the pipe symbole.
|
||||
>>> print(srs['UNIT|AUTHORITY'])
|
||||
EPSG
|
||||
>>> print(srs['UNIT|AUTHORITY', 1]) # The authority value for the units
|
||||
9122
|
||||
|
@ -32,7 +32,8 @@ class Polygon(GEOSGeometry):
|
||||
ext_ring, *init_holes = args
|
||||
n_holes = len(init_holes)
|
||||
|
||||
# If initialized as Polygon(shell, (LinearRing, LinearRing)) [for backward-compatibility]
|
||||
# If initialized as Polygon(shell, (LinearRing, LinearRing))
|
||||
# [for backward-compatibility]
|
||||
if n_holes == 1 and isinstance(init_holes[0], (tuple, list)):
|
||||
if not init_holes[0]:
|
||||
init_holes = ()
|
||||
@ -101,7 +102,8 @@ class Polygon(GEOSGeometry):
|
||||
self,
|
||||
param,
|
||||
msg=(
|
||||
"Parameter must be a sequence of LinearRings or objects that can initialize to LinearRings"
|
||||
"Parameter must be a sequence of LinearRings or objects that can "
|
||||
"initialize to LinearRings"
|
||||
),
|
||||
):
|
||||
"Try to construct a ring from the given parameter."
|
||||
|
@ -34,8 +34,8 @@ class ListOptionAction(argparse.Action):
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = (
|
||||
"Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n"
|
||||
"a GeoDjango model with the given model name. For example:\n"
|
||||
"Inspects the given OGR-compatible data source (e.g., a shapefile) and "
|
||||
"outputs\na GeoDjango model with the given model name. For example:\n"
|
||||
" ./manage.py ogrinspect zipcode.shp Zipcode"
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,8 @@ class Serializer(JSONSerializer):
|
||||
self._init_options()
|
||||
self._cts = {} # cache of CoordTransform's
|
||||
self.stream.write(
|
||||
'{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:%d"}},'
|
||||
'{"type": "FeatureCollection", '
|
||||
'"crs": {"type": "name", "properties": {"name": "EPSG:%d"}},'
|
||||
' "features": [' % self.srid
|
||||
)
|
||||
|
||||
@ -53,7 +54,8 @@ class Serializer(JSONSerializer):
|
||||
data["properties"]["pk"] = obj._meta.pk.value_to_string(obj)
|
||||
if self._geometry:
|
||||
if self._geometry.srid != self.srid:
|
||||
# If needed, transform the geometry in the srid of the global geojson srid
|
||||
# If needed, transform the geometry in the srid of the global
|
||||
# geojson srid.
|
||||
if self._geometry.srid not in self._cts:
|
||||
srs = SpatialReference(self.srid)
|
||||
self._cts[self._geometry.srid] = CoordTransform(
|
||||
|
@ -42,7 +42,8 @@ class KMLSitemap(Sitemap):
|
||||
elif isinstance(source, (list, tuple)):
|
||||
if len(source) != 3:
|
||||
raise ValueError(
|
||||
"Must specify a 3-tuple of (app_label, module_name, field_name)."
|
||||
"Must specify a 3-tuple of (app_label, module_name, "
|
||||
"field_name)."
|
||||
)
|
||||
kml_sources.append(source)
|
||||
else:
|
||||
|
@ -233,7 +233,8 @@ class LayerMapping:
|
||||
if isinstance(model_field, GeometryField):
|
||||
if self.geom_field:
|
||||
raise LayerMapError(
|
||||
"LayerMapping does not support more than one GeometryField per model."
|
||||
"LayerMapping does not support more than one GeometryField per "
|
||||
"model."
|
||||
)
|
||||
|
||||
# Getting the coordinate dimension of the geometry field.
|
||||
@ -695,7 +696,8 @@ class LayerMapping:
|
||||
# Incremental saving is requested at the given interval (step)
|
||||
if default_range:
|
||||
raise LayerMapError(
|
||||
"The `step` keyword may not be used in conjunction with the `fid_range` keyword."
|
||||
"The `step` keyword may not be used in conjunction with the "
|
||||
"`fid_range` keyword."
|
||||
)
|
||||
beg, num_feat, num_saved = (0, 0, 0)
|
||||
indices = range(step, nfeat, step)
|
||||
|
@ -209,7 +209,9 @@ def _ogrinspect(
|
||||
# may also be mapped to `DecimalField` if specified in the
|
||||
# `decimal` keyword.
|
||||
if field_name.lower() in decimal_fields:
|
||||
yield " %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)" % (
|
||||
yield (
|
||||
" %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)"
|
||||
) % (
|
||||
mfield,
|
||||
width,
|
||||
precision,
|
||||
|
@ -256,7 +256,8 @@ class NaturalTimeFormatter:
|
||||
),
|
||||
}
|
||||
future_substrings = {
|
||||
# Translators: 'naturaltime-future' strings will be included in '%(delta)s from now'
|
||||
# Translators: 'naturaltime-future' strings will be included in
|
||||
# '%(delta)s from now'.
|
||||
"year": npgettext_lazy(
|
||||
"naturaltime-future", "%(num)d year", "%(num)d years", "num"
|
||||
),
|
||||
|
@ -18,7 +18,10 @@ class ExclusionConstraintExpression(IndexExpression):
|
||||
|
||||
|
||||
class ExclusionConstraint(BaseConstraint):
|
||||
template = "CONSTRAINT %(name)s EXCLUDE USING %(index_type)s (%(expressions)s)%(include)s%(where)s%(deferrable)s"
|
||||
template = (
|
||||
"CONSTRAINT %(name)s EXCLUDE USING %(index_type)s "
|
||||
"(%(expressions)s)%(include)s%(where)s%(deferrable)s"
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -54,7 +54,8 @@ class RangeField(models.Field):
|
||||
raise TypeError(
|
||||
f"Cannot use 'default_bounds' with {self.__class__.__name__}."
|
||||
)
|
||||
# Initializing base_field here ensures that its model matches the model for self.
|
||||
# Initializing base_field here ensures that its model matches the model
|
||||
# for self.
|
||||
if hasattr(self, "base_field"):
|
||||
self.base_field = self.base_field()
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -185,9 +185,8 @@ class CollationOperation(Operation):
|
||||
)
|
||||
|
||||
def create_collation(self, schema_editor):
|
||||
if (
|
||||
self.deterministic is False
|
||||
and not schema_editor.connection.features.supports_non_deterministic_collations
|
||||
if self.deterministic is False and not (
|
||||
schema_editor.connection.features.supports_non_deterministic_collations
|
||||
):
|
||||
raise NotSupportedError(
|
||||
"Non-deterministic collations require PostgreSQL 12+."
|
||||
|
@ -12,16 +12,20 @@ from django.utils.translation import ngettext_lazy
|
||||
|
||||
class ArrayMaxLengthValidator(MaxLengthValidator):
|
||||
message = ngettext_lazy(
|
||||
"List contains %(show_value)d item, it should contain no more than %(limit_value)d.",
|
||||
"List contains %(show_value)d items, it should contain no more than %(limit_value)d.",
|
||||
"List contains %(show_value)d item, it should contain no more than "
|
||||
"%(limit_value)d.",
|
||||
"List contains %(show_value)d items, it should contain no more than "
|
||||
"%(limit_value)d.",
|
||||
"limit_value",
|
||||
)
|
||||
|
||||
|
||||
class ArrayMinLengthValidator(MinLengthValidator):
|
||||
message = ngettext_lazy(
|
||||
"List contains %(show_value)d item, it should contain no fewer than %(limit_value)d.",
|
||||
"List contains %(show_value)d items, it should contain no fewer than %(limit_value)d.",
|
||||
"List contains %(show_value)d item, it should contain no fewer than "
|
||||
"%(limit_value)d.",
|
||||
"List contains %(show_value)d items, it should contain no fewer than "
|
||||
"%(limit_value)d.",
|
||||
"limit_value",
|
||||
)
|
||||
|
||||
|
@ -32,7 +32,8 @@ class Migration(migrations.Migration):
|
||||
"old_path",
|
||||
models.CharField(
|
||||
help_text=(
|
||||
"This should be an absolute path, excluding the domain name. Example: “/events/search/”."
|
||||
"This should be an absolute path, excluding the domain "
|
||||
"name. Example: “/events/search/”."
|
||||
),
|
||||
max_length=200,
|
||||
verbose_name="redirect from",
|
||||
@ -42,7 +43,10 @@ class Migration(migrations.Migration):
|
||||
(
|
||||
"new_path",
|
||||
models.CharField(
|
||||
help_text="This can be either an absolute path (as above) or a full URL starting with “http://”.",
|
||||
help_text=(
|
||||
"This can be either an absolute path (as above) or a full "
|
||||
"URL starting with “http://”."
|
||||
),
|
||||
max_length=200,
|
||||
verbose_name="redirect to",
|
||||
blank=True,
|
||||
|
@ -10,7 +10,8 @@ class Redirect(models.Model):
|
||||
max_length=200,
|
||||
db_index=True,
|
||||
help_text=_(
|
||||
"This should be an absolute path, excluding the domain name. Example: “/events/search/”."
|
||||
"This should be an absolute path, excluding the domain name. Example: "
|
||||
"“/events/search/”."
|
||||
),
|
||||
)
|
||||
new_path = models.CharField(
|
||||
|
@ -48,7 +48,8 @@ def _get_sitemap_full_url(sitemap_url, sitemap_uses_https=True):
|
||||
|
||||
if sitemap_url is None:
|
||||
raise SitemapNotFound(
|
||||
"You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected."
|
||||
"You didn't provide a sitemap_url, and the sitemap URL couldn't be "
|
||||
"auto-detected."
|
||||
)
|
||||
|
||||
Site = django_apps.get_model("sites.Site")
|
||||
|
@ -20,7 +20,10 @@ class SitemapIndexItem:
|
||||
|
||||
# RemovedInDjango50Warning
|
||||
def __str__(self):
|
||||
msg = "Calling `__str__` on SitemapIndexItem is deprecated, use the `location` attribute instead."
|
||||
msg = (
|
||||
"Calling `__str__` on SitemapIndexItem is deprecated, use the `location` "
|
||||
"attribute instead."
|
||||
)
|
||||
warnings.warn(msg, RemovedInDjango50Warning, stacklevel=2)
|
||||
return self.location
|
||||
|
||||
|
@ -35,7 +35,8 @@ class CurrentSiteManager(models.Manager):
|
||||
if not field.many_to_many and not isinstance(field, (models.ForeignKey)):
|
||||
return [
|
||||
checks.Error(
|
||||
"CurrentSiteManager cannot use '%s.%s' as it is not a foreign key or a many-to-many field."
|
||||
"CurrentSiteManager cannot use '%s.%s' as it is not a foreign key "
|
||||
"or a many-to-many field."
|
||||
% (self.model._meta.object_name, field_name),
|
||||
obj=self,
|
||||
id="sites.E002",
|
||||
|
@ -83,7 +83,10 @@ class Command(BaseCommand):
|
||||
"--no-default-ignore",
|
||||
action="store_false",
|
||||
dest="use_default_ignore_patterns",
|
||||
help="Don't ignore the common private glob-style patterns (defaults to 'CVS', '.*' and '*~').",
|
||||
help=(
|
||||
"Don't ignore the common private glob-style patterns (defaults to "
|
||||
"'CVS', '.*' and '*~')."
|
||||
),
|
||||
)
|
||||
|
||||
def set_options(self, **options):
|
||||
@ -169,7 +172,8 @@ class Command(BaseCommand):
|
||||
message = ["\n"]
|
||||
if self.dry_run:
|
||||
message.append(
|
||||
"You have activated the --dry-run option so no files will be modified.\n\n"
|
||||
"You have activated the --dry-run option so no files will be "
|
||||
"modified.\n\n"
|
||||
)
|
||||
|
||||
message.append(
|
||||
|
3
django/core/cache/backends/memcached.py
vendored
3
django/core/cache/backends/memcached.py
vendored
@ -77,7 +77,8 @@ class BaseMemcachedCache(BaseCache):
|
||||
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
|
||||
key = self.make_and_validate_key(key, version=version)
|
||||
if not self._cache.set(key, value, self.get_backend_timeout(timeout)):
|
||||
# make sure the key doesn't keep its old value in case of failure to set (memcached's 1MB limit)
|
||||
# Make sure the key doesn't keep its old value in case of failure
|
||||
# to set (memcached's 1MB limit).
|
||||
self._cache.delete(key)
|
||||
|
||||
def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None):
|
||||
|
@ -60,8 +60,8 @@ def check_csrf_failure_view(app_configs, **kwargs):
|
||||
inspect.signature(view).bind(None, reason=None)
|
||||
except TypeError:
|
||||
msg = (
|
||||
"The CSRF failure view '%s' does not take the correct number of arguments."
|
||||
% settings.CSRF_FAILURE_VIEW
|
||||
"The CSRF failure view '%s' does not take the correct number of "
|
||||
"arguments." % settings.CSRF_FAILURE_VIEW
|
||||
)
|
||||
errors.append(Error(msg, id="security.E101"))
|
||||
return errors
|
||||
|
@ -6,7 +6,7 @@ Cookbook [1] (licensed under the Python Software License) and a ctypes port by
|
||||
Anatoly Techtonik for Roundup [2] (license [3]).
|
||||
|
||||
[1] https://code.activestate.com/recipes/65203/
|
||||
[2] https://sourceforge.net/p/roundup/code/ci/default/tree/roundup/backends/portalocker.py
|
||||
[2] https://sourceforge.net/p/roundup/code/ci/default/tree/roundup/backends/portalocker.py # NOQA
|
||||
[3] https://sourceforge.net/p/roundup/code/ci/default/tree/COPYING.txt
|
||||
|
||||
Example Usage::
|
||||
|
@ -104,7 +104,8 @@ class Storage:
|
||||
truncation = len(name) - max_length
|
||||
if truncation > 0:
|
||||
file_root = file_root[:-truncation]
|
||||
# Entire file_root was truncated in attempt to find an available filename.
|
||||
# Entire file_root was truncated in attempt to find an
|
||||
# available filename.
|
||||
if not file_root:
|
||||
raise SuspiciousFileOperation(
|
||||
'Storage can not find an available filename for "%s". '
|
||||
|
@ -242,7 +242,10 @@ def load_handler(path, *args, **kwargs):
|
||||
E.g.::
|
||||
>>> from django.http import HttpRequest
|
||||
>>> request = HttpRequest()
|
||||
>>> load_handler('django.core.files.uploadhandler.TemporaryFileUploadHandler', request)
|
||||
>>> load_handler(
|
||||
... 'django.core.files.uploadhandler.TemporaryFileUploadHandler',
|
||||
... request,
|
||||
... )
|
||||
<TemporaryFileUploadHandler object at 0x...>
|
||||
"""
|
||||
return import_string(path)(*args, **kwargs)
|
||||
|
@ -208,7 +208,8 @@ class BaseHandler:
|
||||
if hasattr(response, "render") and callable(response.render):
|
||||
for middleware_method in self._template_response_middleware:
|
||||
response = middleware_method(request, response)
|
||||
# Complain if the template response middleware returned None (a common error).
|
||||
# Complain if the template response middleware returned None
|
||||
# (a common error).
|
||||
self.check_response(
|
||||
response,
|
||||
middleware_method,
|
||||
|
@ -308,7 +308,10 @@ class BaseCommand:
|
||||
default=1,
|
||||
type=int,
|
||||
choices=[0, 1, 2, 3],
|
||||
help="Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output",
|
||||
help=(
|
||||
"Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, "
|
||||
"3=very verbose output"
|
||||
),
|
||||
)
|
||||
self.add_base_argument(
|
||||
parser,
|
||||
@ -322,7 +325,10 @@ class BaseCommand:
|
||||
self.add_base_argument(
|
||||
parser,
|
||||
"--pythonpath",
|
||||
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".',
|
||||
help=(
|
||||
"A directory to add to the Python path, e.g. "
|
||||
'"/home/djangoprojects/myproject".'
|
||||
),
|
||||
)
|
||||
self.add_base_argument(
|
||||
parser,
|
||||
|
@ -173,8 +173,8 @@ class Command(BaseCommand):
|
||||
# Check writability on first location
|
||||
if i == 0 and not is_writable(mo_path):
|
||||
self.stderr.write(
|
||||
"The po files under %s are in a seemingly not writable location. "
|
||||
"mo files will not be updated/created." % dirpath
|
||||
"The po files under %s are in a seemingly not writable "
|
||||
"location. mo files will not be updated/created." % dirpath
|
||||
)
|
||||
self.has_errors = True
|
||||
return
|
||||
|
@ -22,7 +22,10 @@ class Command(BaseCommand):
|
||||
"args",
|
||||
metavar="table_name",
|
||||
nargs="*",
|
||||
help="Optional table names. Otherwise, settings.CACHES is used to find cache tables.",
|
||||
help=(
|
||||
"Optional table names. Otherwise, settings.CACHES is used to find "
|
||||
"cache tables."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
|
@ -16,7 +16,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database onto which to open a shell. Defaults to the "default" database.',
|
||||
help=(
|
||||
"Nominates a database onto which to open a shell. Defaults to the "
|
||||
'"default" database.'
|
||||
),
|
||||
)
|
||||
parameters = parser.add_argument_group("parameters", prefix_chars="--")
|
||||
parameters.add_argument("parameters", nargs="*")
|
||||
|
@ -25,8 +25,8 @@ class Command(BaseCommand):
|
||||
"--default",
|
||||
metavar="MODULE",
|
||||
help=(
|
||||
"The settings module to compare the current settings against. Leave empty to "
|
||||
"compare against Django's default settings."
|
||||
"The settings module to compare the current settings against. Leave "
|
||||
"empty to compare against Django's default settings."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -38,7 +38,10 @@ class Command(BaseCommand):
|
||||
"args",
|
||||
metavar="app_label[.ModelName]",
|
||||
nargs="*",
|
||||
help="Restricts dumped data to the specified app_label or app_label.ModelName.",
|
||||
help=(
|
||||
"Restricts dumped data to the specified app_label or "
|
||||
"app_label.ModelName."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
@ -81,8 +84,11 @@ class Command(BaseCommand):
|
||||
"--all",
|
||||
action="store_true",
|
||||
dest="use_base_manager",
|
||||
help="Use Django's base manager to dump all models stored in the database, "
|
||||
"including those that would otherwise be filtered or modified by a custom manager.",
|
||||
help=(
|
||||
"Use Django's base manager to dump all models stored in the database, "
|
||||
"including those that would otherwise be filtered or modified by a "
|
||||
"custom manager."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pks",
|
||||
|
@ -82,7 +82,8 @@ Are you sure you want to do this?
|
||||
% (connection.settings_dict["NAME"],)
|
||||
) from exc
|
||||
|
||||
# Empty sql_list may signify an empty database and post_migrate would then crash
|
||||
# Empty sql_list may signify an empty database and post_migrate
|
||||
# would then crash.
|
||||
if sql_list and not inhibit_post_migrate:
|
||||
# Emit the post migrate signal. This allows individual applications to
|
||||
# respond as if the database had been migrated from scratch.
|
||||
|
@ -7,7 +7,10 @@ from django.db.models.constants import LOOKUP_SEP
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Introspects the database tables in the given database and outputs a Django model module."
|
||||
help = (
|
||||
"Introspects the database tables in the given database and outputs a Django "
|
||||
"model module."
|
||||
)
|
||||
requires_system_checks = []
|
||||
stealth_options = ("table_name_filter",)
|
||||
db_module = "django.db"
|
||||
@ -22,7 +25,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to introspect. Defaults to using the "default" database.',
|
||||
help=(
|
||||
'Nominates a database to introspect. Defaults to using the "default" '
|
||||
"database."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--include-partitions",
|
||||
@ -41,7 +47,8 @@ class Command(BaseCommand):
|
||||
self.stdout.write(line)
|
||||
except NotImplementedError:
|
||||
raise CommandError(
|
||||
"Database inspection isn't supported for the currently selected database backend."
|
||||
"Database inspection isn't supported for the currently selected "
|
||||
"database backend."
|
||||
)
|
||||
|
||||
def handle_inspection(self, options):
|
||||
@ -57,12 +64,18 @@ class Command(BaseCommand):
|
||||
yield "# You'll have to do the following manually to clean this up:"
|
||||
yield "# * Rearrange models' order"
|
||||
yield "# * Make sure each model has one field with primary_key=True"
|
||||
yield "# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior"
|
||||
yield (
|
||||
"# * Make sure each ForeignKey and OneToOneField has `on_delete` set "
|
||||
"to the desired behavior"
|
||||
)
|
||||
yield (
|
||||
"# * Remove `managed = False` lines if you wish to allow "
|
||||
"Django to create, modify, and delete the table"
|
||||
)
|
||||
yield "# Feel free to rename the models, but don't rename db_table values or field names."
|
||||
yield (
|
||||
"# Feel free to rename the models, but don't rename db_table values or "
|
||||
"field names."
|
||||
)
|
||||
yield "from %s import models" % self.db_module
|
||||
known_models = []
|
||||
table_info = connection.introspection.get_table_list(cursor)
|
||||
|
@ -55,7 +55,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a specific database to load fixtures into. Defaults to the "default" database.',
|
||||
help=(
|
||||
"Nominates a specific database to load fixtures into. Defaults to the "
|
||||
'"default" database.'
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--app",
|
||||
@ -75,7 +78,10 @@ class Command(BaseCommand):
|
||||
"--exclude",
|
||||
action="append",
|
||||
default=[],
|
||||
help="An app_label or app_label.ModelName to exclude. Can be used multiple times.",
|
||||
help=(
|
||||
"An app_label or app_label.ModelName to exclude. Can be used multiple "
|
||||
"times."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
@ -105,7 +111,8 @@ class Command(BaseCommand):
|
||||
@cached_property
|
||||
def compression_formats(self):
|
||||
"""A dict mapping format names to (open function, mode arg) tuples."""
|
||||
# Forcing binary mode may be revisited after dropping Python 2 support (see #22399)
|
||||
# Forcing binary mode may be revisited after dropping Python 2 support
|
||||
# (see #22399).
|
||||
compression_formats = {
|
||||
None: (open, "rb"),
|
||||
"gz": (gzip.GzipFile, "rb"),
|
||||
|
@ -203,11 +203,11 @@ def write_pot_file(potfile, msgs):
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = (
|
||||
"Runs over the entire source tree of the current directory and "
|
||||
"pulls out all strings marked for translation. It creates (or updates) a message "
|
||||
"file in the conf/locale (in the django tree) or locale (for projects and "
|
||||
"applications) directory.\n\nYou must run this command with one of either the "
|
||||
"--locale, --exclude, or --all options."
|
||||
"Runs over the entire source tree of the current directory and pulls out all "
|
||||
"strings marked for translation. It creates (or updates) a message file in the "
|
||||
"conf/locale (in the django tree) or locale (for projects and applications) "
|
||||
"directory.\n\nYou must run this command with one of either the --locale, "
|
||||
"--exclude, or --all options."
|
||||
)
|
||||
|
||||
translatable_file_class = TranslatableFile
|
||||
@ -226,8 +226,10 @@ class Command(BaseCommand):
|
||||
"-l",
|
||||
default=[],
|
||||
action="append",
|
||||
help="Creates or updates the message files for the given locale(s) (e.g. pt_BR). "
|
||||
"Can be used multiple times.",
|
||||
help=(
|
||||
"Creates or updates the message files for the given locale(s) (e.g. "
|
||||
"pt_BR). Can be used multiple times."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--exclude",
|
||||
@ -278,7 +280,10 @@ class Command(BaseCommand):
|
||||
"--no-default-ignore",
|
||||
action="store_false",
|
||||
dest="use_default_ignore_patterns",
|
||||
help="Don't ignore the common glob-style patterns 'CVS', '.*', '*~' and '*.pyc'.",
|
||||
help=(
|
||||
"Don't ignore the common glob-style patterns 'CVS', '.*', '*~' and "
|
||||
"'*.pyc'."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-wrap",
|
||||
|
@ -147,7 +147,8 @@ class Command(BaseCommand):
|
||||
# hard if there are any and they don't want to merge
|
||||
conflicts = loader.detect_conflicts()
|
||||
|
||||
# If app_labels is specified, filter out conflicting migrations for unspecified apps
|
||||
# If app_labels is specified, filter out conflicting migrations for
|
||||
# unspecified apps.
|
||||
if app_labels:
|
||||
conflicts = {
|
||||
app_label: conflict
|
||||
|
@ -47,7 +47,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to synchronize. Defaults to the "default" database.',
|
||||
help=(
|
||||
'Nominates a database to synchronize. Defaults to the "default" '
|
||||
"database."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fake",
|
||||
@ -57,9 +60,12 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--fake-initial",
|
||||
action="store_true",
|
||||
help="Detect if tables already exist and fake-apply initial migrations if so. Make sure "
|
||||
"that the current database schema matches your initial migration before using this "
|
||||
"flag. Django will only check for an existing table name.",
|
||||
help=(
|
||||
"Detect if tables already exist and fake-apply initial migrations if "
|
||||
"so. Make sure that the current database schema matches your initial "
|
||||
"migration before using this flag. Django will only check for an "
|
||||
"existing table name."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--plan",
|
||||
@ -313,7 +319,8 @@ class Command(BaseCommand):
|
||||
if not plan:
|
||||
if self.verbosity >= 1:
|
||||
self.stdout.write(" No migrations to apply.")
|
||||
# If there's changes that aren't in migrations yet, tell them how to fix it.
|
||||
# If there's changes that aren't in migrations yet, tell them
|
||||
# how to fix it.
|
||||
autodetector = MigrationAutodetector(
|
||||
executor.loader.project_state(),
|
||||
ProjectState.from_apps(apps),
|
||||
|
@ -7,7 +7,10 @@ from django.utils import timezone
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Sends a test email to the email addresses specified as arguments."
|
||||
missing_args_message = "You must specify some email recipients, or pass the --managers or --admin options."
|
||||
missing_args_message = (
|
||||
"You must specify some email recipients, or pass the --managers or --admin "
|
||||
"options."
|
||||
)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
|
@ -21,18 +21,27 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--no-startup",
|
||||
action="store_true",
|
||||
help="When using plain Python, ignore the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.",
|
||||
help=(
|
||||
"When using plain Python, ignore the PYTHONSTARTUP environment "
|
||||
"variable and ~/.pythonrc.py script."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--interface",
|
||||
choices=self.shells,
|
||||
help='Specify an interactive interpreter interface. Available options: "ipython", "bpython", and "python"',
|
||||
help=(
|
||||
"Specify an interactive interpreter interface. Available options: "
|
||||
'"ipython", "bpython", and "python"'
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--command",
|
||||
help="Instead of opening an interactive shell, run a command as Django and exit.",
|
||||
help=(
|
||||
"Instead of opening an interactive shell, run a command as Django and "
|
||||
"exit."
|
||||
),
|
||||
)
|
||||
|
||||
def ipython(self, options):
|
||||
|
@ -45,9 +45,9 @@ class Command(BaseCommand):
|
||||
dest="format",
|
||||
const="plan",
|
||||
help=(
|
||||
"Shows all migrations in the order they will be applied. "
|
||||
"With a verbosity level of 2 or above all direct migration dependencies "
|
||||
"and reverse dependencies (run_before) will be included."
|
||||
"Shows all migrations in the order they will be applied. With a "
|
||||
"verbosity level of 2 or above all direct migration dependencies and "
|
||||
"reverse dependencies (run_before) will be included."
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -16,7 +16,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to print the SQL for. Defaults to the "default" database.',
|
||||
help=(
|
||||
'Nominates a database to print the SQL for. Defaults to the "default" '
|
||||
"database."
|
||||
),
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
|
@ -19,7 +19,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to create SQL for. Defaults to the "default" database.',
|
||||
help=(
|
||||
'Nominates a database to create SQL for. Defaults to the "default" '
|
||||
"database."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--backwards",
|
||||
@ -55,13 +58,13 @@ class Command(BaseCommand):
|
||||
migration = loader.get_migration_by_prefix(app_label, migration_name)
|
||||
except AmbiguityError:
|
||||
raise CommandError(
|
||||
"More than one migration matches '%s' in app '%s'. Please be more specific."
|
||||
% (migration_name, app_label)
|
||||
"More than one migration matches '%s' in app '%s'. Please be more "
|
||||
"specific." % (migration_name, app_label)
|
||||
)
|
||||
except KeyError:
|
||||
raise CommandError(
|
||||
"Cannot find a migration matching '%s' from app '%s'. Is it in INSTALLED_APPS?"
|
||||
% (migration_name, app_label)
|
||||
"Cannot find a migration matching '%s' from app '%s'. Is it in "
|
||||
"INSTALLED_APPS?" % (migration_name, app_label)
|
||||
)
|
||||
target = (app_label, migration.name)
|
||||
|
||||
|
@ -14,7 +14,10 @@ class Command(AppCommand):
|
||||
parser.add_argument(
|
||||
"--database",
|
||||
default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to print the SQL for. Defaults to the "default" database.',
|
||||
help=(
|
||||
'Nominates a database to print the SQL for. Defaults to the "default" '
|
||||
"database."
|
||||
),
|
||||
)
|
||||
|
||||
def handle_app_config(self, app_config, **options):
|
||||
|
@ -12,7 +12,10 @@ from django.utils.version import get_docs_version
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Squashes an existing set of migrations (from first until specified) into a single new one."
|
||||
help = (
|
||||
"Squashes an existing set of migrations (from first until specified) into a "
|
||||
"single new one."
|
||||
)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
@ -22,7 +25,10 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
"start_migration_name",
|
||||
nargs="?",
|
||||
help="Migrations will be squashed starting from and including this migration.",
|
||||
help=(
|
||||
"Migrations will be squashed starting from and including this "
|
||||
"migration."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"migration_name",
|
||||
@ -66,7 +72,8 @@ class Command(BaseCommand):
|
||||
apps.get_app_config(app_label)
|
||||
except LookupError as err:
|
||||
raise CommandError(str(err))
|
||||
# Load the current graph state, check the app and migration they asked for exists
|
||||
# Load the current graph state, check the app and migration they asked
|
||||
# for exists.
|
||||
loader = MigrationLoader(connections[DEFAULT_DB_ALIAS])
|
||||
if app_label not in loader.migrated_apps:
|
||||
raise CommandError(
|
||||
@ -135,10 +142,9 @@ class Command(BaseCommand):
|
||||
for smigration in migrations_to_squash:
|
||||
if smigration.replaces:
|
||||
raise CommandError(
|
||||
"You cannot squash squashed migrations! Please transition "
|
||||
"it to a normal migration first: "
|
||||
"https://docs.djangoproject.com/en/%s/topics/migrations/#squashing-migrations"
|
||||
% get_docs_version()
|
||||
"You cannot squash squashed migrations! Please transition it to a "
|
||||
"normal migration first: https://docs.djangoproject.com/en/%s/"
|
||||
"topics/migrations/#squashing-migrations" % get_docs_version()
|
||||
)
|
||||
operations.extend(smigration.operations)
|
||||
for dependency in smigration.dependencies:
|
||||
@ -223,15 +229,18 @@ class Command(BaseCommand):
|
||||
+ "\n"
|
||||
" You should commit this migration but leave the old ones in place;\n"
|
||||
" the new migration will be used for new installs. Once you are sure\n"
|
||||
" all instances of the codebase have applied the migrations you squashed,\n"
|
||||
" all instances of the codebase have applied the migrations you "
|
||||
"squashed,\n"
|
||||
" you can delete them."
|
||||
)
|
||||
if writer.needs_manual_porting:
|
||||
self.stdout.write(
|
||||
self.style.MIGRATE_HEADING("Manual porting required") + "\n"
|
||||
" Your migrations contained functions that must be manually copied over,\n"
|
||||
" Your migrations contained functions that must be manually "
|
||||
"copied over,\n"
|
||||
" as we could not safely copy their implementation.\n"
|
||||
" See the comment at the top of the squashed migration for details."
|
||||
" See the comment at the top of the squashed migration for "
|
||||
"details."
|
||||
)
|
||||
|
||||
def find_migration(self, loader, app_label, name):
|
||||
|
@ -28,7 +28,10 @@ class Command(BaseCommand):
|
||||
"args",
|
||||
metavar="test_label",
|
||||
nargs="*",
|
||||
help="Module paths to test; can be modulename, modulename.TestCase or modulename.TestCase.test_method",
|
||||
help=(
|
||||
"Module paths to test; can be modulename, modulename.TestCase or "
|
||||
"modulename.TestCase.test_method"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--noinput",
|
||||
|
@ -174,8 +174,11 @@ class EmailValidator:
|
||||
message = _("Enter a valid email address.")
|
||||
code = "invalid"
|
||||
user_regex = _lazy_re_compile(
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" # dot-atom
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)', # quoted-string
|
||||
# dot-atom
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z"
|
||||
# quoted-string
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])'
|
||||
r'*"\Z)',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
domain_regex = _lazy_re_compile(
|
||||
@ -257,7 +260,8 @@ slug_unicode_re = _lazy_re_compile(r"^[-\w]+\Z")
|
||||
validate_unicode_slug = RegexValidator(
|
||||
slug_unicode_re,
|
||||
_(
|
||||
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens."
|
||||
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or "
|
||||
"hyphens."
|
||||
),
|
||||
"invalid",
|
||||
)
|
||||
@ -400,8 +404,10 @@ class MinValueValidator(BaseValidator):
|
||||
@deconstructible
|
||||
class MinLengthValidator(BaseValidator):
|
||||
message = ngettext_lazy(
|
||||
"Ensure this value has at least %(limit_value)d character (it has %(show_value)d).",
|
||||
"Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).",
|
||||
"Ensure this value has at least %(limit_value)d character (it has "
|
||||
"%(show_value)d).",
|
||||
"Ensure this value has at least %(limit_value)d characters (it has "
|
||||
"%(show_value)d).",
|
||||
"limit_value",
|
||||
)
|
||||
code = "min_length"
|
||||
@ -416,8 +422,10 @@ class MinLengthValidator(BaseValidator):
|
||||
@deconstructible
|
||||
class MaxLengthValidator(BaseValidator):
|
||||
message = ngettext_lazy(
|
||||
"Ensure this value has at most %(limit_value)d character (it has %(show_value)d).",
|
||||
"Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).",
|
||||
"Ensure this value has at most %(limit_value)d character (it has "
|
||||
"%(show_value)d).",
|
||||
"Ensure this value has at most %(limit_value)d characters (it has "
|
||||
"%(show_value)d).",
|
||||
"limit_value",
|
||||
)
|
||||
code = "max_length"
|
||||
@ -449,8 +457,10 @@ class DecimalValidator:
|
||||
"max",
|
||||
),
|
||||
"max_whole_digits": ngettext_lazy(
|
||||
"Ensure that there are no more than %(max)s digit before the decimal point.",
|
||||
"Ensure that there are no more than %(max)s digits before the decimal point.",
|
||||
"Ensure that there are no more than %(max)s digit before the decimal "
|
||||
"point.",
|
||||
"Ensure that there are no more than %(max)s digits before the decimal "
|
||||
"point.",
|
||||
"max",
|
||||
),
|
||||
}
|
||||
|
@ -190,19 +190,22 @@ class BaseDatabaseWrapper:
|
||||
def get_connection_params(self):
|
||||
"""Return a dict of parameters suitable for get_new_connection."""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseWrapper may require a get_connection_params() method"
|
||||
"subclasses of BaseDatabaseWrapper may require a get_connection_params() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def get_new_connection(self, conn_params):
|
||||
"""Open a connection to the database."""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseWrapper may require a get_new_connection() method"
|
||||
"subclasses of BaseDatabaseWrapper may require a get_new_connection() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def init_connection_state(self):
|
||||
"""Initialize the database connection settings."""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseWrapper may require an init_connection_state() method"
|
||||
"subclasses of BaseDatabaseWrapper may require an init_connection_state() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def create_cursor(self, name=None):
|
||||
|
@ -63,7 +63,8 @@ class BaseDatabaseIntrospection:
|
||||
views that exist in the database.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_table_list() method"
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_table_list() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def get_table_description(self, cursor, table_name):
|
||||
@ -158,7 +159,8 @@ class BaseDatabaseIntrospection:
|
||||
'name' key can be added if the backend supports named sequences.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_sequences() method"
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_sequences() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def get_relations(self, cursor, table_name):
|
||||
@ -200,5 +202,6 @@ class BaseDatabaseIntrospection:
|
||||
if they don't name constraints of a certain type (e.g. SQLite)
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_constraints() method"
|
||||
"subclasses of BaseDatabaseIntrospection may require a get_constraints() "
|
||||
"method"
|
||||
)
|
||||
|
@ -106,7 +106,8 @@ class BaseDatabaseOperations:
|
||||
extracts a value from the given date field field_name.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseOperations may require a date_extract_sql() method"
|
||||
"subclasses of BaseDatabaseOperations may require a date_extract_sql() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def date_trunc_sql(self, lookup_type, field_name, tzname=None):
|
||||
@ -119,7 +120,8 @@ class BaseDatabaseOperations:
|
||||
timezone.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseOperations may require a date_trunc_sql() method."
|
||||
"subclasses of BaseDatabaseOperations may require a date_trunc_sql() "
|
||||
"method."
|
||||
)
|
||||
|
||||
def datetime_cast_date_sql(self, field_name, tzname):
|
||||
@ -136,7 +138,8 @@ class BaseDatabaseOperations:
|
||||
Return the SQL to cast a datetime value to time value.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseOperations may require a datetime_cast_time_sql() method"
|
||||
"subclasses of BaseDatabaseOperations may require a "
|
||||
"datetime_cast_time_sql() method"
|
||||
)
|
||||
|
||||
def datetime_extract_sql(self, lookup_type, field_name, tzname):
|
||||
@ -146,7 +149,8 @@ class BaseDatabaseOperations:
|
||||
datetime field field_name.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseOperations may require a datetime_extract_sql() method"
|
||||
"subclasses of BaseDatabaseOperations may require a datetime_extract_sql() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def datetime_trunc_sql(self, lookup_type, field_name, tzname):
|
||||
@ -156,7 +160,8 @@ class BaseDatabaseOperations:
|
||||
field_name to a datetime object with only the given specificity.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"subclasses of BaseDatabaseOperations may require a datetime_trunc_sql() method"
|
||||
"subclasses of BaseDatabaseOperations may require a datetime_trunc_sql() "
|
||||
"method"
|
||||
)
|
||||
|
||||
def time_trunc_sql(self, lookup_type, field_name, tzname=None):
|
||||
@ -727,9 +732,9 @@ class BaseDatabaseOperations:
|
||||
|
||||
def window_frame_range_start_end(self, start=None, end=None):
|
||||
start_, end_ = self.window_frame_rows_start_end(start, end)
|
||||
if (
|
||||
self.connection.features.only_supports_unbounded_with_preceding_and_following
|
||||
and ((start and start < 0) or (end and end > 0))
|
||||
features = self.connection.features
|
||||
if features.only_supports_unbounded_with_preceding_and_following and (
|
||||
(start and start < 0) or (end and end > 0)
|
||||
):
|
||||
raise NotSupportedError(
|
||||
"%s only supports UNBOUNDED together with PRECEDING and "
|
||||
|
@ -104,7 +104,10 @@ class BaseDatabaseSchemaEditor:
|
||||
sql_create_check = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s CHECK (%(check)s)"
|
||||
sql_delete_check = sql_delete_constraint
|
||||
|
||||
sql_create_unique = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s UNIQUE (%(columns)s)%(deferrable)s"
|
||||
sql_create_unique = (
|
||||
"ALTER TABLE %(table)s ADD CONSTRAINT %(name)s "
|
||||
"UNIQUE (%(columns)s)%(deferrable)s"
|
||||
)
|
||||
sql_delete_unique = sql_delete_constraint
|
||||
|
||||
sql_create_fk = (
|
||||
@ -115,8 +118,14 @@ class BaseDatabaseSchemaEditor:
|
||||
sql_create_column_inline_fk = None
|
||||
sql_delete_fk = sql_delete_constraint
|
||||
|
||||
sql_create_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s)%(include)s%(extra)s%(condition)s"
|
||||
sql_create_unique_index = "CREATE UNIQUE INDEX %(name)s ON %(table)s (%(columns)s)%(include)s%(condition)s"
|
||||
sql_create_index = (
|
||||
"CREATE INDEX %(name)s ON %(table)s "
|
||||
"(%(columns)s)%(include)s%(extra)s%(condition)s"
|
||||
)
|
||||
sql_create_unique_index = (
|
||||
"CREATE UNIQUE INDEX %(name)s ON %(table)s "
|
||||
"(%(columns)s)%(include)s%(condition)s"
|
||||
)
|
||||
sql_delete_index = "DROP INDEX %(name)s"
|
||||
|
||||
sql_create_pk = (
|
||||
@ -418,10 +427,12 @@ class BaseDatabaseSchemaEditor:
|
||||
the given `model`.
|
||||
"""
|
||||
sql, params = self.table_sql(model)
|
||||
# Prevent using [] as params, in the case a literal '%' is used in the definition
|
||||
# Prevent using [] as params, in the case a literal '%' is used in the
|
||||
# definition.
|
||||
self.execute(sql, params or None)
|
||||
|
||||
# Add any field index and index_together's (deferred as SQLite _remake_table needs it)
|
||||
# Add any field index and index_together's (deferred as SQLite
|
||||
# _remake_table needs it).
|
||||
self.deferred_sql.extend(self._model_indexes_sql(model))
|
||||
|
||||
# Make M2M tables
|
||||
@ -1190,8 +1201,9 @@ class BaseDatabaseSchemaEditor:
|
||||
# Repoint the FK to the other side
|
||||
self.alter_field(
|
||||
new_field.remote_field.through,
|
||||
# We need the field that points to the target model, so we can tell alter_field to change it -
|
||||
# this is m2m_reverse_field_name() (as opposed to m2m_field_name, which points to our model)
|
||||
# The field that points to the target model is needed, so we can
|
||||
# tell alter_field to change it - this is m2m_reverse_field_name()
|
||||
# (as opposed to m2m_field_name(), which points to our model).
|
||||
old_field.remote_field.through._meta.get_field(
|
||||
old_field.m2m_reverse_field_name()
|
||||
),
|
||||
|
@ -349,9 +349,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
)
|
||||
for bad_row in cursor.fetchall():
|
||||
raise IntegrityError(
|
||||
"The row in table '%s' with primary key '%s' has an invalid "
|
||||
"foreign key: %s.%s contains a value '%s' that does not "
|
||||
"have a corresponding value in %s.%s."
|
||||
"The row in table '%s' with primary key '%s' has an "
|
||||
"invalid foreign key: %s.%s contains a value '%s' that "
|
||||
"does not have a corresponding value in %s.%s."
|
||||
% (
|
||||
table_name,
|
||||
bad_row[0],
|
||||
|
@ -69,8 +69,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
def django_test_skips(self):
|
||||
skips = {
|
||||
"This doesn't work on MySQL.": {
|
||||
"db_functions.comparison.test_greatest.GreatestTests.test_coalesce_workaround",
|
||||
"db_functions.comparison.test_least.LeastTests.test_coalesce_workaround",
|
||||
"db_functions.comparison.test_greatest.GreatestTests."
|
||||
"test_coalesce_workaround",
|
||||
"db_functions.comparison.test_least.LeastTests."
|
||||
"test_coalesce_workaround",
|
||||
},
|
||||
"Running on MySQL requires utf8mb4 encoding (#18392).": {
|
||||
"model_fields.test_textfield.TextFieldTests.test_emoji",
|
||||
@ -90,8 +92,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
{
|
||||
"GROUP BY optimization does not work properly when "
|
||||
"ONLY_FULL_GROUP_BY mode is enabled on MySQL, see #31331.": {
|
||||
"aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_multivalued",
|
||||
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_aggregate_with_m2o",
|
||||
"aggregation.tests.AggregateTestCase."
|
||||
"test_aggregation_subquery_annotation_multivalued",
|
||||
"annotations.tests.NonAggregateAnnotationTestCase."
|
||||
"test_annotation_aggregate_with_m2o",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -100,13 +104,19 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
):
|
||||
skips.update(
|
||||
{
|
||||
"Casting to datetime/time is not supported by MySQL < 8.0. (#30224)": {
|
||||
"aggregation.tests.AggregateTestCase.test_aggregation_default_using_time_from_python",
|
||||
"aggregation.tests.AggregateTestCase.test_aggregation_default_using_datetime_from_python",
|
||||
"Casting to datetime/time is not supported by MySQL < 8.0. "
|
||||
"(#30224)": {
|
||||
"aggregation.tests.AggregateTestCase."
|
||||
"test_aggregation_default_using_time_from_python",
|
||||
"aggregation.tests.AggregateTestCase."
|
||||
"test_aggregation_default_using_datetime_from_python",
|
||||
},
|
||||
"MySQL < 8.0 returns string type instead of datetime/time. (#30224)": {
|
||||
"aggregation.tests.AggregateTestCase.test_aggregation_default_using_time_from_database",
|
||||
"aggregation.tests.AggregateTestCase.test_aggregation_default_using_datetime_from_database",
|
||||
"MySQL < 8.0 returns string type instead of datetime/time. "
|
||||
"(#30224)": {
|
||||
"aggregation.tests.AggregateTestCase."
|
||||
"test_aggregation_default_using_time_from_database",
|
||||
"aggregation.tests.AggregateTestCase."
|
||||
"test_aggregation_default_using_datetime_from_database",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -118,7 +128,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
skips.update(
|
||||
{
|
||||
"https://jira.mariadb.org/browse/MDEV-19598": {
|
||||
"schema.tests.SchemaTests.test_alter_not_unique_field_to_primary_key",
|
||||
"schema.tests.SchemaTests."
|
||||
"test_alter_not_unique_field_to_primary_key",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -130,7 +141,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
skips.update(
|
||||
{
|
||||
"https://jira.mariadb.org/browse/MDEV-22775": {
|
||||
"schema.tests.SchemaTests.test_alter_pk_with_self_referential_field",
|
||||
"schema.tests.SchemaTests."
|
||||
"test_alter_pk_with_self_referential_field",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -92,7 +92,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
FROM information_schema.check_constraints AS c
|
||||
WHERE
|
||||
c.table_name = %s AND
|
||||
LOWER(c.check_clause) = 'json_valid(`' + LOWER(c.constraint_name) + '`)' AND
|
||||
LOWER(c.check_clause) =
|
||||
'json_valid(`' + LOWER(c.constraint_name) + '`)' AND
|
||||
c.constraint_schema = DATABASE()
|
||||
""",
|
||||
[table_name],
|
||||
|
@ -69,7 +69,8 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
return "CAST(DATE_FORMAT(%s, '%s') AS DATE)" % (field_name, format_str)
|
||||
elif lookup_type == "quarter":
|
||||
return (
|
||||
"MAKEDATE(YEAR(%s), 1) + INTERVAL QUARTER(%s) QUARTER - INTERVAL 1 QUARTER"
|
||||
"MAKEDATE(YEAR(%s), 1) + "
|
||||
"INTERVAL QUARTER(%s) QUARTER - INTERVAL 1 QUARTER"
|
||||
% (field_name, field_name)
|
||||
)
|
||||
elif lookup_type == "week":
|
||||
@ -266,7 +267,8 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
value = timezone.make_naive(value, self.connection.timezone)
|
||||
else:
|
||||
raise ValueError(
|
||||
"MySQL backend does not support timezone-aware datetimes when USE_TZ is False."
|
||||
"MySQL backend does not support timezone-aware datetimes when "
|
||||
"USE_TZ is False."
|
||||
)
|
||||
return str(value)
|
||||
|
||||
@ -347,7 +349,10 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
if self.connection.mysql_is_mariadb:
|
||||
# MariaDB includes the microsecond component in TIME_TO_SEC as
|
||||
# a decimal. MySQL returns an integer without microseconds.
|
||||
return "CAST((TIME_TO_SEC(%(lhs)s) - TIME_TO_SEC(%(rhs)s)) * 1000000 AS SIGNED)" % {
|
||||
return (
|
||||
"CAST((TIME_TO_SEC(%(lhs)s) - TIME_TO_SEC(%(rhs)s)) "
|
||||
"* 1000000 AS SIGNED)"
|
||||
) % {
|
||||
"lhs": lhs_sql,
|
||||
"rhs": rhs_sql,
|
||||
}, (
|
||||
|
@ -22,7 +22,8 @@ class DatabaseValidation(BaseDatabaseValidation):
|
||||
"%s, such as data truncation upon insertion, by "
|
||||
"escalating warnings into errors. It is strongly "
|
||||
"recommended you activate it. See: "
|
||||
"https://docs.djangoproject.com/en/%s/ref/databases/#mysql-sql-mode"
|
||||
"https://docs.djangoproject.com/en/%s/ref/databases/"
|
||||
"#mysql-sql-mode"
|
||||
% (
|
||||
self.connection.display_name,
|
||||
self.connection.display_name,
|
||||
|
@ -158,16 +158,31 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
_standard_operators = {
|
||||
"exact": "= %s",
|
||||
"iexact": "= UPPER(%s)",
|
||||
"contains": "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"icontains": "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"contains": (
|
||||
"LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
"icontains": (
|
||||
"LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) "
|
||||
"ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
"gt": "> %s",
|
||||
"gte": ">= %s",
|
||||
"lt": "< %s",
|
||||
"lte": "<= %s",
|
||||
"startswith": "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"endswith": "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"istartswith": "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"iendswith": "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
|
||||
"startswith": (
|
||||
"LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
"endswith": (
|
||||
"LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
"istartswith": (
|
||||
"LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) "
|
||||
"ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
"iendswith": (
|
||||
"LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) "
|
||||
"ESCAPE TRANSLATE('\\' USING NCHAR_CS)"
|
||||
),
|
||||
}
|
||||
|
||||
_likec_operators = {
|
||||
|
@ -61,7 +61,8 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||
cursor, parameters, verbosity, autoclobber
|
||||
)
|
||||
else:
|
||||
# Ran into a database error that isn't about leftover objects in the tablespace
|
||||
# Ran into a database error that isn't about
|
||||
# leftover objects in the tablespace.
|
||||
self.log(
|
||||
"Got an error destroying the old test database: %s"
|
||||
% e
|
||||
@ -117,7 +118,8 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||
else:
|
||||
self.log("Tests cancelled.")
|
||||
sys.exit(1)
|
||||
self._maindb_connection.close() # done with main user -- test user and tablespaces created
|
||||
# Done with main user -- test user and tablespaces created.
|
||||
self._maindb_connection.close()
|
||||
self._switch_to_test_user(parameters)
|
||||
return self.connection.settings_dict["NAME"]
|
||||
|
||||
@ -160,8 +162,8 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||
# There are objects in the test tablespace which prevent dropping it
|
||||
# The easy fix is to drop the test user -- but are we allowed to do so?
|
||||
self.log(
|
||||
"There are objects in the old test database which prevent its destruction.\n"
|
||||
"If they belong to the test user, deleting the user will allow the test "
|
||||
"There are objects in the old test database which prevent its destruction."
|
||||
"\nIf they belong to the test user, deleting the user will allow the test "
|
||||
"database to be recreated.\n"
|
||||
"Otherwise, you will need to find and remove each of these objects, "
|
||||
"or use a different tablespace.\n"
|
||||
@ -301,8 +303,10 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||
if verbosity >= 2:
|
||||
self.log("_execute_test_db_destruction(): dbname=%s" % parameters["user"])
|
||||
statements = [
|
||||
"DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS",
|
||||
"DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS",
|
||||
"DROP TABLESPACE %(tblspace)s "
|
||||
"INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS",
|
||||
"DROP TABLESPACE %(tblspace_temp)s "
|
||||
"INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS",
|
||||
]
|
||||
self._execute_statements(cursor, statements, parameters, verbosity)
|
||||
|
||||
|
@ -31,7 +31,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
requires_literal_defaults = True
|
||||
closed_cursor_error_class = InterfaceError
|
||||
bare_select_suffix = " FROM DUAL"
|
||||
# select for update with limit can be achieved on Oracle, but not with the current backend.
|
||||
# Select for update with limit can be achieved on Oracle, but not with the
|
||||
# current backend.
|
||||
supports_select_for_update_with_limit = False
|
||||
supports_temporal_subtraction = True
|
||||
# Oracle doesn't ignore quoted identifiers case but the current backend
|
||||
@ -79,13 +80,16 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
},
|
||||
"Oracle doesn't correctly calculate ISO 8601 week numbering before "
|
||||
"1583 (the Gregorian calendar was introduced in 1582).": {
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_week_before_1000",
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_week_before_1000",
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionTests."
|
||||
"test_trunc_week_before_1000",
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
|
||||
"test_trunc_week_before_1000",
|
||||
},
|
||||
"Oracle doesn't support bitwise XOR.": {
|
||||
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor",
|
||||
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null",
|
||||
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_right_null",
|
||||
"expressions.tests.ExpressionOperatorTests."
|
||||
"test_lefthand_bitwise_xor_right_null",
|
||||
},
|
||||
"Oracle requires ORDER BY in row_number, ANSI:SQL doesn't.": {
|
||||
"expressions_window.tests.WindowFunctionTests.test_row_number_no_ordering",
|
||||
@ -97,7 +101,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
django_test_expected_failures = {
|
||||
# A bug in Django/cx_Oracle with respect to string handling (#23843).
|
||||
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions",
|
||||
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions_can_ref_other_functions",
|
||||
"annotations.tests.NonAggregateAnnotationTestCase."
|
||||
"test_custom_functions_can_ref_other_functions",
|
||||
}
|
||||
|
||||
@cached_property
|
||||
|
@ -147,7 +147,14 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
is_autofield,
|
||||
is_json,
|
||||
)
|
||||
for column, default, collation, internal_size, is_autofield, is_json in cursor.fetchall()
|
||||
for (
|
||||
column,
|
||||
default,
|
||||
collation,
|
||||
internal_size,
|
||||
is_autofield,
|
||||
is_json,
|
||||
) in cursor.fetchall()
|
||||
}
|
||||
self.cache_bust_counter += 1
|
||||
cursor.execute(
|
||||
@ -271,7 +278,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
"""
|
||||
SELECT
|
||||
user_constraints.constraint_name,
|
||||
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.position),
|
||||
LISTAGG(LOWER(cols.column_name), ',')
|
||||
WITHIN GROUP (ORDER BY cols.position),
|
||||
CASE user_constraints.constraint_type
|
||||
WHEN 'P' THEN 1
|
||||
ELSE 0
|
||||
@ -287,7 +295,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
FROM
|
||||
user_constraints
|
||||
LEFT OUTER JOIN
|
||||
user_cons_columns cols ON user_constraints.constraint_name = cols.constraint_name
|
||||
user_cons_columns cols
|
||||
ON user_constraints.constraint_name = cols.constraint_name
|
||||
WHERE
|
||||
user_constraints.constraint_type = ANY('P', 'U', 'C')
|
||||
AND user_constraints.table_name = UPPER(%s)
|
||||
@ -310,15 +319,18 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
"""
|
||||
SELECT
|
||||
cons.constraint_name,
|
||||
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.position),
|
||||
LISTAGG(LOWER(cols.column_name), ',')
|
||||
WITHIN GROUP (ORDER BY cols.position),
|
||||
LOWER(rcols.table_name),
|
||||
LOWER(rcols.column_name)
|
||||
FROM
|
||||
user_constraints cons
|
||||
INNER JOIN
|
||||
user_cons_columns rcols ON rcols.constraint_name = cons.r_constraint_name AND rcols.position = 1
|
||||
user_cons_columns rcols
|
||||
ON rcols.constraint_name = cons.r_constraint_name AND rcols.position = 1
|
||||
LEFT OUTER JOIN
|
||||
user_cons_columns cols ON cons.constraint_name = cols.constraint_name
|
||||
user_cons_columns cols
|
||||
ON cons.constraint_name = cols.constraint_name
|
||||
WHERE
|
||||
cons.constraint_type = 'R' AND
|
||||
cons.table_name = UPPER(%s)
|
||||
@ -343,7 +355,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
ind.index_name,
|
||||
LOWER(ind.index_type),
|
||||
LOWER(ind.uniqueness),
|
||||
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.column_position),
|
||||
LISTAGG(LOWER(cols.column_name), ',')
|
||||
WITHIN GROUP (ORDER BY cols.column_position),
|
||||
LISTAGG(cols.descend, ',') WITHIN GROUP (ORDER BY cols.column_position)
|
||||
FROM
|
||||
user_ind_columns cols, user_indexes ind
|
||||
|
@ -399,12 +399,15 @@ END;
|
||||
user_tables
|
||||
JOIN
|
||||
user_constraints cons
|
||||
ON (user_tables.table_name = cons.table_name AND cons.constraint_type = ANY('P', 'U'))
|
||||
ON (user_tables.table_name = cons.table_name
|
||||
AND cons.constraint_type = ANY('P', 'U'))
|
||||
LEFT JOIN
|
||||
user_constraints rcons
|
||||
ON (user_tables.table_name = rcons.table_name AND rcons.constraint_type = 'R')
|
||||
ON (user_tables.table_name = rcons.table_name
|
||||
AND rcons.constraint_type = 'R')
|
||||
START WITH user_tables.table_name = UPPER(%s)
|
||||
CONNECT BY NOCYCLE PRIOR cons.constraint_name = rcons.r_constraint_name
|
||||
CONNECT BY
|
||||
NOCYCLE PRIOR cons.constraint_name = rcons.r_constraint_name
|
||||
GROUP BY
|
||||
user_tables.table_name, rcons.constraint_name
|
||||
HAVING user_tables.table_name != UPPER(%s)
|
||||
@ -583,7 +586,8 @@ END;
|
||||
value = timezone.make_naive(value, self.connection.timezone)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Oracle backend does not support timezone-aware datetimes when USE_TZ is False."
|
||||
"Oracle backend does not support timezone-aware datetimes when "
|
||||
"USE_TZ is False."
|
||||
)
|
||||
|
||||
return Oracle_datetime.from_datetime(value)
|
||||
|
@ -132,10 +132,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||
new_value = "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')" % new_value
|
||||
elif new_internal_type == "TimeField":
|
||||
# TimeField are stored as TIMESTAMP with a 1900-01-01 date part.
|
||||
new_value = (
|
||||
"TO_TIMESTAMP(CONCAT('1900-01-01 ', %s), 'YYYY-MM-DD HH24:MI:SS.FF')"
|
||||
% new_value
|
||||
)
|
||||
new_value = "CONCAT('1900-01-01 ', %s)" % new_value
|
||||
new_value = "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')" % new_value
|
||||
# Transfer values across
|
||||
self.execute(
|
||||
"UPDATE %s set %s=%s"
|
||||
|
@ -67,7 +67,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
|
||||
django_test_skips = {
|
||||
"opclasses are PostgreSQL only.": {
|
||||
"indexes.tests.SchemaIndexesNotPostgreSQLTests.test_create_index_ignores_opclasses",
|
||||
"indexes.tests.SchemaIndexesNotPostgreSQLTests."
|
||||
"test_create_index_ignores_opclasses",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
"""Return a list of table and view names in the current database."""
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT c.relname,
|
||||
CASE WHEN c.relispartition THEN 'p' WHEN c.relkind IN ('m', 'v') THEN 'v' ELSE 't' END
|
||||
SELECT
|
||||
c.relname,
|
||||
CASE
|
||||
WHEN c.relispartition THEN 'p'
|
||||
WHEN c.relkind IN ('m', 'v') THEN 'v'
|
||||
ELSE 't'
|
||||
END
|
||||
FROM pg_catalog.pg_class c
|
||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind IN ('f', 'm', 'p', 'r', 'v')
|
||||
@ -116,9 +121,15 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
SELECT s.relname as sequence_name, col.attname
|
||||
FROM pg_class s
|
||||
JOIN pg_namespace sn ON sn.oid = s.relnamespace
|
||||
JOIN pg_depend d ON d.refobjid = s.oid AND d.refclassid = 'pg_class'::regclass
|
||||
JOIN pg_attrdef ad ON ad.oid = d.objid AND d.classid = 'pg_attrdef'::regclass
|
||||
JOIN pg_attribute col ON col.attrelid = ad.adrelid AND col.attnum = ad.adnum
|
||||
JOIN
|
||||
pg_depend d ON d.refobjid = s.oid
|
||||
AND d.refclassid = 'pg_class'::regclass
|
||||
JOIN
|
||||
pg_attrdef ad ON ad.oid = d.objid
|
||||
AND d.classid = 'pg_attrdef'::regclass
|
||||
JOIN
|
||||
pg_attribute col ON col.attrelid = ad.adrelid
|
||||
AND col.attnum = ad.adnum
|
||||
JOIN pg_class tbl ON tbl.oid = ad.adrelid
|
||||
WHERE s.relkind = 'S'
|
||||
AND d.deptype in ('a', 'n')
|
||||
@ -143,8 +154,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
FROM pg_constraint con
|
||||
LEFT JOIN pg_class c1 ON con.conrelid = c1.oid
|
||||
LEFT JOIN pg_class c2 ON con.confrelid = c2.oid
|
||||
LEFT JOIN pg_attribute a1 ON c1.oid = a1.attrelid AND a1.attnum = con.conkey[1]
|
||||
LEFT JOIN pg_attribute a2 ON c2.oid = a2.attrelid AND a2.attnum = con.confkey[1]
|
||||
LEFT JOIN
|
||||
pg_attribute a1 ON c1.oid = a1.attrelid AND a1.attnum = con.conkey[1]
|
||||
LEFT JOIN
|
||||
pg_attribute a2 ON c2.oid = a2.attrelid AND a2.attnum = con.confkey[1]
|
||||
WHERE
|
||||
c1.relname = %s AND
|
||||
con.contype = 'f' AND
|
||||
@ -203,8 +216,14 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT
|
||||
indexname, array_agg(attname ORDER BY arridx), indisunique, indisprimary,
|
||||
array_agg(ordering ORDER BY arridx), amname, exprdef, s2.attoptions
|
||||
indexname,
|
||||
array_agg(attname ORDER BY arridx),
|
||||
indisunique,
|
||||
indisprimary,
|
||||
array_agg(ordering ORDER BY arridx),
|
||||
amname,
|
||||
exprdef,
|
||||
s2.attoptions
|
||||
FROM (
|
||||
SELECT
|
||||
c2.relname as indexname, idx.*, attr.attname, am.amname,
|
||||
@ -221,12 +240,16 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
c2.reloptions as attoptions
|
||||
FROM (
|
||||
SELECT *
|
||||
FROM pg_index i, unnest(i.indkey, i.indoption) WITH ORDINALITY koi(key, option, arridx)
|
||||
FROM
|
||||
pg_index i,
|
||||
unnest(i.indkey, i.indoption)
|
||||
WITH ORDINALITY koi(key, option, arridx)
|
||||
) idx
|
||||
LEFT JOIN pg_class c ON idx.indrelid = c.oid
|
||||
LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid
|
||||
LEFT JOIN pg_am am ON c2.relam = am.oid
|
||||
LEFT JOIN pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key
|
||||
LEFT JOIN
|
||||
pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key
|
||||
WHERE c.relname = %s AND pg_catalog.pg_table_is_visible(c.oid)
|
||||
) s2
|
||||
GROUP BY indexname, indisunique, indisprimary, amname, exprdef, attoptions;
|
||||
|
@ -187,11 +187,12 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
output = []
|
||||
qn = self.quote_name
|
||||
for model in model_list:
|
||||
# Use `coalesce` to set the sequence for each model to the max pk value if there are records,
|
||||
# or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true
|
||||
# if there are records (as the max pk value is already in use), otherwise set it to false.
|
||||
# Use pg_get_serial_sequence to get the underlying sequence name from the table name
|
||||
# and column name (available since PostgreSQL 8)
|
||||
# Use `coalesce` to set the sequence for each model to the max pk
|
||||
# value if there are records, or 1 if there are none. Set the
|
||||
# `is_called` property (the third argument to `setval`) to true if
|
||||
# there are records (as the max pk value is already in use),
|
||||
# otherwise set it to false. Use pg_get_serial_sequence to get the
|
||||
# underlying sequence name from the table name and column name.
|
||||
|
||||
for f in model._meta.local_fields:
|
||||
if isinstance(f, models.AutoField):
|
||||
@ -209,7 +210,9 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
style.SQL_TABLE(qn(model._meta.db_table)),
|
||||
)
|
||||
)
|
||||
break # Only one AutoField is allowed per model, so don't bother continuing.
|
||||
# Only one AutoField is allowed per model, so don't bother
|
||||
# continuing.
|
||||
break
|
||||
return output
|
||||
|
||||
def prep_for_iexact_query(self, x):
|
||||
|
@ -33,8 +33,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||
)
|
||||
# Setting the constraint to IMMEDIATE runs any deferred checks to allow
|
||||
# dropping it in the same transaction.
|
||||
sql_delete_fk = "SET CONSTRAINTS %(name)s IMMEDIATE; ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"
|
||||
|
||||
sql_delete_fk = (
|
||||
"SET CONSTRAINTS %(name)s IMMEDIATE; "
|
||||
"ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"
|
||||
)
|
||||
sql_delete_procedure = "DROP FUNCTION %(procedure)s(%(param_types)s)"
|
||||
|
||||
def quote_value(self, value):
|
||||
|
@ -209,9 +209,15 @@ def _sqlite_datetime_trunc(lookup_type, dt, tzname, conn_tzname):
|
||||
elif lookup_type == "hour":
|
||||
return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} {dt.hour:02d}:00:00"
|
||||
elif lookup_type == "minute":
|
||||
return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} {dt.hour:02d}:{dt.minute:02d}:00"
|
||||
return (
|
||||
f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} "
|
||||
f"{dt.hour:02d}:{dt.minute:02d}:00"
|
||||
)
|
||||
elif lookup_type == "second":
|
||||
return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} {dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}"
|
||||
return (
|
||||
f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} "
|
||||
f"{dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}"
|
||||
)
|
||||
raise ValueError(f"Unsupported lookup type: {lookup_type!r}")
|
||||
|
||||
|
||||
|
@ -57,26 +57,34 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
def django_test_skips(self):
|
||||
skips = {
|
||||
"SQLite stores values rounded to 15 significant digits.": {
|
||||
"model_fields.test_decimalfield.DecimalFieldTests.test_fetch_from_db_without_float_rounding",
|
||||
"model_fields.test_decimalfield.DecimalFieldTests."
|
||||
"test_fetch_from_db_without_float_rounding",
|
||||
},
|
||||
"SQLite naively remakes the table on field alteration.": {
|
||||
"schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops",
|
||||
"schema.tests.SchemaTests.test_unique_and_reverse_m2m",
|
||||
"schema.tests.SchemaTests.test_alter_field_default_doesnt_perform_queries",
|
||||
"schema.tests.SchemaTests.test_rename_column_renames_deferred_sql_references",
|
||||
"schema.tests.SchemaTests."
|
||||
"test_alter_field_default_doesnt_perform_queries",
|
||||
"schema.tests.SchemaTests."
|
||||
"test_rename_column_renames_deferred_sql_references",
|
||||
},
|
||||
"SQLite doesn't support negative precision for ROUND().": {
|
||||
"db_functions.math.test_round.RoundTests.test_null_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests.test_decimal_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests.test_float_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests.test_integer_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests."
|
||||
"test_null_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests."
|
||||
"test_decimal_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests."
|
||||
"test_float_with_negative_precision",
|
||||
"db_functions.math.test_round.RoundTests."
|
||||
"test_integer_with_negative_precision",
|
||||
},
|
||||
}
|
||||
if Database.sqlite_version_info < (3, 27):
|
||||
skips.update(
|
||||
{
|
||||
"Nondeterministic failure on SQLite < 3.27.": {
|
||||
"expressions_window.tests.WindowFunctionTests.test_subquery_row_range_rank",
|
||||
"expressions_window.tests.WindowFunctionTests."
|
||||
"test_subquery_row_range_rank",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -85,8 +93,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
{
|
||||
"the sqlite backend's close() method is a no-op when using an "
|
||||
"in-memory database": {
|
||||
"servers.test_liveserverthread.LiveServerThreadTest.test_closes_connections",
|
||||
"servers.tests.LiveServerTestCloseConnectionTest.test_closes_connections",
|
||||
"servers.test_liveserverthread.LiveServerThreadTest."
|
||||
"test_closes_connections",
|
||||
"servers.tests.LiveServerTestCloseConnectionTest."
|
||||
"test_closes_connections",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -146,7 +146,14 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
)
|
||||
return {
|
||||
column_name: (ref_column_name, ref_table_name)
|
||||
for _, _, ref_table_name, column_name, ref_column_name, *_ in cursor.fetchall()
|
||||
for (
|
||||
_,
|
||||
_,
|
||||
ref_table_name,
|
||||
column_name,
|
||||
ref_column_name,
|
||||
*_,
|
||||
) in cursor.fetchall()
|
||||
}
|
||||
|
||||
def get_primary_key_column(self, cursor, table_name):
|
||||
|
@ -168,7 +168,9 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
|
||||
def last_executed_query(self, cursor, sql, params):
|
||||
# Python substitutes parameters in Modules/_sqlite/cursor.c with:
|
||||
# pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars);
|
||||
# pysqlite_statement_bind_parameters(
|
||||
# self->statement, parameters, allow_8bit_chars
|
||||
# );
|
||||
# Unfortunately there is no way to reach self->statement from Python,
|
||||
# so we quote and substitute parameters manually.
|
||||
if params:
|
||||
@ -271,7 +273,8 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
value = timezone.make_naive(value, self.connection.timezone)
|
||||
else:
|
||||
raise ValueError(
|
||||
"SQLite backend does not support timezone-aware datetimes when USE_TZ is False."
|
||||
"SQLite backend does not support timezone-aware datetimes when "
|
||||
"USE_TZ is False."
|
||||
)
|
||||
|
||||
return str(value)
|
||||
|
@ -468,12 +468,15 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||
old_field.remote_field.through._meta.db_table
|
||||
== new_field.remote_field.through._meta.db_table
|
||||
):
|
||||
# The field name didn't change, but some options did; we have to propagate this altering.
|
||||
# The field name didn't change, but some options did, so we have to
|
||||
# propagate this altering.
|
||||
self._remake_table(
|
||||
old_field.remote_field.through,
|
||||
alter_field=(
|
||||
# We need the field that points to the target model, so we can tell alter_field to change it -
|
||||
# this is m2m_reverse_field_name() (as opposed to m2m_field_name, which points to our model)
|
||||
# The field that points to the target model is needed, so
|
||||
# we can tell alter_field to change it - this is
|
||||
# m2m_reverse_field_name() (as opposed to m2m_field_name(),
|
||||
# which points to our model).
|
||||
old_field.remote_field.through._meta.get_field(
|
||||
old_field.m2m_reverse_field_name()
|
||||
),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user