summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/conf/urls/i18n.py4
-rw-r--r--django/contrib/admin/decorators.py9
-rw-r--r--django/contrib/contenttypes/fields.py20
-rw-r--r--django/contrib/contenttypes/models.py3
-rw-r--r--django/contrib/gis/db/models/fields.py7
-rw-r--r--django/contrib/gis/forms/fields.py9
-rw-r--r--django/contrib/gis/geos/libgeos.py11
-rw-r--r--django/contrib/postgres/search.py14
-rw-r--r--django/core/mail/backends/filebased.py6
-rw-r--r--django/core/serializers/base.py15
-rw-r--r--django/core/serializers/python.py14
-rw-r--r--django/core/serializers/xml_serializer.py6
-rw-r--r--django/core/servers/basehttp.py6
-rw-r--r--django/db/backends/oracle/functions.py10
-rw-r--r--django/db/models/expressions.py11
-rw-r--r--django/db/models/fields/__init__.py10
-rw-r--r--django/db/models/fields/related.py10
-rw-r--r--django/db/models/fields/related_descriptors.py30
-rw-r--r--django/db/models/functions/base.py5
-rw-r--r--django/db/models/query.py21
-rw-r--r--django/forms/fields.py24
-rw-r--r--django/forms/models.py10
-rw-r--r--django/shortcuts.py8
-rw-r--r--django/template/loader_tags.py6
-rw-r--r--django/test/testcases.py3
-rw-r--r--django/utils/datastructures.py7
-rw-r--r--django/utils/deconstruct.py6
-rw-r--r--django/views/decorators/cache.py14
-rw-r--r--django/views/generic/list.py4
29 files changed, 114 insertions, 189 deletions
diff --git a/django/conf/urls/i18n.py b/django/conf/urls/i18n.py
index 23e4bbcd74..3731afc886 100644
--- a/django/conf/urls/i18n.py
+++ b/django/conf/urls/i18n.py
@@ -6,7 +6,7 @@ from django.urls import LocaleRegexURLResolver, get_resolver
from django.views.i18n import set_language
-def i18n_patterns(*urls, **kwargs):
+def i18n_patterns(*urls, prefix_default_language=True):
"""
Adds the language code prefix to every URL pattern within this
function. This may only be used in the root URLconf, not in an included
@@ -14,8 +14,6 @@ def i18n_patterns(*urls, **kwargs):
"""
if not settings.USE_I18N:
return list(urls)
- prefix_default_language = kwargs.pop('prefix_default_language', True)
- assert not kwargs, 'Unexpected kwargs for i18n_patterns(): %s' % kwargs
return [LocaleRegexURLResolver(list(urls), prefix_default_language=prefix_default_language)]
diff --git a/django/contrib/admin/decorators.py b/django/contrib/admin/decorators.py
index 8b30139ea3..1a0d981225 100644
--- a/django/contrib/admin/decorators.py
+++ b/django/contrib/admin/decorators.py
@@ -1,4 +1,4 @@
-def register(*models, **kwargs):
+def register(*models, site=None):
"""
Registers the given model(s) classes and wrapped ModelAdmin class with
admin site:
@@ -7,17 +7,16 @@ def register(*models, **kwargs):
class AuthorAdmin(admin.ModelAdmin):
pass
- A kwarg of `site` can be passed as the admin site, otherwise the default
- admin site will be used.
+ The `site` kwarg is an admin site to use instead of the default admin site.
"""
from django.contrib.admin import ModelAdmin
- from django.contrib.admin.sites import site, AdminSite
+ from django.contrib.admin.sites import site as default_site, AdminSite
def _model_admin_wrapper(admin_class):
if not models:
raise ValueError('At least one model must be passed to register.')
- admin_site = kwargs.pop('site', site)
+ admin_site = site or default_site
if not isinstance(admin_site, AdminSite):
raise ValueError('site must subclass AdminSite')
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
index 37a9df14a0..c2b46d1254 100644
--- a/django/contrib/contenttypes/fields.py
+++ b/django/contrib/contenttypes/fields.py
@@ -496,10 +496,8 @@ def create_generic_related_manager(superclass, rel):
self.object_id_field_name: self.pk_val,
}
- def __call__(self, **kwargs):
- # We use **kwargs rather than a kwarg argument to enforce the
- # `manager='manager_name'` syntax.
- manager = getattr(self.model, kwargs.pop('manager'))
+ def __call__(self, *, manager):
+ manager = getattr(self.model, manager)
manager_class = create_generic_related_manager(manager.__class__, rel)
return manager_class(instance=self.instance)
do_not_call_in_templates = True
@@ -542,8 +540,7 @@ def create_generic_related_manager(superclass, rel):
False,
self.prefetch_cache_name)
- def add(self, *objs, **kwargs):
- bulk = kwargs.pop('bulk', True)
+ def add(self, *objs, bulk=True):
db = router.db_for_write(self.model, instance=self.instance)
def check_and_update_obj(obj):
@@ -576,15 +573,13 @@ def create_generic_related_manager(superclass, rel):
obj.save()
add.alters_data = True
- def remove(self, *objs, **kwargs):
+ def remove(self, *objs, bulk=True):
if not objs:
return
- bulk = kwargs.pop('bulk', True)
self._clear(self.filter(pk__in=[o.pk for o in objs]), bulk)
remove.alters_data = True
- def clear(self, **kwargs):
- bulk = kwargs.pop('bulk', True)
+ def clear(self, *, bulk=True):
self._clear(self, bulk)
clear.alters_data = True
@@ -601,14 +596,11 @@ def create_generic_related_manager(superclass, rel):
obj.delete()
_clear.alters_data = True
- def set(self, objs, **kwargs):
+ def set(self, objs, *, bulk=True, clear=False):
# Force evaluation of `objs` in case it's a queryset whose value
# could be affected by `manager.clear()`. Refs #19816.
objs = tuple(objs)
- bulk = kwargs.pop('bulk', True)
- clear = kwargs.pop('clear', False)
-
db = router.db_for_write(self.model, instance=self.instance)
with transaction.atomic(using=db, savepoint=False):
if clear:
diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
index ce9afdb8ad..522bf2d279 100644
--- a/django/contrib/contenttypes/models.py
+++ b/django/contrib/contenttypes/models.py
@@ -60,11 +60,10 @@ class ContentTypeManager(models.Manager):
self._add_to_cache(self.db, ct)
return ct
- def get_for_models(self, *models, **kwargs):
+ def get_for_models(self, *models, for_concrete_models=True):
"""
Given *models, returns a dictionary mapping {model: content_type}.
"""
- for_concrete_models = kwargs.pop('for_concrete_models', True)
results = {}
# Models that aren't already in the cache.
needed_app_labels = set()
diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py
index d6cd529dc1..c8cf827c10 100644
--- a/django/contrib/gis/db/models/fields.py
+++ b/django/contrib/gis/db/models/fields.py
@@ -263,7 +263,8 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
# The OpenGIS Geometry name.
geom_type = 'GEOMETRY'
- def __init__(self, verbose_name=None, dim=2, geography=False, **kwargs):
+ def __init__(self, verbose_name=None, dim=2, geography=False, *, extent=(-180.0, -90.0, 180.0, 90.0),
+ tolerance=0.05, **kwargs):
"""
The initialization function for geometry fields. In addition to the
parameters from BaseSpatialField, it takes the following as keyword
@@ -289,8 +290,8 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
# Oracle-specific private attributes for creating the entry in
# `USER_SDO_GEOM_METADATA`
- self._extent = kwargs.pop('extent', (-180.0, -90.0, 180.0, 90.0))
- self._tolerance = kwargs.pop('tolerance', 0.05)
+ self._extent = extent
+ self._tolerance = tolerance
super().__init__(verbose_name=verbose_name, **kwargs)
diff --git a/django/contrib/gis/forms/fields.py b/django/contrib/gis/forms/fields.py
index f435bd5ab1..4a2efb5100 100644
--- a/django/contrib/gis/forms/fields.py
+++ b/django/contrib/gis/forms/fields.py
@@ -22,11 +22,10 @@ class GeometryField(forms.Field):
'to the SRID of the geometry form field.'),
}
- def __init__(self, **kwargs):
- # Pop out attributes from the database field, or use sensible
- # defaults (e.g., allow None).
- self.srid = kwargs.pop('srid', None)
- self.geom_type = kwargs.pop('geom_type', self.geom_type)
+ def __init__(self, *, srid=None, geom_type=None, **kwargs):
+ self.srid = srid
+ if geom_type is not None:
+ self.geom_type = geom_type
super().__init__(**kwargs)
self.widget.attrs['geom_type'] = self.geom_type
diff --git a/django/contrib/gis/geos/libgeos.py b/django/contrib/gis/geos/libgeos.py
index faf29de0c1..43353e5750 100644
--- a/django/contrib/gis/geos/libgeos.py
+++ b/django/contrib/gis/geos/libgeos.py
@@ -147,11 +147,14 @@ class GEOSFuncFactory:
restype = None
errcheck = None
- def __init__(self, func_name, *args, **kwargs):
+ def __init__(self, func_name, *args, restype=None, errcheck=None, argtypes=None, **kwargs):
self.func_name = func_name
- self.restype = kwargs.pop('restype', self.restype)
- self.errcheck = kwargs.pop('errcheck', self.errcheck)
- self.argtypes = kwargs.pop('argtypes', self.argtypes)
+ if restype is not None:
+ self.restype = restype
+ if errcheck is not None:
+ self.errcheck = errcheck
+ if argtypes is not None:
+ self.argtypes = argtypes
self.args = args
self.kwargs = kwargs
self.func = None
diff --git a/django/contrib/postgres/search.py b/django/contrib/postgres/search.py
index 9a773db1d5..9d66976ae0 100644
--- a/django/contrib/postgres/search.py
+++ b/django/contrib/postgres/search.py
@@ -125,13 +125,11 @@ class SearchQueryCombinable:
class SearchQuery(SearchQueryCombinable, Value):
- invert = False
_output_field = SearchQueryField()
- config = None
- def __init__(self, value, output_field=None, **extra):
- self.config = extra.pop('config', self.config)
- self.invert = extra.pop('invert', self.invert)
+ def __init__(self, value, output_field=None, *, config=None, invert=False):
+ self.config = config
+ self.invert = invert
super().__init__(value, output_field=output_field)
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
@@ -161,11 +159,7 @@ class SearchQuery(SearchQueryCombinable, Value):
return combined
def __invert__(self):
- extra = {
- 'invert': not self.invert,
- 'config': self.config,
- }
- return type(self)(self.value, **extra)
+ return type(self)(self.value, config=self.config, invert=not self.invert)
class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression):
diff --git a/django/core/mail/backends/filebased.py b/django/core/mail/backends/filebased.py
index b051fe6313..e956a3367a 100644
--- a/django/core/mail/backends/filebased.py
+++ b/django/core/mail/backends/filebased.py
@@ -10,10 +10,10 @@ from django.core.mail.backends.console import \
class EmailBackend(ConsoleEmailBackend):
- def __init__(self, *args, **kwargs):
+ def __init__(self, *args, file_path=None, **kwargs):
self._fname = None
- if 'file_path' in kwargs:
- self.file_path = kwargs.pop('file_path')
+ if file_path is not None:
+ self.file_path = file_path
else:
self.file_path = getattr(settings, 'EMAIL_FILE_PATH', None)
# Make sure self.file_path is a string.
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
index d1a5344064..2ffe022da9 100644
--- a/django/core/serializers/base.py
+++ b/django/core/serializers/base.py
@@ -62,19 +62,18 @@ class Serializer:
progress_class = ProgressBar
stream_class = StringIO
- def serialize(self, queryset, **options):
+ def serialize(self, queryset, *, stream=None, fields=None, use_natural_foreign_keys=False,
+ use_natural_primary_keys=False, progress_output=None, object_count=0, **options):
"""
Serialize a queryset.
"""
self.options = options
- self.stream = options.pop("stream", self.stream_class())
- self.selected_fields = options.pop("fields", None)
- self.use_natural_foreign_keys = options.pop('use_natural_foreign_keys', False)
- self.use_natural_primary_keys = options.pop('use_natural_primary_keys', False)
- progress_bar = self.progress_class(
- options.pop('progress_output', None), options.pop('object_count', 0)
- )
+ self.stream = stream if stream is not None else self.stream_class()
+ self.selected_fields = fields
+ self.use_natural_foreign_keys = use_natural_foreign_keys
+ self.use_natural_primary_keys = use_natural_primary_keys
+ progress_bar = self.progress_class(progress_output, object_count)
self.start_serialization()
self.first = True
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index 7b7510be41..a299ed62c8 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -79,15 +79,13 @@ class Serializer(base.Serializer):
return self.objects
-def Deserializer(object_list, **options):
+def Deserializer(object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options):
"""
Deserialize simple Python objects back into Django ORM instances.
It's expected that you pass the Python objects themselves (instead of a
stream or a string) to the constructor
"""
- db = options.pop('using', DEFAULT_DB_ALIAS)
- ignore = options.pop('ignorenonexistent', False)
field_names_cache = {} # Model: <list of field_names>
for d in object_list:
@@ -95,7 +93,7 @@ def Deserializer(object_list, **options):
try:
Model = _get_model(d["model"])
except base.DeserializationError:
- if ignore:
+ if ignorenonexistent:
continue
else:
raise
@@ -114,7 +112,7 @@ def Deserializer(object_list, **options):
# Handle each field
for (field_name, field_value) in d["fields"].items():
- if ignore and field_name not in field_names:
+ if ignorenonexistent and field_name not in field_names:
# skip fields no longer on model
continue
@@ -131,7 +129,7 @@ def Deserializer(object_list, **options):
if hasattr(model._default_manager, 'get_by_natural_key'):
def m2m_convert(value):
if hasattr(value, '__iter__') and not isinstance(value, str):
- return model._default_manager.db_manager(db).get_by_natural_key(*value).pk
+ return model._default_manager.db_manager(using).get_by_natural_key(*value).pk
else:
return force_text(model._meta.pk.to_python(value), strings_only=True)
else:
@@ -154,7 +152,7 @@ def Deserializer(object_list, **options):
field_name = field.remote_field.field_name
if hasattr(default_manager, 'get_by_natural_key'):
if hasattr(field_value, '__iter__') and not isinstance(field_value, str):
- obj = default_manager.db_manager(db).get_by_natural_key(*field_value)
+ obj = default_manager.db_manager(using).get_by_natural_key(*field_value)
value = getattr(obj, field.remote_field.field_name)
# If this is a natural foreign key to an object that
# has a FK/O2O as the foreign key, use the FK value
@@ -177,7 +175,7 @@ def Deserializer(object_list, **options):
except Exception as e:
raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value)
- obj = base.build_instance(Model, data, db)
+ obj = base.build_instance(Model, data, using)
yield base.DeserializedObject(obj, m2m_data)
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
index ddf0bf3e1a..7e64952074 100644
--- a/django/core/serializers/xml_serializer.py
+++ b/django/core/serializers/xml_serializer.py
@@ -157,11 +157,11 @@ class Deserializer(base.Deserializer):
Deserialize XML.
"""
- def __init__(self, stream_or_string, **options):
+ def __init__(self, stream_or_string, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options):
super().__init__(stream_or_string, **options)
self.event_stream = pulldom.parse(self.stream, self._make_parser())
- self.db = options.pop('using', DEFAULT_DB_ALIAS)
- self.ignore = options.pop('ignorenonexistent', False)
+ self.db = using
+ self.ignore = ignorenonexistent
def _make_parser(self):
"""Create a hardened XML parser (no custom/external entities)."""
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index ef2edc0f80..68ef2a74b7 100644
--- a/django/core/servers/basehttp.py
+++ b/django/core/servers/basehttp.py
@@ -59,10 +59,10 @@ class WSGIServer(simple_server.WSGIServer):
request_queue_size = 10
- def __init__(self, *args, **kwargs):
- if kwargs.pop('ipv6', False):
+ def __init__(self, *args, ipv6=False, allow_reuse_address=True, **kwargs):
+ if ipv6:
self.address_family = socket.AF_INET6
- self.allow_reuse_address = kwargs.pop('allow_reuse_address', True)
+ self.allow_reuse_address = allow_reuse_address
super().__init__(*args, **kwargs)
def server_bind(self):
diff --git a/django/db/backends/oracle/functions.py b/django/db/backends/oracle/functions.py
index 7e9b6a6204..1aeb4597e3 100644
--- a/django/db/backends/oracle/functions.py
+++ b/django/db/backends/oracle/functions.py
@@ -10,15 +10,13 @@ class IntervalToSeconds(Func):
EXTRACT(second from %(expressions)s)
"""
- def __init__(self, expression, **extra):
- output_field = extra.pop('output_field', DecimalField())
- super().__init__(expression, output_field=output_field, **extra)
+ def __init__(self, expression, *, output_field=None, **extra):
+ super().__init__(expression, output_field=output_field or DecimalField(), **extra)
class SecondsToInterval(Func):
function = 'NUMTODSINTERVAL'
template = "%(function)s(%(expressions)s, 'SECOND')"
- def __init__(self, expression, **extra):
- output_field = extra.pop('output_field', DurationField())
- super().__init__(expression, output_field=output_field, **extra)
+ def __init__(self, expression, *, output_field=None, **extra):
+ super().__init__(expression, output_field=output_field or DurationField(), **extra)
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index fcbf867b96..af8891da22 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -506,7 +506,7 @@ class Func(Expression):
arg_joiner = ', '
arity = None # The number of arguments the function accepts.
- def __init__(self, *expressions, **extra):
+ def __init__(self, *expressions, output_field=None, **extra):
if self.arity is not None and len(expressions) != self.arity:
raise TypeError(
"'%s' takes exactly %s %s (%s given)" % (
@@ -516,7 +516,6 @@ class Func(Expression):
len(expressions),
)
)
- output_field = extra.pop('output_field', None)
super().__init__(output_field=output_field)
self.source_expressions = self._parse_expressions(*expressions)
self.extra = extra
@@ -828,11 +827,9 @@ class Case(Expression):
template = 'CASE %(cases)s ELSE %(default)s END'
case_joiner = ' '
- def __init__(self, *cases, **extra):
+ def __init__(self, *cases, default=None, output_field=None, **extra):
if not all(isinstance(case, When) for case in cases):
raise TypeError("Positional arguments must all be When objects.")
- default = extra.pop('default', None)
- output_field = extra.pop('output_field', None)
super().__init__(output_field)
self.cases = list(cases)
self.default = self._parse_expressions(default)[0]
@@ -983,8 +980,8 @@ class Subquery(Expression):
class Exists(Subquery):
template = 'EXISTS(%(subquery)s)'
- def __init__(self, *args, **kwargs):
- self.negated = kwargs.pop('negated', False)
+ def __init__(self, *args, negated=False, **kwargs):
+ self.negated = negated
super().__init__(*args, **kwargs)
def __invert__(self):
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 809a14277e..68a42f0236 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -2045,15 +2045,11 @@ class SlugField(CharField):
default_validators = [validators.validate_slug]
description = _("Slug (up to %(max_length)s)")
- def __init__(self, *args, **kwargs):
- kwargs['max_length'] = kwargs.get('max_length', 50)
- # Set db_index=True unless it's been set manually.
- if 'db_index' not in kwargs:
- kwargs['db_index'] = True
- self.allow_unicode = kwargs.pop('allow_unicode', False)
+ def __init__(self, *args, max_length=50, db_index=True, allow_unicode=False, **kwargs):
+ self.allow_unicode = allow_unicode
if self.allow_unicode:
self.default_validators = [validators.validate_unicode_slug]
- super().__init__(*args, **kwargs)
+ super().__init__(*args, max_length=max_length, db_index=db_index, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index dd84d780fb..cf39de7287 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -922,15 +922,14 @@ class ForeignKey(ForeignObject):
if self.remote_field.field_name is None:
self.remote_field.field_name = cls._meta.pk.name
- def formfield(self, **kwargs):
- db = kwargs.pop('using', None)
+ def formfield(self, *, using=None, **kwargs):
if isinstance(self.remote_field.model, str):
raise ValueError("Cannot create form field for %r yet, because "
"its related model %r has not been loaded yet" %
(self.name, self.remote_field.model))
defaults = {
'form_class': forms.ModelChoiceField,
- 'queryset': self.remote_field.model._default_manager.using(db),
+ 'queryset': self.remote_field.model._default_manager.using(using),
'to_field_name': self.remote_field.field_name,
}
defaults.update(kwargs)
@@ -1609,11 +1608,10 @@ class ManyToManyField(RelatedField):
def save_form_data(self, instance, data):
getattr(instance, self.attname).set(data)
- def formfield(self, **kwargs):
- db = kwargs.pop('using', None)
+ def formfield(self, *, using=None, **kwargs):
defaults = {
'form_class': forms.ModelMultipleChoiceField,
- 'queryset': self.remote_field.model._default_manager.using(db),
+ 'queryset': self.remote_field.model._default_manager.using(using),
}
defaults.update(kwargs)
# If initial is passed in, it's a list of related objects, but the
diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py
index b3e87cd482..5899a2324c 100644
--- a/django/db/models/fields/related_descriptors.py
+++ b/django/db/models/fields/related_descriptors.py
@@ -510,10 +510,8 @@ def create_reverse_many_to_one_manager(superclass, rel):
self.core_filters = {self.field.name: instance}
- def __call__(self, **kwargs):
- # We use **kwargs rather than a kwarg argument to enforce the
- # `manager='manager_name'` syntax.
- manager = getattr(self.model, kwargs.pop('manager'))
+ def __call__(self, *, manager):
+ manager = getattr(self.model, manager)
manager_class = create_reverse_many_to_one_manager(manager.__class__, rel)
return manager_class(self.instance)
do_not_call_in_templates = True
@@ -569,9 +567,8 @@ def create_reverse_many_to_one_manager(superclass, rel):
cache_name = self.field.related_query_name()
return queryset, rel_obj_attr, instance_attr, False, cache_name
- def add(self, *objs, **kwargs):
+ def add(self, *objs, bulk=True):
self._remove_prefetched_objects()
- bulk = kwargs.pop('bulk', True)
objs = list(objs)
db = router.db_for_write(self.model, instance=self.instance)
@@ -622,10 +619,9 @@ def create_reverse_many_to_one_manager(superclass, rel):
# remove() and clear() are only provided if the ForeignKey can have a value of null.
if rel.field.null:
- def remove(self, *objs, **kwargs):
+ def remove(self, *objs, bulk=True):
if not objs:
return
- bulk = kwargs.pop('bulk', True)
val = self.field.get_foreign_related_value(self.instance)
old_ids = set()
for obj in objs:
@@ -639,8 +635,7 @@ def create_reverse_many_to_one_manager(superclass, rel):
self._clear(self.filter(pk__in=old_ids), bulk)
remove.alters_data = True
- def clear(self, **kwargs):
- bulk = kwargs.pop('bulk', True)
+ def clear(self, *, bulk=True):
self._clear(self, bulk)
clear.alters_data = True
@@ -658,14 +653,11 @@ def create_reverse_many_to_one_manager(superclass, rel):
obj.save(update_fields=[self.field.name])
_clear.alters_data = True
- def set(self, objs, **kwargs):
+ def set(self, objs, *, bulk=True, clear=False):
# Force evaluation of `objs` in case it's a queryset whose value
# could be affected by `manager.clear()`. Refs #19816.
objs = tuple(objs)
- bulk = kwargs.pop('bulk', True)
- clear = kwargs.pop('clear', False)
-
if self.field.null:
db = router.db_for_write(self.model, instance=self.instance)
with transaction.atomic(using=db, savepoint=False):
@@ -791,10 +783,8 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
"a many-to-many relationship can be used." %
instance.__class__.__name__)
- def __call__(self, **kwargs):
- # We use **kwargs rather than a kwarg argument to enforce the
- # `manager='manager_name'` syntax.
- manager = getattr(self.model, kwargs.pop('manager'))
+ def __call__(self, *, manager):
+ manager = getattr(self.model, manager)
manager_class = create_forward_many_to_many_manager(manager.__class__, rel, reverse)
return manager_class(instance=self.instance)
do_not_call_in_templates = True
@@ -924,7 +914,7 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
)
clear.alters_data = True
- def set(self, objs, **kwargs):
+ def set(self, objs, *, clear=False):
if not rel.through._meta.auto_created:
opts = self.through._meta
raise AttributeError(
@@ -937,8 +927,6 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
# could be affected by `manager.clear()`. Refs #19816.
objs = tuple(objs)
- clear = kwargs.pop('clear', False)
-
db = router.db_for_write(self.through, instance=self.instance)
with transaction.atomic(using=db, savepoint=False):
if clear:
diff --git a/django/db/models/functions/base.py b/django/db/models/functions/base.py
index e9bf01ff0d..905f740a6c 100644
--- a/django/db/models/functions/base.py
+++ b/django/db/models/functions/base.py
@@ -165,9 +165,8 @@ class Length(Transform):
function = 'LENGTH'
lookup_name = 'length'
- def __init__(self, expression, **extra):
- output_field = extra.pop('output_field', fields.IntegerField())
- super().__init__(expression, output_field=output_field, **extra)
+ def __init__(self, expression, *, output_field=None, **extra):
+ super().__init__(expression, output_field=output_field or fields.IntegerField(), **extra)
def as_mysql(self, compiler, connection):
return super().as_sql(compiler, connection, function='CHAR_LENGTH')
diff --git a/django/db/models/query.py b/django/db/models/query.py
index dcb1360054..244cfaf164 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -691,11 +691,7 @@ class QuerySet:
clone._iterable_class = ValuesIterable
return clone
- def values_list(self, *fields, **kwargs):
- flat = kwargs.pop('flat', False)
- if kwargs:
- raise TypeError('Unexpected keyword arguments to values_list: %s' % (list(kwargs),))
-
+ def values_list(self, *fields, flat=False):
if flat and len(fields) > 1:
raise TypeError("'flat' is not valid when values_list is called with more than one field.")
@@ -812,7 +808,7 @@ class QuerySet:
else:
return self._filter_or_exclude(None, **filter_obj)
- def _combinator_query(self, combinator, *other_qs, **kwargs):
+ def _combinator_query(self, combinator, *other_qs, all=False):
# Clone the query to inherit the select list and everything
clone = self._clone()
# Clear limits and ordering so they can be reapplied
@@ -820,18 +816,11 @@ class QuerySet:
clone.query.clear_limits()
clone.query.combined_queries = (self.query,) + tuple(qs.query for qs in other_qs)
clone.query.combinator = combinator
- clone.query.combinator_all = kwargs.pop('all', False)
+ clone.query.combinator_all = all
return clone
- def union(self, *other_qs, **kwargs):
- if kwargs:
- unexpected_kwarg = next((k for k in kwargs.keys() if k != 'all'), None)
- if unexpected_kwarg:
- raise TypeError(
- "union() received an unexpected keyword argument '%s'" %
- (unexpected_kwarg,)
- )
- return self._combinator_query('union', *other_qs, **kwargs)
+ def union(self, *other_qs, all=False):
+ return self._combinator_query('union', *other_qs, all=all)
def intersection(self, *other_qs):
return self._combinator_query('intersection', *other_qs)
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 979a13835d..13899c3ab1 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -541,9 +541,9 @@ class FileField(Field):
'contradiction': _('Please either submit a file or check the clear checkbox, not both.')
}
- def __init__(self, *args, **kwargs):
- self.max_length = kwargs.pop('max_length', None)
- self.allow_empty_file = kwargs.pop('allow_empty_file', False)
+ def __init__(self, *args, max_length=None, allow_empty_file=False, **kwargs):
+ self.max_length = max_length
+ self.allow_empty_file = allow_empty_file
super().__init__(*args, **kwargs)
def to_python(self, data):
@@ -821,9 +821,9 @@ class ChoiceField(Field):
class TypedChoiceField(ChoiceField):
- def __init__(self, *args, **kwargs):
- self.coerce = kwargs.pop('coerce', lambda val: val)
- self.empty_value = kwargs.pop('empty_value', '')
+ def __init__(self, *args, coerce=lambda val: val, empty_value='', **kwargs):
+ self.coerce = coerce
+ self.empty_value = empty_value
super().__init__(*args, **kwargs)
def _coerce(self, value):
@@ -890,8 +890,8 @@ class MultipleChoiceField(ChoiceField):
class TypedMultipleChoiceField(MultipleChoiceField):
- def __init__(self, *args, **kwargs):
- self.coerce = kwargs.pop('coerce', lambda val: val)
+ def __init__(self, *args, coerce=lambda val: val, **kwargs):
+ self.coerce = coerce
self.empty_value = kwargs.pop('empty_value', [])
super().__init__(*args, **kwargs)
@@ -971,8 +971,8 @@ class MultiValueField(Field):
'incomplete': _('Enter a complete value.'),
}
- def __init__(self, fields=(), *args, **kwargs):
- self.require_all_fields = kwargs.pop('require_all_fields', True)
+ def __init__(self, fields=(), *args, require_all_fields=True, **kwargs):
+ self.require_all_fields = require_all_fields
super().__init__(*args, **kwargs)
for f in fields:
f.error_messages.setdefault('incomplete',
@@ -1174,8 +1174,8 @@ class GenericIPAddressField(CharField):
class SlugField(CharField):
default_validators = [validators.validate_slug]
- def __init__(self, *args, **kwargs):
- self.allow_unicode = kwargs.pop('allow_unicode', False)
+ def __init__(self, *args, allow_unicode=False, **kwargs):
+ self.allow_unicode = allow_unicode
if self.allow_unicode:
self.default_validators = [validators.validate_unicode_slug]
super().__init__(*args, **kwargs)
diff --git a/django/forms/models.py b/django/forms/models.py
index a95f281b45..0368839415 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -553,9 +553,9 @@ class BaseModelFormSet(BaseFormSet):
unique_fields = set()
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
- queryset=None, **kwargs):
+ queryset=None, *, initial=None, **kwargs):
self.queryset = queryset
- self.initial_extra = kwargs.pop('initial', None)
+ self.initial_extra = initial
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
defaults.update(kwargs)
super().__init__(**defaults)
@@ -1065,10 +1065,10 @@ class InlineForeignKeyField(Field):
'invalid_choice': _('The inline foreign key did not match the parent instance primary key.'),
}
- def __init__(self, parent_instance, *args, **kwargs):
+ def __init__(self, parent_instance, *args, pk_field=False, to_field=None, **kwargs):
self.parent_instance = parent_instance
- self.pk_field = kwargs.pop("pk_field", False)
- self.to_field = kwargs.pop("to_field", None)
+ self.pk_field = pk_field
+ self.to_field = to_field
if self.parent_instance is not None:
if self.to_field:
kwargs["initial"] = getattr(self.parent_instance, self.to_field)
diff --git a/django/shortcuts.py b/django/shortcuts.py
index b27a75206f..04e2f3e103 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -30,7 +30,7 @@ def render(request, template_name, context=None, content_type=None, status=None,
return HttpResponse(content, content_type, status)
-def redirect(to, *args, **kwargs):
+def redirect(to, *args, permanent=False, **kwargs):
"""
Returns an HttpResponseRedirect to the appropriate URL for the arguments
passed.
@@ -47,11 +47,7 @@ def redirect(to, *args, **kwargs):
By default issues a temporary redirect; pass permanent=True to issue a
permanent redirect
"""
- if kwargs.pop('permanent', False):
- redirect_class = HttpResponsePermanentRedirect
- else:
- redirect_class = HttpResponseRedirect
-
+ redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py
index 6a45b8c985..a0b0de54d0 100644
--- a/django/template/loader_tags.py
+++ b/django/template/loader_tags.py
@@ -157,10 +157,10 @@ class ExtendsNode(Node):
class IncludeNode(Node):
context_key = '__include_context'
- def __init__(self, template, *args, **kwargs):
+ def __init__(self, template, *args, extra_context=None, isolated_context=False, **kwargs):
self.template = template
- self.extra_context = kwargs.pop('extra_context', {})
- self.isolated_context = kwargs.pop('isolated_context', False)
+ self.extra_context = extra_context or {}
+ self.isolated_context = isolated_context
super().__init__(*args, **kwargs)
def render(self, context):
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 4c1d778795..0f879d4222 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -929,8 +929,7 @@ class TransactionTestCase(SimpleTestCase):
"against more than one ordered values")
return self.assertEqual(list(items), values, msg=msg)
- def assertNumQueries(self, num, func=None, *args, **kwargs):
- using = kwargs.pop("using", DEFAULT_DB_ALIAS)
+ def assertNumQueries(self, num, func=None, *args, using=DEFAULT_DB_ALIAS, **kwargs):
conn = connections[using]
context = _AssertNumQueriesContext(self, num, conn)
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 8e64328a2c..c15cb5eb49 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -235,12 +235,7 @@ class ImmutableList(tuple):
AttributeError: You cannot mutate this.
"""
- def __new__(cls, *args, **kwargs):
- if 'warning' in kwargs:
- warning = kwargs['warning']
- del kwargs['warning']
- else:
- warning = 'ImmutableList object is immutable.'
+ def __new__(cls, *args, warning='ImmutableList object is immutable.', **kwargs):
self = tuple.__new__(cls, *args, **kwargs)
self.warning = warning
return self
diff --git a/django/utils/deconstruct.py b/django/utils/deconstruct.py
index 6bc70f7e53..c546fc1dea 100644
--- a/django/utils/deconstruct.py
+++ b/django/utils/deconstruct.py
@@ -3,15 +3,13 @@ from importlib import import_module
from django.utils.version import get_docs_version
-def deconstructible(*args, **kwargs):
+def deconstructible(*args, path=None):
"""
Class decorator that allow the decorated class to be serialized
by the migrations subsystem.
Accepts an optional kwarg `path` to specify the import path.
"""
- path = kwargs.pop('path', None)
-
def decorator(klass):
def __new__(cls, *args, **kwargs):
# We capture the arguments to make returning them trivial
@@ -54,4 +52,4 @@ def deconstructible(*args, **kwargs):
if not args:
return decorator
- return decorator(*args, **kwargs)
+ return decorator(*args)
diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py
index 18238aaae7..7c5d157ea5 100644
--- a/django/views/decorators/cache.py
+++ b/django/views/decorators/cache.py
@@ -5,7 +5,7 @@ from django.utils.cache import add_never_cache_headers, patch_cache_control
from django.utils.decorators import decorator_from_middleware_with_args
-def cache_page(*args, **kwargs):
+def cache_page(timeout, *, cache=None, key_prefix=None):
"""
Decorator for views that tries getting the page from the cache and
populates the cache if the page isn't in the cache yet.
@@ -19,18 +19,8 @@ def cache_page(*args, **kwargs):
Additionally, all headers from the response's Vary header will be taken
into account on caching -- just like the middleware does.
"""
- # We also add some asserts to give better error messages in case people are
- # using other ways to call cache_page that no longer work.
- if len(args) != 1 or callable(args[0]):
- raise TypeError("cache_page has a single mandatory positional argument: timeout")
- cache_timeout = args[0]
- cache_alias = kwargs.pop('cache', None)
- key_prefix = kwargs.pop('key_prefix', None)
- if kwargs:
- raise TypeError("cache_page has two optional keyword arguments: cache and key_prefix")
-
return decorator_from_middleware_with_args(CacheMiddleware)(
- cache_timeout=cache_timeout, cache_alias=cache_alias, key_prefix=key_prefix
+ cache_timeout=timeout, cache_alias=cache, key_prefix=key_prefix
)
diff --git a/django/views/generic/list.py b/django/views/generic/list.py
index 39dc856e55..61320fccbe 100644
--- a/django/views/generic/list.py
+++ b/django/views/generic/list.py
@@ -120,11 +120,11 @@ class MultipleObjectMixin(ContextMixin):
else:
return None
- def get_context_data(self, **kwargs):
+ def get_context_data(self, *, object_list=None, **kwargs):
"""
Get the context for this view.
"""
- queryset = kwargs.pop('object_list', self.object_list)
+ queryset = object_list if object_list is not None else self.object_list
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size: