Skip to content

Instantly share code, notes, and snippets.

@loic
Created August 3, 2013 08:15
Show Gist options
  • Save loic/6145691 to your computer and use it in GitHub Desktop.
Save loic/6145691 to your computer and use it in GitHub Desktop.
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 0b941df..39700dd 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1,3 +1,4 @@
+from collections import OrderedDict
import copy
import operator
from functools import partial, reduce, update_wrapper
@@ -29,7 +30,6 @@ from django.http.response import HttpResponseBase
from django.shortcuts import get_object_or_404
from django.template.response import SimpleTemplateResponse, TemplateResponse
from django.utils.decorators import method_decorator
-from django.utils.datastructures import SortedDict
from django.utils.html import escape, escapejs
from django.utils.safestring import mark_safe
from django.utils import six
@@ -671,7 +671,7 @@ class ModelAdmin(BaseModelAdmin):
# want *any* actions enabled on this page.
from django.contrib.admin.views.main import _is_changelist_popup
if self.actions is None or _is_changelist_popup(request):
- return SortedDict()
+ return OrderedDict()
actions = []
@@ -692,8 +692,8 @@ class ModelAdmin(BaseModelAdmin):
# get_action might have returned None, so filter any of those out.
actions = filter(None, actions)
- # Convert the actions into a SortedDict keyed by name.
- actions = SortedDict([
+ # Convert the actions into an OrderedDict keyed by name.
+ actions = OrderedDict([
(name, (func, name, desc))
for func, name, desc in actions
])
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index f766031..3325747 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -1,3 +1,4 @@
+from collections import OrderedDict
import sys
import warnings
@@ -7,7 +8,6 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.utils import six
-from django.utils.datastructures import SortedDict
from django.utils.deprecation import RenameMethodsBase
from django.utils.encoding import force_str, force_text
from django.utils.translation import ugettext, ugettext_lazy
@@ -319,13 +319,13 @@ class ChangeList(six.with_metaclass(RenameChangeListMethods)):
def get_ordering_field_columns(self):
"""
- Returns a SortedDict of ordering field column numbers and asc/desc
+ Returns an OrderedDict 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 = SortedDict()
+ ordering_fields = OrderedDict()
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/forms.py b/django/contrib/auth/forms.py
index e3f03cc..c5c2db4 100644
--- a/django/contrib/auth/forms.py
+++ b/django/contrib/auth/forms.py
@@ -1,9 +1,10 @@
from __future__ import unicode_literals
+from collections import OrderedDict
+
from django import forms
from django.forms.util import flatatt
from django.template import loader
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_bytes
from django.utils.html import format_html, format_html_join
from django.utils.http import urlsafe_base64_encode
@@ -324,7 +325,7 @@ class PasswordChangeForm(SetPasswordForm):
)
return old_password
-PasswordChangeForm.base_fields = SortedDict([
+PasswordChangeForm.base_fields = OrderedDict([
(k, PasswordChangeForm.base_fields[k])
for k in ['old_password', 'new_password1', 'new_password2']
])
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 45ebc0f..06aec64 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -2,13 +2,13 @@ from __future__ import unicode_literals
import base64
import binascii
+from collections import OrderedDict
import hashlib
import importlib
from django.dispatch import receiver
from django.conf import settings
from django.test.signals import setting_changed
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_bytes, force_str, force_text
from django.core.exceptions import ImproperlyConfigured
from django.utils.crypto import (
@@ -243,7 +243,7 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), algorithm),
(_('iterations'), iterations),
(_('salt'), mask_hash(salt)),
@@ -320,7 +320,7 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)
assert algorithm == self.algorithm
salt, checksum = data[:22], data[22:]
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), algorithm),
(_('work factor'), work_factor),
(_('salt'), mask_hash(salt)),
@@ -368,7 +368,7 @@ class SHA1PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), mask_hash(salt, show=2)),
(_('hash'), mask_hash(hash)),
@@ -396,7 +396,7 @@ class MD5PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), mask_hash(salt, show=2)),
(_('hash'), mask_hash(hash)),
@@ -429,7 +429,7 @@ class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
assert encoded.startswith('sha1$$')
hash = encoded[6:]
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), self.algorithm),
(_('hash'), mask_hash(hash)),
])
@@ -462,7 +462,7 @@ class UnsaltedMD5PasswordHasher(BasePasswordHasher):
return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), self.algorithm),
(_('hash'), mask_hash(encoded, show=3)),
])
@@ -496,7 +496,7 @@ class CryptPasswordHasher(BasePasswordHasher):
def safe_summary(self, encoded):
algorithm, salt, data = encoded.split('$', 2)
assert algorithm == self.algorithm
- return SortedDict([
+ return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), salt),
(_('hash'), mask_hash(data, show=3)),
diff --git a/django/contrib/formtools/wizard/views.py b/django/contrib/formtools/wizard/views.py
index c137f1a..8c3b825 100644
--- a/django/contrib/formtools/wizard/views.py
+++ b/django/contrib/formtools/wizard/views.py
@@ -1,3 +1,4 @@
+from collections import OrderedDict
import re
from django import forms
@@ -5,7 +6,6 @@ from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.forms import formsets, ValidationError
from django.views.generic import TemplateView
-from django.utils.datastructures import SortedDict
from django.utils.decorators import classonlymethod
from django.utils.translation import ugettext as _
from django.utils import six
@@ -158,7 +158,7 @@ class WizardView(TemplateView):
form_list = form_list or kwargs.pop('form_list',
getattr(cls, 'form_list', None)) or []
- computed_form_list = SortedDict()
+ computed_form_list = OrderedDict()
assert len(form_list) > 0, 'at least one form is needed'
@@ -206,7 +206,7 @@ class WizardView(TemplateView):
The form_list is always generated on the fly because condition methods
could use data from other (maybe previous forms).
"""
- form_list = SortedDict()
+ form_list = OrderedDict()
for form_key, form_class in six.iteritems(self.form_list):
# try to fetch the value from condition list, by default, the form
# gets passed to the new list.
@@ -498,9 +498,9 @@ class WizardView(TemplateView):
if step is None:
step = self.steps.current
form_list = self.get_form_list()
- key = form_list.keyOrder.index(step) + 1
- if len(form_list.keyOrder) > key:
- return form_list.keyOrder[key]
+ key = form_list.keys().index(step) + 1
+ if len(form_list.keys()) > key:
+ return form_list.keys()[key]
return None
def get_prev_step(self, step=None):
@@ -512,9 +512,9 @@ class WizardView(TemplateView):
if step is None:
step = self.steps.current
form_list = self.get_form_list()
- key = form_list.keyOrder.index(step) - 1
+ key = form_list.keys().index(step) - 1
if key >= 0:
- return form_list.keyOrder[key]
+ return form_list.keys()[key]
return None
def get_step_index(self, step=None):
@@ -524,7 +524,7 @@ class WizardView(TemplateView):
"""
if step is None:
step = self.steps.current
- return self.get_form_list().keyOrder.index(step)
+ return self.get_form_list().keys().index(step)
def get_context_data(self, form, **kwargs):
"""
diff --git a/django/contrib/staticfiles/finders.py b/django/contrib/staticfiles/finders.py
index 7d266d9..c4afe6f 100644
--- a/django/contrib/staticfiles/finders.py
+++ b/django/contrib/staticfiles/finders.py
@@ -1,8 +1,9 @@
import os
+from collections import OrderedDict
+
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import default_storage, Storage, FileSystemStorage
-from django.utils.datastructures import SortedDict
from django.utils.functional import empty, memoize, LazyObject
from django.utils.module_loading import import_by_path
from django.utils._os import safe_join
@@ -11,7 +12,7 @@ from django.utils import six
from django.contrib.staticfiles import utils
from django.contrib.staticfiles.storage import AppStaticStorage
-_finders = SortedDict()
+_finders = OrderedDict()
class BaseFinder(object):
@@ -47,7 +48,7 @@ class FileSystemFinder(BaseFinder):
# List of locations with static files
self.locations = []
# Maps dir paths to an appropriate storage instance
- self.storages = SortedDict()
+ self.storages = OrderedDict()
if not isinstance(settings.STATICFILES_DIRS, (list, tuple)):
raise ImproperlyConfigured(
"Your STATICFILES_DIRS setting is not a tuple or list; "
@@ -118,7 +119,7 @@ class AppDirectoriesFinder(BaseFinder):
# The list of apps that are handled
self.apps = []
# Mapping of app module paths to storage instances
- self.storages = SortedDict()
+ self.storages = OrderedDict()
if apps is None:
apps = settings.INSTALLED_APPS
for app in apps:
diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py
index 7c3de80..c1e9fa8 100644
--- a/django/contrib/staticfiles/management/commands/collectstatic.py
+++ b/django/contrib/staticfiles/management/commands/collectstatic.py
@@ -2,12 +2,12 @@ from __future__ import unicode_literals
import os
import sys
+from collections import OrderedDict
from optparse import make_option
from django.core.files.storage import FileSystemStorage
from django.core.management.base import CommandError, NoArgsCommand
from django.utils.encoding import smart_text
-from django.utils.datastructures import SortedDict
from django.utils.six.moves import input
from django.contrib.staticfiles import finders, storage
@@ -97,7 +97,7 @@ class Command(NoArgsCommand):
else:
handler = self.copy_file
- found_files = SortedDict()
+ found_files = OrderedDict()
for finder in finders.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 f6d0a37..a814533 100644
--- a/django/contrib/staticfiles/storage.py
+++ b/django/contrib/staticfiles/storage.py
@@ -1,5 +1,6 @@
from __future__ import unicode_literals
import hashlib
+from collections import OrderedDict
from importlib import import_module
import os
import posixpath
@@ -16,7 +17,6 @@ from django.core.cache import (get_cache, InvalidCacheBackendError,
from django.core.exceptions import ImproperlyConfigured
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage, get_storage_class
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_bytes, force_text
from django.utils.functional import LazyObject
from django.utils._os import upath
@@ -64,7 +64,7 @@ class CachedFilesMixin(object):
except InvalidCacheBackendError:
# Use the default backend
self.cache = default_cache
- self._patterns = SortedDict()
+ self._patterns = OrderedDict()
for extension, patterns in self.patterns:
for pattern in patterns:
if isinstance(pattern, (tuple, list)):
@@ -202,7 +202,7 @@ class CachedFilesMixin(object):
def post_process(self, paths, dry_run=False, **options):
"""
- Post process the given SortedDict of files (called from collectstatic).
+ Post process the given OrderedDict of files (called from collectstatic).
Processing is actually two separate operations:
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py
index 100c187..1676081 100644
--- a/django/core/management/commands/dumpdata.py
+++ b/django/core/management/commands/dumpdata.py
@@ -2,8 +2,8 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand, CommandError
from django.core import serializers
from django.db import router, DEFAULT_DB_ALIAS
-from django.utils.datastructures import SortedDict
+from collections import OrderedDict
from optparse import make_option
class Command(BaseCommand):
@@ -66,11 +66,11 @@ class Command(BaseCommand):
if len(app_labels) == 0:
if primary_keys:
raise CommandError("You can only use --pks option with one model")
- app_list = SortedDict((app, None) for app in get_apps() if app not in excluded_apps)
+ app_list = OrderedDict((app, None) for app in get_apps() if app 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 = SortedDict()
+ app_list = OrderedDict()
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 dc26bb1..2cfea02 100644
--- a/django/core/management/commands/inspectdb.py
+++ b/django/core/management/commands/inspectdb.py
@@ -1,12 +1,12 @@
from __future__ import unicode_literals
+from collections import OrderedDict
import keyword
import re
from optparse import make_option
from django.core.management.base import NoArgsCommand, CommandError
from django.db import connections, DEFAULT_DB_ALIAS
-from django.utils.datastructures import SortedDict
class Command(NoArgsCommand):
@@ -69,7 +69,7 @@ class Command(NoArgsCommand):
used_column_names = [] # Holds column names used in the table so far
for i, row in enumerate(connection.introspection.get_table_description(cursor, table_name)):
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
- extra_params = SortedDict() # Holds Field parameters such as 'db_column'.
+ extra_params = OrderedDict() # Holds Field parameters such as 'db_column'.
column_name = row[0]
is_relation = i in relations
@@ -193,7 +193,7 @@ class Command(NoArgsCommand):
description, this routine will return the given field type name, as
well as any additional keyword parameters and notes for the field.
"""
- field_params = SortedDict()
+ field_params = OrderedDict()
field_notes = []
try:
diff --git a/django/core/management/commands/syncdb.py b/django/core/management/commands/syncdb.py
index 7c8d8b5..d51699e 100644
--- a/django/core/management/commands/syncdb.py
+++ b/django/core/management/commands/syncdb.py
@@ -1,3 +1,4 @@
+from collections import OrderedDict
from importlib import import_module
from optparse import make_option
import itertools
@@ -9,7 +10,6 @@ from django.core.management.base import NoArgsCommand
from django.core.management.color import no_style
from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal, emit_pre_sync_signal
from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
-from django.utils.datastructures import SortedDict
class Command(NoArgsCommand):
@@ -76,7 +76,7 @@ class Command(NoArgsCommand):
return not ((converter(opts.db_table) in tables) or
(opts.auto_created and converter(opts.auto_created._meta.db_table) in tables))
- manifest = SortedDict(
+ manifest = OrderedDict(
(app_name, list(filter(model_installed, model_list)))
for app_name, model_list in all_models
)
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index e0bfb9d..f4c64f7 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -1,8 +1,8 @@
+from collections import OrderedDict
from operator import attrgetter
from django.db import connections, transaction, IntegrityError
from django.db.models import signals, sql
-from django.utils.datastructures import SortedDict
from django.utils import six
@@ -234,7 +234,7 @@ class Collector(object):
found = True
if not found:
return
- self.data = SortedDict([(model, self.data[model])
+ self.data = OrderedDict([(model, self.data[model])
for model in sorted_models])
def delete(self):
diff --git a/django/db/models/loading.py b/django/db/models/loading.py
index 8368203..e1f7b84 100644
--- a/django/db/models/loading.py
+++ b/django/db/models/loading.py
@@ -1,5 +1,6 @@
"Utilities for loading models and the modules that contain them."
+from collections import OrderedDict
import imp
from importlib import import_module
import os
@@ -7,7 +8,6 @@ import sys
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
-from django.utils.datastructures import SortedDict
from django.utils.module_loading import module_has_submodule
from django.utils._os import upath
from django.utils import six
@@ -17,6 +17,14 @@ __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
MODELS_MODULE_NAME = 'models'
+class ModelDict(OrderedDict):
+ '''
+ We need to special-case the deepcopy for this, as the keys are modules,
+ which can't be deep copied.
+ '''
+ def __deepcopy__(self, memo):
+ return self.__class__([(key, copy.deepcopy(value, memo))
+ for key, value in self.items()])
class UnavailableApp(Exception):
pass
@@ -31,14 +39,14 @@ class AppCache(object):
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531.
__shared_state = dict(
# Keys of app_store are the model modules for each application.
- app_store=SortedDict(),
+ app_store=ModelDict(),
# Mapping of installed app_labels to model modules for that app.
app_labels={},
# Mapping of app_labels to a dictionary of model names to model code.
# May contain apps that are not installed.
- app_models=SortedDict(),
+ app_models=ModelDict(),
# Mapping of app_labels to errors raised when trying to import the app.
app_errors={},
@@ -244,12 +252,12 @@ class AppCache(object):
if app_mod:
if app_mod in self.app_store:
app_list = [self.app_models.get(self._label_for(app_mod),
- SortedDict())]
+ ModelDict())]
else:
app_list = []
else:
if only_installed:
- app_list = [self.app_models.get(app_label, SortedDict())
+ app_list = [self.app_models.get(app_label, ModelDict())
for app_label in six.iterkeys(self.app_labels)]
else:
app_list = six.itervalues(self.app_models)
@@ -298,7 +306,7 @@ class AppCache(object):
# Store as 'name: model' pair in a dictionary
# in the app_models dictionary
model_name = model._meta.model_name
- model_dict = self.app_models.setdefault(app_label, SortedDict())
+ model_dict = self.app_models.setdefault(app_label, ModelDict())
if model_name in model_dict:
# The same model may be imported via different paths (e.g.
# appname.models and project.appname.models). We use the source
diff --git a/django/db/models/options.py b/django/db/models/options.py
index d072d67..95cefec 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -1,5 +1,6 @@
from __future__ import unicode_literals
+from collections import OrderedDict
import re
from bisect import bisect
import warnings
@@ -11,7 +12,6 @@ from django.db.models.fields.proxy import OrderWrt
from django.db.models.loading import get_models, app_cache_ready
from django.utils import six
from django.utils.functional import cached_property
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
from django.utils.translation import activate, deactivate_all, get_language, string_concat
@@ -58,7 +58,7 @@ class Options(object):
# concrete models, the concrete_model is always the class itself.
self.concrete_model = None
self.swappable = None
- self.parents = SortedDict()
+ self.parents = OrderedDict()
self.auto_created = False
# To handle various inheritance situations, we need to track where
@@ -332,7 +332,7 @@ class Options(object):
return list(six.iteritems(self._m2m_cache))
def _fill_m2m_cache(self):
- cache = SortedDict()
+ cache = OrderedDict()
for parent in self.parents:
for field, model in parent._meta.get_m2m_with_model():
if model:
@@ -474,7 +474,7 @@ class Options(object):
return [t for t in cache.items() if all(p(*t) for p in predicates)]
def _fill_related_objects_cache(self):
- cache = SortedDict()
+ cache = OrderedDict()
parent_list = self.get_parent_list()
for parent in self.parents:
for obj, model in parent._meta.get_all_related_objects_with_model(include_hidden=True):
@@ -519,7 +519,7 @@ class Options(object):
return list(six.iteritems(cache))
def _fill_related_many_to_many_cache(self):
- cache = SortedDict()
+ cache = OrderedDict()
parent_list = self.get_parent_list()
for parent in self.parents:
for obj, model in parent._meta.get_all_related_m2m_objects_with_model():
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index fa7ae51..de43120 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -7,9 +7,9 @@ databases). The abstraction barrier only works one way: this module has to know
all about the internals of models in order to get the information it needs.
"""
+from collections import OrderedDict
import copy
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_text
from django.utils.tree import Node
from django.utils import six
@@ -142,7 +142,7 @@ class Query(object):
self.select_related = False
# SQL aggregate-related attributes
- self.aggregates = SortedDict() # Maps alias -> SQL aggregate function
+ self.aggregates = OrderedDict() # Maps alias -> SQL aggregate function
self.aggregate_select_mask = None
self._aggregate_select_cache = None
@@ -152,7 +152,7 @@ class Query(object):
# These are for extensions. The contents are more or less appended
# verbatim to the appropriate clause.
- self.extra = SortedDict() # Maps col_alias -> (col_sql, params).
+ self.extra = OrderedDict() # Maps col_alias -> (col_sql, params).
self.extra_select_mask = None
self._extra_select_cache = None
@@ -741,7 +741,7 @@ class Query(object):
self.group_by = [relabel_column(col) for col in self.group_by]
self.select = [SelectInfo(relabel_column(s.col), s.field)
for s in self.select]
- self.aggregates = SortedDict(
+ self.aggregates = OrderedDict(
(key, relabel_column(col)) for key, col in self.aggregates.items())
# 2. Rename the alias in the internal table/alias datastructures.
@@ -795,7 +795,7 @@ class Query(object):
assert current < ord('Z')
prefix = chr(current + 1)
self.alias_prefix = prefix
- change_map = SortedDict()
+ change_map = OrderedDict()
for pos, alias in enumerate(self.tables):
if alias in exceptions:
continue
@@ -1638,7 +1638,7 @@ class Query(object):
# dictionary with their parameters in 'select_params' so that
# subsequent updates to the select dictionary also adjust the
# parameters appropriately.
- select_pairs = SortedDict()
+ select_pairs = OrderedDict()
if select_params:
param_iter = iter(select_params)
else:
@@ -1651,7 +1651,7 @@ class Query(object):
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 a SortedDict.
+ # 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)
@@ -1760,7 +1760,7 @@ class Query(object):
self._extra_select_cache = None
def _aggregate_select(self):
- """The SortedDict of aggregate columns that are not masked, and should
+ """The OrderedDict of aggregate columns that are not masked, and should
be used in the SELECT clause.
This result is cached for optimization purposes.
@@ -1768,7 +1768,7 @@ class Query(object):
if self._aggregate_select_cache is not None:
return self._aggregate_select_cache
elif self.aggregate_select_mask is not None:
- self._aggregate_select_cache = SortedDict([
+ self._aggregate_select_cache = OrderedDict([
(k, v) for k, v in self.aggregates.items()
if k in self.aggregate_select_mask
])
@@ -1781,7 +1781,7 @@ class Query(object):
if self._extra_select_cache is not None:
return self._extra_select_cache
elif self.extra_select_mask is not None:
- self._extra_select_cache = SortedDict([
+ self._extra_select_cache = OrderedDict([
(k, v) for k, v in self.extra.items()
if k in self.extra_select_mask
])
diff --git a/django/forms/forms.py b/django/forms/forms.py
index 31e51e7..9905eee 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -4,6 +4,7 @@ Form classes
from __future__ import unicode_literals
+from collections import OrderedDict
import copy
import warnings
@@ -11,7 +12,6 @@ from django.core.exceptions import ValidationError
from django.forms.fields import Field, FileField
from django.forms.util import flatatt, ErrorDict, ErrorList
from django.forms.widgets import Media, media_property, TextInput, Textarea
-from django.utils.datastructures import SortedDict
from django.utils.html import conditional_escape, format_html
from django.utils.encoding import smart_text, force_text, python_2_unicode_compatible
from django.utils.safestring import mark_safe
@@ -55,7 +55,7 @@ def get_declared_fields(bases, attrs, with_base_fields=True):
if hasattr(base, 'declared_fields'):
fields = list(six.iteritems(base.declared_fields)) + fields
- return SortedDict(fields)
+ return OrderedDict(fields)
class DeclarativeFieldsMetaclass(type):
"""
diff --git a/django/forms/models.py b/django/forms/models.py
index 83954b0..a5b82e5 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -5,6 +5,7 @@ and database field objects.
from __future__ import unicode_literals
+from collections import OrderedDict
import warnings
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS, FieldError
@@ -15,7 +16,6 @@ from django.forms.util import ErrorList
from django.forms.widgets import (SelectMultiple, HiddenInput,
MultipleHiddenInput, media_property, CheckboxSelectMultiple)
from django.utils.encoding import smart_text, force_text
-from django.utils.datastructures import SortedDict
from django.utils import six
from django.utils.text import get_text_list, capfirst
from django.utils.translation import ugettext_lazy as _, ugettext, string_concat
@@ -142,7 +142,7 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
formfield_callback=None, localized_fields=None,
labels=None, help_texts=None, error_messages=None):
"""
- Returns a ``SortedDict`` containing form fields for the given model.
+ Returns a ``OrderedDict`` containing form fields for the given model.
``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned fields.
@@ -199,9 +199,9 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
field_list.append((f.name, formfield))
else:
ignored.append(f.name)
- field_dict = SortedDict(field_list)
+ field_dict = OrderedDict(field_list)
if fields:
- field_dict = SortedDict(
+ 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)]
)
diff --git a/django/middleware/locale.py b/django/middleware/locale.py
index 4e0a475..cd5d2cc 100644
--- a/django/middleware/locale.py
+++ b/django/middleware/locale.py
@@ -1,12 +1,13 @@
"This is the locale selecting middleware that will look at accept headers"
+from collections import OrderedDict
+
from django.conf import settings
from django.core.urlresolvers import (is_valid_path, get_resolver,
LocaleRegexURLResolver)
from django.http import HttpResponseRedirect
from django.utils.cache import patch_vary_headers
from django.utils import translation
-from django.utils.datastructures import SortedDict
class LocaleMiddleware(object):
@@ -19,7 +20,7 @@ class LocaleMiddleware(object):
"""
def __init__(self):
- self._supported_languages = SortedDict(settings.LANGUAGES)
+ self._supported_languages = OrderedDict(settings.LANGUAGES)
self._is_language_prefix_patterns_used = False
for url_pattern in get_resolver(None).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 3b16383..41b6501 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -1,6 +1,6 @@
import copy
from django.utils import six
-
+import warnings
class MergeDict(object):
"""
@@ -124,6 +124,10 @@ class SortedDict(dict):
return instance
def __init__(self, data=None):
+ warnings.warn(
+ "SortedDict is deprecated and will be removed in Django 1.9."
+ PendingDeprecationWarning, stacklevel=2
+ )
if data is None or isinstance(data, dict):
data = data or []
super(SortedDict, self).__init__(data)
@@ -496,3 +500,4 @@ class DictWrapper(dict):
if use_func:
return self.func(value)
return value
+
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 91a73f1..11463d8 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -1,6 +1,7 @@
"""Translation helper functions."""
from __future__ import unicode_literals
+from collections import OrderedDict
import locale
import os
import re
@@ -10,7 +11,6 @@ from importlib import import_module
from threading import local
import warnings
-from django.utils.datastructures import SortedDict
from django.utils.encoding import force_str, force_text
from django.utils.functional import memoize
from django.utils._os import upath
@@ -369,7 +369,7 @@ def get_supported_language_variant(lang_code, supported=None, strict=False):
"""
if supported is None:
from django.conf import settings
- supported = SortedDict(settings.LANGUAGES)
+ supported = OrderedDict(settings.LANGUAGES)
if lang_code:
# if fr-CA is not supported, try fr-ca; if that fails, fallback to fr.
generic_lang_code = lang_code.split('-')[0]
@@ -396,7 +396,7 @@ def get_language_from_path(path, supported=None, strict=False):
"""
if supported is None:
from django.conf import settings
- supported = SortedDict(settings.LANGUAGES)
+ supported = OrderedDict(settings.LANGUAGES)
regex_match = language_code_prefix_re.match(path)
if not regex_match:
return None
@@ -418,7 +418,7 @@ def get_language_from_request(request, check_path=False):
"""
global _accepted
from django.conf import settings
- supported = SortedDict(settings.LANGUAGES)
+ supported = OrderedDict(settings.LANGUAGES)
if check_path:
lang_code = get_language_from_path(request.path_info, supported)
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index 3d6cd48..53eb8a3 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -423,6 +423,9 @@ these changes.
* FastCGI support via the ``runfcgi`` management command will be
removed. Please deploy your project using WSGI.
+* django.utils.datastructures.SortedDict will be removed. Use the built in
+ collections.OrderedDict instead.
+
2.0
---
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index c47a392..606f640 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -164,6 +164,12 @@ on all Python versions. Since ``unittest2`` became the standard library's
Python versions, this module isn't useful anymore. It has been deprecated. Use
:mod:`unittest` instead.
+``django.utils.datastructures.SortedDict``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As OrderedDict was added to the standard library's :mod:`collections` in
+Python 2.7, ``django.utils.datastructures.SortedDict`` has been deprecated.
+
Custom SQL location for models package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index 025fcd8..6e03b0d 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -1,5 +1,6 @@
from __future__ import unicode_literals
+from collections import OrderedDict
import datetime
from operator import attrgetter
import pickle
@@ -14,7 +15,6 @@ from django.db.models.sql.where import WhereNode, EverythingNode, NothingNode
from django.db.models.sql.datastructures import EmptyResultSet
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import str_prefix
-from django.utils.datastructures import SortedDict
from .models import (
Annotation, Article, Author, Celebrity, Child, Cover, Detail, DumbCategory,
@@ -499,7 +499,7 @@ class Queries1Tests(BaseQuerysetTest):
)
def test_ticket2902(self):
- # Parameters can be given to extra_select, *if* you use a SortedDict.
+ # Parameters can be given to extra_select, *if* you use an OrderedDict.
# (First we need to know which order the keys fall in "naturally" on
# your system, so we can put things in the wrong way around from
@@ -513,7 +513,7 @@ class Queries1Tests(BaseQuerysetTest):
# This slightly odd comparison works around the fact that PostgreSQL will
# return 'one' and 'two' as strings, not Unicode objects. It's a side-effect of
# using constants here and not a real concern.
- d = Item.objects.extra(select=SortedDict(s), select_params=params).values('a', 'b')[0]
+ d = Item.objects.extra(select=OrderedDict(s), select_params=params).values('a', 'b')[0]
self.assertEqual(d, {'a': 'one', 'b': 'two'})
# Order by the number of tags attached to an item.
@@ -1987,7 +1987,7 @@ class ValuesQuerysetTests(BaseQuerysetTest):
def test_extra_values(self):
# testing for ticket 14930 issues
- qs = Number.objects.extra(select=SortedDict([('value_plus_x', 'num+%s'),
+ qs = Number.objects.extra(select=OrderedDict([('value_plus_x', 'num+%s'),
('value_minus_x', 'num-%s')]),
select_params=(1, 2))
qs = qs.order_by('value_minus_x')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment