summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorNick Pope <nick.pope@flightdataservices.com>2019-02-05 11:22:08 +0000
committerTim Graham <timograham@gmail.com>2019-02-06 13:48:39 -0500
commit24b82cd201e21060fbc02117dc16d1702877a1f3 (patch)
tree7d36db9251700d0abf8fbf69399c8abc7fd9026a /django
parent21bb71ef0dcb86798edb0d8b21138bcc4b947590 (diff)
Fixed #30159 -- Removed unneeded use of OrderedDict.
Dicts preserve order since Python 3.6.
Diffstat (limited to 'django')
-rw-r--r--django/apps/registry.py15
-rw-r--r--django/contrib/admin/options.py14
-rw-r--r--django/contrib/admin/views/main.py5
-rw-r--r--django/contrib/auth/hashers.py91
-rw-r--r--django/contrib/staticfiles/finders.py5
-rw-r--r--django/contrib/staticfiles/management/commands/collectstatic.py3
-rw-r--r--django/contrib/staticfiles/storage.py15
-rw-r--r--django/core/management/__init__.py6
-rw-r--r--django/core/management/commands/dumpdata.py5
-rw-r--r--django/core/management/commands/inspectdb.py5
-rw-r--r--django/core/management/commands/migrate.py7
-rw-r--r--django/core/serializers/python.py5
-rw-r--r--django/core/serializers/pyyaml.py3
-rw-r--r--django/db/migrations/serializer.py40
-rw-r--r--django/db/migrations/state.py3
-rw-r--r--django/db/models/deletion.py7
-rw-r--r--django/db/models/options.py4
-rw-r--r--django/db/models/query.py8
-rw-r--r--django/db/models/sql/compiler.py4
-rw-r--r--django/db/models/sql/query.py73
-rw-r--r--django/forms/forms.py12
-rw-r--r--django/forms/models.py16
-rw-r--r--django/template/utils.py4
-rw-r--r--django/test/utils.py4
-rw-r--r--django/utils/datastructures.py4
-rw-r--r--django/utils/translation/trans_real.py5
-rw-r--r--django/utils/xmlutils.py3
27 files changed, 159 insertions, 207 deletions
diff --git a/django/apps/registry.py b/django/apps/registry.py
index 234a830fb9..408964a146 100644
--- a/django/apps/registry.py
+++ b/django/apps/registry.py
@@ -2,7 +2,7 @@ import functools
import sys
import threading
import warnings
-from collections import Counter, OrderedDict, defaultdict
+from collections import Counter, defaultdict
from functools import partial
from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
@@ -31,10 +31,10 @@ class Apps:
# and whether the registry has been populated. Since it isn't possible
# to reimport a module safely (it could reexecute initialization code)
# all_models is never overridden or reset.
- self.all_models = defaultdict(OrderedDict)
+ self.all_models = defaultdict(dict)
# Mapping of labels to AppConfig instances for installed apps.
- self.app_configs = OrderedDict()
+ self.app_configs = {}
# Stack of app_configs. Used to store the current state in
# set_available_apps and set_installed_apps.
@@ -316,10 +316,11 @@ class Apps:
)
self.stored_app_configs.append(self.app_configs)
- self.app_configs = OrderedDict(
- (label, app_config)
+ self.app_configs = {
+ label: app_config
for label, app_config in self.app_configs.items()
- if app_config.name in available)
+ if app_config.name in available
+ }
self.clear_cache()
def unset_available_apps(self):
@@ -347,7 +348,7 @@ class Apps:
if not self.ready:
raise AppRegistryNotReady("App registry isn't ready yet.")
self.stored_app_configs.append(self.app_configs)
- self.app_configs = OrderedDict()
+ self.app_configs = {}
self.apps_ready = self.models_ready = self.loading = self.ready = False
self.clear_cache()
self.populate(installed)
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index ab4aa6d93b..d170f2f291 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -2,7 +2,6 @@ import copy
import json
import operator
import re
-from collections import OrderedDict
from functools import partial, reduce, update_wrapper
from urllib.parse import quote as urlquote
@@ -682,10 +681,7 @@ class ModelAdmin(BaseModelAdmin):
exclude = exclude or None
# Remove declared form fields which are in readonly_fields.
- new_attrs = OrderedDict.fromkeys(
- f for f in readonly_fields
- if f in self.form.declared_fields
- )
+ new_attrs = dict.fromkeys(f for f in readonly_fields if f in self.form.declared_fields)
form = type(self.form.__name__, (self.form,), new_attrs)
defaults = {
@@ -886,13 +882,9 @@ class ModelAdmin(BaseModelAdmin):
# If self.actions is set to None that means actions are disabled on
# this page.
if self.actions is None or IS_POPUP_VAR in request.GET:
- return OrderedDict()
+ return {}
actions = self._filter_actions_by_permissions(request, self._get_base_actions())
- # Convert the actions into an OrderedDict keyed by name.
- return OrderedDict(
- (name, (func, name, desc))
- for func, name, desc in actions
- )
+ return {name: (func, name, desc) for func, name, desc in actions}
def get_action_choices(self, request, default_choices=BLANK_CHOICE_DASH):
"""
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 298e18c57e..978910df26 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -1,4 +1,3 @@
-from collections import OrderedDict
from datetime import datetime, timedelta
from django.conf import settings
@@ -361,12 +360,12 @@ class ChangeList:
def get_ordering_field_columns(self):
"""
- Return an OrderedDict of ordering field column numbers and asc/desc.
+ Return a dictionary of ordering field column numbers and asc/desc.
"""
# We must cope with more than one column having the same underlying sort
# field, so we base things on column numbers.
ordering = self._get_default_ordering()
- ordering_fields = OrderedDict()
+ ordering_fields = {}
if ORDER_VAR not in self.params:
# for ordering specified on ModelAdmin or model Meta, we don't know
# the right column numbers absolutely, because there might be more
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 04025ec7e4..34caa4eba9 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -4,7 +4,6 @@ import functools
import hashlib
import importlib
import warnings
-from collections import OrderedDict
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
@@ -256,12 +255,12 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('iterations'), iterations),
- (_('salt'), mask_hash(salt)),
- (_('hash'), mask_hash(hash)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('iterations'): iterations,
+ _('salt'): mask_hash(salt),
+ _('hash'): mask_hash(hash),
+ }
def must_update(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
@@ -330,16 +329,16 @@ class Argon2PasswordHasher(BasePasswordHasher):
(algorithm, variety, version, time_cost, memory_cost, parallelism,
salt, data) = self._decode(encoded)
assert algorithm == self.algorithm
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('variety'), variety),
- (_('version'), version),
- (_('memory cost'), memory_cost),
- (_('time cost'), time_cost),
- (_('parallelism'), parallelism),
- (_('salt'), mask_hash(salt)),
- (_('hash'), mask_hash(data)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('variety'): variety,
+ _('version'): version,
+ _('memory cost'): memory_cost,
+ _('time cost'): time_cost,
+ _('parallelism'): parallelism,
+ _('salt'): mask_hash(salt),
+ _('hash'): mask_hash(data),
+ }
def must_update(self, encoded):
(algorithm, variety, version, time_cost, memory_cost, parallelism,
@@ -426,12 +425,12 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)
assert algorithm == self.algorithm
salt, checksum = data[:22], data[22:]
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('work factor'), work_factor),
- (_('salt'), mask_hash(salt)),
- (_('checksum'), mask_hash(checksum)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('work factor'): work_factor,
+ _('salt'): mask_hash(salt),
+ _('checksum'): mask_hash(checksum),
+ }
def must_update(self, encoded):
algorithm, empty, algostr, rounds, data = encoded.split('$', 4)
@@ -486,11 +485,11 @@ class SHA1PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('salt'), mask_hash(salt, show=2)),
- (_('hash'), mask_hash(hash)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('salt'): mask_hash(salt, show=2),
+ _('hash'): mask_hash(hash),
+ }
def harden_runtime(self, password, encoded):
pass
@@ -517,11 +516,11 @@ class MD5PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('salt'), mask_hash(salt, show=2)),
- (_('hash'), mask_hash(hash)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('salt'): mask_hash(salt, show=2),
+ _('hash'): mask_hash(hash),
+ }
def harden_runtime(self, password, encoded):
pass
@@ -553,10 +552,10 @@ class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
assert encoded.startswith('sha1$$')
hash = encoded[6:]
- return OrderedDict([
- (_('algorithm'), self.algorithm),
- (_('hash'), mask_hash(hash)),
- ])
+ return {
+ _('algorithm'): self.algorithm,
+ _('hash'): mask_hash(hash),
+ }
def harden_runtime(self, password, encoded):
pass
@@ -589,10 +588,10 @@ class UnsaltedMD5PasswordHasher(BasePasswordHasher):
return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
- return OrderedDict([
- (_('algorithm'), self.algorithm),
- (_('hash'), mask_hash(encoded, show=3)),
- ])
+ return {
+ _('algorithm'): self.algorithm,
+ _('hash'): mask_hash(encoded, show=3),
+ }
def harden_runtime(self, password, encoded):
pass
@@ -627,11 +626,11 @@ class CryptPasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, data = encoded.split('$', 2)
assert algorithm == self.algorithm
- return OrderedDict([
- (_('algorithm'), algorithm),
- (_('salt'), salt),
- (_('hash'), mask_hash(data, show=3)),
- ])
+ return {
+ _('algorithm'): algorithm,
+ _('salt'): salt,
+ _('hash'): mask_hash(data, show=3),
+ }
def harden_runtime(self, password, encoded):
pass
diff --git a/django/contrib/staticfiles/finders.py b/django/contrib/staticfiles/finders.py
index 8d8f1cb983..53d31b9b1f 100644
--- a/django/contrib/staticfiles/finders.py
+++ b/django/contrib/staticfiles/finders.py
@@ -1,6 +1,5 @@
import functools
import os
-from collections import OrderedDict
from django.apps import apps
from django.conf import settings
@@ -54,7 +53,7 @@ class FileSystemFinder(BaseFinder):
# List of locations with static files
self.locations = []
# Maps dir paths to an appropriate storage instance
- self.storages = OrderedDict()
+ self.storages = {}
for root in settings.STATICFILES_DIRS:
if isinstance(root, (list, tuple)):
prefix, root = root
@@ -144,7 +143,7 @@ class AppDirectoriesFinder(BaseFinder):
# The list of apps that are handled
self.apps = []
# Mapping of app names to storage instances
- self.storages = OrderedDict()
+ self.storages = {}
app_configs = apps.get_app_configs()
if app_names:
app_names = set(app_names)
diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py
index cccaf1b9c2..238a30aa98 100644
--- a/django/contrib/staticfiles/management/commands/collectstatic.py
+++ b/django/contrib/staticfiles/management/commands/collectstatic.py
@@ -1,5 +1,4 @@
import os
-from collections import OrderedDict
from django.apps import apps
from django.contrib.staticfiles.finders import get_finders
@@ -100,7 +99,7 @@ class Command(BaseCommand):
else:
handler = self.copy_file
- found_files = OrderedDict()
+ found_files = {}
for finder in get_finders():
for path, storage in finder.list(self.ignore_patterns):
# Prefix the relative path if the source storage contains it
diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py
index e49febe611..130d6270bb 100644
--- a/django/contrib/staticfiles/storage.py
+++ b/django/contrib/staticfiles/storage.py
@@ -4,7 +4,6 @@ import os
import posixpath
import re
import warnings
-from collections import OrderedDict
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
from django.conf import settings
@@ -59,7 +58,7 @@ class HashedFilesMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self._patterns = OrderedDict()
+ self._patterns = {}
self.hashed_files = {}
for extension, patterns in self.patterns:
for pattern in patterns:
@@ -208,7 +207,7 @@ class HashedFilesMixin:
def post_process(self, paths, dry_run=False, **options):
"""
- Post process the given OrderedDict of files (called from collectstatic).
+ Post process the given dictionary of files (called from collectstatic).
Processing is actually two separate operations:
@@ -225,7 +224,7 @@ class HashedFilesMixin:
return
# where to store the new paths
- hashed_files = OrderedDict()
+ hashed_files = {}
# build a list of adjustable files
adjustable_paths = [
@@ -386,20 +385,20 @@ class ManifestFilesMixin(HashedFilesMixin):
def load_manifest(self):
content = self.read_manifest()
if content is None:
- return OrderedDict()
+ return {}
try:
- stored = json.loads(content, object_pairs_hook=OrderedDict)
+ stored = json.loads(content)
except json.JSONDecodeError:
pass
else:
version = stored.get('version')
if version == '1.0':
- return stored.get('paths', OrderedDict())
+ return stored.get('paths', {})
raise ValueError("Couldn't load manifest '%s' (version %s)" %
(self.manifest_name, self.manifest_version))
def post_process(self, *args, **kwargs):
- self.hashed_files = OrderedDict()
+ self.hashed_files = {}
yield from super().post_process(*args, **kwargs)
self.save_manifest()
diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
index e0c924bdac..b8f47fa4a4 100644
--- a/django/core/management/__init__.py
+++ b/django/core/management/__init__.py
@@ -2,7 +2,7 @@ import functools
import os
import pkgutil
import sys
-from collections import OrderedDict, defaultdict
+from collections import defaultdict
from difflib import get_close_matches
from importlib import import_module
@@ -339,8 +339,8 @@ class ManagementUtility:
# The exception will be raised later in the child process
# started by the autoreloader. Pretend it didn't happen by
# loading an empty list of applications.
- apps.all_models = defaultdict(OrderedDict)
- apps.app_configs = OrderedDict()
+ apps.all_models = defaultdict(dict)
+ apps.app_configs = {}
apps.apps_ready = apps.models_ready = apps.ready = True
# Remove options not compatible with the built-in runserver
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py
index 31df5ac244..ce936c5459 100644
--- a/django/core/management/commands/dumpdata.py
+++ b/django/core/management/commands/dumpdata.py
@@ -1,5 +1,4 @@
import warnings
-from collections import OrderedDict
from django.apps import apps
from django.core import serializers
@@ -87,14 +86,14 @@ class Command(BaseCommand):
if not app_labels:
if primary_keys:
raise CommandError("You can only use --pks option with one model")
- app_list = OrderedDict.fromkeys(
+ app_list = dict.fromkeys(
app_config for app_config in apps.get_app_configs()
if app_config.models_module is not None and app_config not in excluded_apps
)
else:
if len(app_labels) > 1 and primary_keys:
raise CommandError("You can only use --pks option with one model")
- app_list = OrderedDict()
+ app_list = {}
for label in app_labels:
try:
app_label, model_label = label.split('.')
diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py
index 92f010a064..92c2035877 100644
--- a/django/core/management/commands/inspectdb.py
+++ b/django/core/management/commands/inspectdb.py
@@ -1,6 +1,5 @@
import keyword
import re
-from collections import OrderedDict
from django.core.management.base import BaseCommand, CommandError
from django.db import DEFAULT_DB_ALIAS, connections
@@ -98,7 +97,7 @@ class Command(BaseCommand):
column_to_field_name = {} # Maps column names to names of model fields
for row in table_description:
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
- extra_params = OrderedDict() # Holds Field parameters such as 'db_column'.
+ extra_params = {} # Holds Field parameters such as 'db_column'.
column_name = row.name
is_relation = column_name in relations
@@ -232,7 +231,7 @@ class Command(BaseCommand):
description, this routine will return the given field type name, as
well as any additional keyword parameters and notes for the field.
"""
- field_params = OrderedDict()
+ field_params = {}
field_notes = []
try:
diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py
index c2d0c16816..551804a72e 100644
--- a/django/core/management/commands/migrate.py
+++ b/django/core/management/commands/migrate.py
@@ -1,5 +1,4 @@
import time
-from collections import OrderedDict
from importlib import import_module
from django.apps import apps
@@ -314,10 +313,10 @@ class Command(BaseCommand):
(opts.auto_created and converter(opts.auto_created._meta.db_table) in tables)
)
- manifest = OrderedDict(
- (app_name, list(filter(model_installed, model_list)))
+ manifest = {
+ app_name: list(filter(model_installed, model_list))
for app_name, model_list in all_models
- )
+ }
# Create the tables for each model
if self.verbosity >= 1:
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index 08739c98fc..5a5d8a7036 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -3,7 +3,6 @@ A Python "serializer". Doesn't do much serializing per se -- just converts to
and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for
other serializers.
"""
-from collections import OrderedDict
from django.apps import apps
from django.core.serializers import base
@@ -26,14 +25,14 @@ class Serializer(base.Serializer):
pass
def start_object(self, obj):
- self._current = OrderedDict()
+ self._current = {}
def end_object(self, obj):
self.objects.append(self.get_dump_object(obj))
self._current = None
def get_dump_object(self, obj):
- data = OrderedDict([('model', str(obj._meta))])
+ data = {'model': str(obj._meta)}
if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'):
data["pk"] = self._value_from_field(obj, obj._meta.pk)
data['fields'] = self._current
diff --git a/django/core/serializers/pyyaml.py b/django/core/serializers/pyyaml.py
index ed3d391d51..778c933584 100644
--- a/django/core/serializers/pyyaml.py
+++ b/django/core/serializers/pyyaml.py
@@ -34,6 +34,9 @@ class DjangoSafeDumper(SafeDumper):
DjangoSafeDumper.add_representer(decimal.Decimal, DjangoSafeDumper.represent_decimal)
DjangoSafeDumper.add_representer(collections.OrderedDict, DjangoSafeDumper.represent_ordered_dict)
+# Workaround to represent dictionaries in insertion order.
+# See https://github.com/yaml/pyyaml/pull/143.
+DjangoSafeDumper.add_representer(dict, DjangoSafeDumper.represent_ordered_dict)
class Serializer(PythonSerializer):
diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py
index ace0a860c4..239b17e974 100644
--- a/django/db/migrations/serializer.py
+++ b/django/db/migrations/serializer.py
@@ -8,7 +8,6 @@ import math
import re
import types
import uuid
-from collections import OrderedDict
from django.conf import SettingsReference
from django.db import models
@@ -273,25 +272,26 @@ class UUIDSerializer(BaseSerializer):
class Serializer:
- _registry = OrderedDict([
- (frozenset, FrozensetSerializer),
- (list, SequenceSerializer),
- (set, SetSerializer),
- (tuple, TupleSerializer),
- (dict, DictionarySerializer),
- (enum.Enum, EnumSerializer),
- (datetime.datetime, DatetimeDatetimeSerializer),
- ((datetime.date, datetime.timedelta, datetime.time), DateTimeSerializer),
- (SettingsReference, SettingsReferenceSerializer),
- (float, FloatSerializer),
- ((bool, int, type(None), bytes, str), BaseSimpleSerializer),
- (decimal.Decimal, DecimalSerializer),
- ((functools.partial, functools.partialmethod), FunctoolsPartialSerializer),
- ((types.FunctionType, types.BuiltinFunctionType, types.MethodType), FunctionTypeSerializer),
- (collections.abc.Iterable, IterableSerializer),
- ((COMPILED_REGEX_TYPE, RegexObject), RegexSerializer),
- (uuid.UUID, UUIDSerializer),
- ])
+ _registry = {
+ # Some of these are order-dependent.
+ frozenset: FrozensetSerializer,
+ list: SequenceSerializer,
+ set: SetSerializer,
+ tuple: TupleSerializer,
+ dict: DictionarySerializer,
+ enum.Enum: EnumSerializer,
+ datetime.datetime: DatetimeDatetimeSerializer,
+ (datetime.date, datetime.timedelta, datetime.time): DateTimeSerializer,
+ SettingsReference: SettingsReferenceSerializer,
+ float: FloatSerializer,
+ (bool, int, type(None), bytes, str): BaseSimpleSerializer,
+ decimal.Decimal: DecimalSerializer,
+ (functools.partial, functools.partialmethod): FunctoolsPartialSerializer,
+ (types.FunctionType, types.BuiltinFunctionType, types.MethodType): FunctionTypeSerializer,
+ collections.abc.Iterable: IterableSerializer,
+ (COMPILED_REGEX_TYPE, RegexObject): RegexSerializer,
+ uuid.UUID: UUIDSerializer,
+ }
@classmethod
def register(cls, type_, serializer):
diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py
index a20aa0bd4a..9b62edad1f 100644
--- a/django/db/migrations/state.py
+++ b/django/db/migrations/state.py
@@ -1,5 +1,4 @@
import copy
-from collections import OrderedDict
from contextlib import contextmanager
from django.apps import AppConfig
@@ -334,7 +333,7 @@ class StateApps(Apps):
if app_label not in self.app_configs:
self.app_configs[app_label] = AppConfigStub(app_label)
self.app_configs[app_label].apps = self
- self.app_configs[app_label].models = OrderedDict()
+ self.app_configs[app_label].models = {}
self.app_configs[app_label].models[model._meta.model_name] = model
self.do_pending_operations(model)
self.clear_cache()
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 0a1c0338c1..92fe4affb9 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -1,4 +1,4 @@
-from collections import Counter, OrderedDict
+from collections import Counter
from operator import attrgetter
from django.db import IntegrityError, connections, transaction
@@ -64,7 +64,7 @@ class Collector:
def __init__(self, using):
self.using = using
# Initially, {model: {instances}}, later values become lists.
- self.data = OrderedDict()
+ self.data = {}
self.field_updates = {} # {model: {(field, value): {instances}}}
# fast_deletes is a list of queryset-likes that can be deleted without
# fetching the objects into memory.
@@ -257,8 +257,7 @@ class Collector:
found = True
if not found:
return
- self.data = OrderedDict((model, self.data[model])
- for model in sorted_models)
+ self.data = {model: self.data[model] for model in sorted_models}
def delete(self):
# sort instance collections
diff --git a/django/db/models/options.py b/django/db/models/options.py
index b8b48cddac..fea65f7626 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -1,7 +1,7 @@
import copy
import inspect
from bisect import bisect
-from collections import OrderedDict, defaultdict
+from collections import defaultdict
from django.apps import apps
from django.conf import settings
@@ -117,7 +117,7 @@ class Options:
# concrete models, the concrete_model is always the class itself.
self.concrete_model = None
self.swappable = None
- self.parents = OrderedDict()
+ self.parents = {}
self.auto_created = False
# List of all lookups defined in ForeignKey 'limit_choices_to' options
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 5c2f352636..41225f2b1a 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -5,7 +5,7 @@ The main QuerySet implementation. This provides the public API for the ORM.
import copy
import operator
import warnings
-from collections import OrderedDict, namedtuple
+from collections import namedtuple
from functools import lru_cache
from itertools import chain
@@ -725,7 +725,7 @@ class QuerySet:
query = self.query.chain(sql.UpdateQuery)
query.add_update_values(kwargs)
# Clear any annotations so that they won't be present in subqueries.
- query._annotations = None
+ query.annotations = {}
with transaction.mark_for_rollback_on_error(using=self.db):
rows = query.get_compiler(self.db).execute_sql(CURSOR)
self._result_cache = None
@@ -744,7 +744,7 @@ class QuerySet:
query = self.query.chain(sql.UpdateQuery)
query.add_update_fields(values)
# Clear any annotations so that they won't be present in subqueries.
- query._annotations = None
+ query.annotations = {}
self._result_cache = None
return query.get_compiler(self.db).execute_sql(CURSOR)
_update.alters_data = True
@@ -1014,7 +1014,7 @@ class QuerySet:
with extra data or aggregations.
"""
self._validate_values_are_expressions(args + tuple(kwargs.values()), method_name='annotate')
- annotations = OrderedDict() # To preserve ordering of args
+ annotations = {}
for arg in args:
# The default_alias property may raise a TypeError.
try:
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index dd5a2e8c39..39ec6eacfc 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -317,7 +317,7 @@ class SQLCompiler:
), False))
continue
- if not self.query._extra or col not in self.query._extra:
+ if not self.query.extra or col not in self.query.extra:
# 'col' is of the form 'field' or 'field1__field2' or
# '-field1__field2__field', etc.
order_by.extend(self.find_ordering_name(
@@ -1438,7 +1438,7 @@ class SQLUpdateCompiler(SQLCompiler):
query = self.query.chain(klass=Query)
query.select_related = False
query.clear_ordering(True)
- query._extra = {}
+ query.extra = {}
query.select = []
query.add_fields([query.get_meta().pk.name])
super().pre_sql_setup()
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 675ff8c176..5574941ef5 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -8,7 +8,7 @@ all about the internals of models in order to get the information it needs.
"""
import difflib
import functools
-from collections import Counter, OrderedDict, namedtuple
+from collections import Counter, namedtuple
from collections.abc import Iterator, Mapping
from itertools import chain, count, product
from string import ascii_uppercase
@@ -152,7 +152,7 @@ class Query:
# types they are. The key is the alias of the joined table (possibly
# the table name) and the value is a Join-like object (see
# sql.datastructures.Join for more information).
- self.alias_map = OrderedDict()
+ self.alias_map = {}
# Sometimes the query contains references to aliases in outer queries (as
# a result of split_exclude). Correct alias quoting needs to know these
# aliases too.
@@ -199,10 +199,7 @@ class Query:
self.values_select = ()
# SQL annotation-related attributes
- # The _annotations will be an OrderedDict when used. Due to the cost
- # of creating OrderedDict this attribute is created lazily (in
- # self.annotations property).
- self._annotations = None # Maps alias -> Annotation Expression
+ self.annotations = {} # Maps alias -> Annotation Expression
self.annotation_select_mask = None
self._annotation_select_cache = None
@@ -213,9 +210,7 @@ class Query:
# These are for extensions. The contents are more or less appended
# verbatim to the appropriate clause.
- # The _extra attribute is an OrderedDict, lazily created similarly to
- # .annotations
- self._extra = None # Maps col_alias -> (col_sql, params).
+ self.extra = {} # Maps col_alias -> (col_sql, params).
self.extra_select_mask = None
self._extra_select_cache = None
@@ -234,18 +229,6 @@ class Query:
self.explain_options = {}
@property
- def extra(self):
- if self._extra is None:
- self._extra = OrderedDict()
- return self._extra
-
- @property
- def annotations(self):
- if self._annotations is None:
- self._annotations = OrderedDict()
- return self._annotations
-
- @property
def has_select_fields(self):
return bool(self.select or self.annotation_select_mask or self.extra_select_mask)
@@ -311,7 +294,7 @@ class Query:
obj.external_aliases = self.external_aliases.copy()
obj.table_map = self.table_map.copy()
obj.where = self.where.clone()
- obj._annotations = self._annotations.copy() if self._annotations is not None else None
+ obj.annotations = self.annotations.copy()
if self.annotation_select_mask is None:
obj.annotation_select_mask = None
else:
@@ -322,7 +305,7 @@ class Query:
# It will get re-populated in the cloned queryset the next time it's
# used.
obj._annotation_select_cache = None
- obj._extra = self._extra.copy() if self._extra is not None else None
+ obj.extra = self.extra.copy()
if self.extra_select_mask is None:
obj.extra_select_mask = None
else:
@@ -479,7 +462,7 @@ class Query:
outer_query = self
self.select = ()
self.default_cols = False
- self._extra = {}
+ self.extra = {}
outer_query.clear_ordering(True)
outer_query.clear_limits()
@@ -613,7 +596,7 @@ class Query:
# It would be nice to be able to handle this, but the queries don't
# really make sense (or return consistent value sets). Not worth
# the extra complexity when you can write a real query instead.
- if self._extra and rhs._extra:
+ if self.extra and rhs.extra:
raise ValueError("When merging querysets using 'or', you cannot have extra(select=…) on both sides.")
self.extra.update(rhs.extra)
extra_select_mask = set()
@@ -825,9 +808,9 @@ class Query:
if isinstance(self.group_by, tuple):
self.group_by = tuple([col.relabeled_clone(change_map) for col in self.group_by])
self.select = tuple([col.relabeled_clone(change_map) for col in self.select])
- self._annotations = self._annotations and OrderedDict(
- (key, col.relabeled_clone(change_map)) for key, col in self._annotations.items()
- )
+ self.annotations = self.annotations and {
+ key: col.relabeled_clone(change_map) for key, col in self.annotations.items()
+ }
# 2. Rename the alias in the internal table/alias datastructures.
for old_alias, new_alias in change_map.items():
@@ -887,11 +870,10 @@ class Query:
)
self.subq_aliases = self.subq_aliases.union([self.alias_prefix])
outer_query.subq_aliases = outer_query.subq_aliases.union(self.subq_aliases)
- change_map = OrderedDict()
- for pos, alias in enumerate(self.alias_map):
- new_alias = '%s%d' % (self.alias_prefix, pos)
- change_map[alias] = new_alias
- self.change_aliases(change_map)
+ self.change_aliases({
+ alias: '%s%d' % (self.alias_prefix, pos)
+ for pos, alias in enumerate(self.alias_map)
+ })
def get_initial_alias(self):
"""
@@ -1042,7 +1024,7 @@ class Query:
Solve the lookup type from the lookup (e.g.: 'foobar__id__icontains').
"""
lookup_splitted = lookup.split(LOOKUP_SEP)
- if self._annotations:
+ if self.annotations:
expression, expression_lookups = refs_expression(lookup_splitted, self.annotations)
if expression:
return expression_lookups, (), expression
@@ -1867,7 +1849,7 @@ class Query:
# dictionary with their parameters in 'select_params' so that
# subsequent updates to the select dictionary also adjust the
# parameters appropriately.
- select_pairs = OrderedDict()
+ select_pairs = {}
if select_params:
param_iter = iter(select_params)
else:
@@ -1881,7 +1863,6 @@ class Query:
entry_params.append(next(param_iter))
pos = entry.find("%s", pos + 2)
select_pairs[name] = (entry, entry_params)
- # This is order preserving, since self.extra_select is an OrderedDict.
self.extra.update(select_pairs)
if where or params:
self.where.add(ExtraWhere(where, params), AND)
@@ -1998,7 +1979,7 @@ class Query:
field_names = []
extra_names = []
annotation_names = []
- if not self._extra and not self._annotations:
+ if not self.extra and not self.annotations:
# Shortcut - if there are no extra or annotations, then
# the values() clause must be just field names.
field_names = list(fields)
@@ -2022,18 +2003,18 @@ class Query:
@property
def annotation_select(self):
"""
- Return the OrderedDict of aggregate columns that are not masked and
+ Return the dictionary of aggregate columns that are not masked and
should be used in the SELECT clause. Cache this result for performance.
"""
if self._annotation_select_cache is not None:
return self._annotation_select_cache
- elif not self._annotations:
+ elif not self.annotations:
return {}
elif self.annotation_select_mask is not None:
- self._annotation_select_cache = OrderedDict(
- (k, v) for k, v in self.annotations.items()
+ self._annotation_select_cache = {
+ k: v for k, v in self.annotations.items()
if k in self.annotation_select_mask
- )
+ }
return self._annotation_select_cache
else:
return self.annotations
@@ -2042,13 +2023,13 @@ class Query:
def extra_select(self):
if self._extra_select_cache is not None:
return self._extra_select_cache
- if not self._extra:
+ if not self.extra:
return {}
elif self.extra_select_mask is not None:
- self._extra_select_cache = OrderedDict(
- (k, v) for k, v in self.extra.items()
+ self._extra_select_cache = {
+ k: v for k, v in self.extra.items()
if k in self.extra_select_mask
- )
+ }
return self._extra_select_cache
else:
return self.extra
diff --git a/django/forms/forms.py b/django/forms/forms.py
index 51e6465539..0c49a94432 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -3,7 +3,6 @@ Form classes
"""
import copy
-from collections import OrderedDict
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
# BoundField is imported for backwards compatibility in Django 1.9
@@ -31,12 +30,12 @@ class DeclarativeFieldsMetaclass(MediaDefiningClass):
if isinstance(value, Field):
current_fields.append((key, value))
attrs.pop(key)
- attrs['declared_fields'] = OrderedDict(current_fields)
+ attrs['declared_fields'] = dict(current_fields)
new_class = super(DeclarativeFieldsMetaclass, mcs).__new__(mcs, name, bases, attrs)
# Walk through the MRO.
- declared_fields = OrderedDict()
+ declared_fields = {}
for base in reversed(new_class.__mro__):
# Collect fields from base class.
if hasattr(base, 'declared_fields'):
@@ -52,11 +51,6 @@ class DeclarativeFieldsMetaclass(MediaDefiningClass):
return new_class
- @classmethod
- def __prepare__(metacls, name, bases, **kwds):
- # Remember the order in which form fields are defined.
- return OrderedDict()
-
@html_safe
class BaseForm:
@@ -129,7 +123,7 @@ class BaseForm:
"""
if field_order is None:
return
- fields = OrderedDict()
+ fields = {}
for key in field_order:
try:
fields[key] = self.fields.pop(key)
diff --git a/django/forms/models.py b/django/forms/models.py
index fe8a67ed2b..d157c291ef 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -3,7 +3,6 @@ Helper functions for creating Form classes from Django models
and database field objects.
"""
-from collections import OrderedDict
from itertools import chain
from django.core.exceptions import (
@@ -105,7 +104,7 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
labels=None, help_texts=None, error_messages=None,
field_classes=None, *, apply_limit_choices_to=True):
"""
- Return an ``OrderedDict`` containing form fields for the given model.
+ Return a dictionary containing form fields for the given model.
``fields`` is an optional list of field names. If provided, return only the
named fields.
@@ -134,7 +133,7 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
``apply_limit_choices_to`` is a boolean indicating if limit_choices_to
should be applied to a field's queryset.
"""
- field_list = []
+ field_dict = {}
ignored = []
opts = model._meta
# Avoid circular import
@@ -178,15 +177,14 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
if formfield:
if apply_limit_choices_to:
apply_limit_choices_to_to_formfield(formfield)
- field_list.append((f.name, formfield))
+ field_dict[f.name] = formfield
else:
ignored.append(f.name)
- field_dict = OrderedDict(field_list)
if fields:
- field_dict = OrderedDict(
- [(f, field_dict.get(f)) for f in fields
- if ((not exclude) or (exclude and f not in exclude)) and (f not in ignored)]
- )
+ field_dict = {
+ f: field_dict.get(f) for f in fields
+ if (not exclude or f not in exclude) and f not in ignored
+ }
return field_dict
diff --git a/django/template/utils.py b/django/template/utils.py
index 5a6c414939..f4ed2750c2 100644
--- a/django/template/utils.py
+++ b/django/template/utils.py
@@ -1,5 +1,5 @@
import functools
-from collections import Counter, OrderedDict
+from collections import Counter
from pathlib import Path
from django.apps import apps
@@ -27,7 +27,7 @@ class EngineHandler:
if self._templates is None:
self._templates = settings.TEMPLATES
- templates = OrderedDict()
+ templates = {}
backend_names = []
for tpl in self._templates:
try:
diff --git a/django/test/utils.py b/django/test/utils.py
index 419180eed3..8bdcea77d7 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -1,4 +1,3 @@
-import collections
import logging
import re
import sys
@@ -280,8 +279,7 @@ def get_unique_databases_and_mirrors(aliases=None):
if alias != DEFAULT_DB_ALIAS and connection.creation.test_db_signature() != default_sig:
dependencies[alias] = test_settings.get('DEPENDENCIES', [DEFAULT_DB_ALIAS])
- test_databases = dependency_ordered(test_databases.items(), dependencies)
- test_databases = collections.OrderedDict(test_databases)
+ test_databases = dict(dependency_ordered(test_databases.items(), dependencies))
return test_databases, mirrored_aliases
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 191c2348f6..083cf3cb8b 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -1,16 +1,14 @@
import copy
-from collections import OrderedDict
from collections.abc import Mapping
class OrderedSet:
"""
A set which keeps the ordering of the inserted items.
- Currently backs onto OrderedDict.
"""
def __init__(self, iterable=None):
- self.dict = OrderedDict.fromkeys(iterable or ())
+ self.dict = dict.fromkeys(iterable or ())
def add(self, item):
self.dict[item] = None
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 0e53b223e5..d6f1f7f14f 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -5,7 +5,6 @@ import os
import re
import sys
import warnings
-from collections import OrderedDict
from threading import local
from django.apps import apps
@@ -385,9 +384,9 @@ def check_for_language(lang_code):
@functools.lru_cache()
def get_languages():
"""
- Cache of settings.LANGUAGES in an OrderedDict for easy lookups by key.
+ Cache of settings.LANGUAGES in a dictionary for easy lookups by key.
"""
- return OrderedDict(settings.LANGUAGES)
+ return dict(settings.LANGUAGES)
@functools.lru_cache(maxsize=1000)
diff --git a/django/utils/xmlutils.py b/django/utils/xmlutils.py
index 1a14034243..e4607b9865 100644
--- a/django/utils/xmlutils.py
+++ b/django/utils/xmlutils.py
@@ -3,7 +3,6 @@ Utilities for XML generation/parsing.
"""
import re
-from collections import OrderedDict
from xml.sax.saxutils import XMLGenerator
@@ -30,5 +29,5 @@ class SimplerXMLGenerator(XMLGenerator):
def startElement(self, name, attrs):
# Sort attrs for a deterministic output.
- sorted_attrs = OrderedDict(sorted(attrs.items())) if attrs else attrs
+ sorted_attrs = dict(sorted(attrs.items())) if attrs else attrs
super().startElement(name, sorted_attrs)