summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2014-11-19 12:22:23 -0500
committerTim Graham <timograham@gmail.com>2015-01-17 08:40:23 -0500
commitc820892eed9ea10879270e64e8109dc44829756a (patch)
tree3edb914f3eeac75acb72bc60a94b991f9b211902
parent41f0d3d3bc8b0a6831530e1176c6415f9ba45b0b (diff)
Removed django.utils.datastructures.SortedDict per deprecation timeline.
-rw-r--r--django/utils/datastructures.py125
-rw-r--r--docs/ref/utils.txt28
-rw-r--r--docs/releases/1.0-porting-guide.txt4
-rw-r--r--docs/releases/1.7.txt3
-rw-r--r--docs/topics/python3.txt2
-rw-r--r--tests/utils_tests/test_datastructures.py131
6 files changed, 6 insertions, 287 deletions
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 275f2a428a..6c60675d38 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -1,132 +1,7 @@
import copy
-import warnings
from collections import OrderedDict
from django.utils import six
-from django.utils.deprecation import RemovedInDjango19Warning
-
-
-class SortedDict(dict):
- """
- A dictionary that keeps its keys in the order in which they're inserted.
- """
- def __new__(cls, *args, **kwargs):
- instance = super(SortedDict, cls).__new__(cls, *args, **kwargs)
- instance.keyOrder = []
- return instance
-
- def __init__(self, data=None):
- warnings.warn(
- "SortedDict is deprecated and will be removed in Django 1.9.",
- RemovedInDjango19Warning, stacklevel=2
- )
- if data is None or isinstance(data, dict):
- data = data or []
- super(SortedDict, self).__init__(data)
- self.keyOrder = list(data) if data else []
- else:
- super(SortedDict, self).__init__()
- super_set = super(SortedDict, self).__setitem__
- for key, value in data:
- # Take the ordering from first key
- if key not in self:
- self.keyOrder.append(key)
- # But override with last value in data (dict() does this)
- super_set(key, value)
-
- def __deepcopy__(self, memo):
- return self.__class__([(key, copy.deepcopy(value, memo))
- for key, value in self.items()])
-
- def __copy__(self):
- # The Python's default copy implementation will alter the state
- # of self. The reason for this seems complex but is likely related to
- # subclassing dict.
- return self.copy()
-
- def __setitem__(self, key, value):
- if key not in self:
- self.keyOrder.append(key)
- super(SortedDict, self).__setitem__(key, value)
-
- def __delitem__(self, key):
- super(SortedDict, self).__delitem__(key)
- self.keyOrder.remove(key)
-
- def __iter__(self):
- return iter(self.keyOrder)
-
- def __reversed__(self):
- return reversed(self.keyOrder)
-
- def pop(self, k, *args):
- result = super(SortedDict, self).pop(k, *args)
- try:
- self.keyOrder.remove(k)
- except ValueError:
- # Key wasn't in the dictionary in the first place. No problem.
- pass
- return result
-
- def popitem(self):
- result = super(SortedDict, self).popitem()
- self.keyOrder.remove(result[0])
- return result
-
- def _iteritems(self):
- for key in self.keyOrder:
- yield key, self[key]
-
- def _iterkeys(self):
- for key in self.keyOrder:
- yield key
-
- def _itervalues(self):
- for key in self.keyOrder:
- yield self[key]
-
- if six.PY3:
- items = _iteritems
- keys = _iterkeys
- values = _itervalues
- else:
- iteritems = _iteritems
- iterkeys = _iterkeys
- itervalues = _itervalues
-
- def items(self):
- return [(k, self[k]) for k in self.keyOrder]
-
- def keys(self):
- return self.keyOrder[:]
-
- def values(self):
- return [self[k] for k in self.keyOrder]
-
- def update(self, dict_):
- for k, v in six.iteritems(dict_):
- self[k] = v
-
- def setdefault(self, key, default):
- if key not in self:
- self.keyOrder.append(key)
- return super(SortedDict, self).setdefault(key, default)
-
- def copy(self):
- """Returns a copy of this object."""
- # This way of initializing the copy means it works for subclasses, too.
- return self.__class__(self)
-
- def __repr__(self):
- """
- Replaces the normal dict.__repr__ with a version that returns the keys
- in their sorted order.
- """
- return '{%s}' % ', '.join('%r: %r' % (k, v) for k, v in six.iteritems(self))
-
- def clear(self):
- super(SortedDict, self).clear()
- self.keyOrder = []
class OrderedSet(object):
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 55184c277b..d1881bb830 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -97,34 +97,6 @@ need to distinguish caches by the ``Accept-language`` header.
cache, this just means that we have to build the response once to get at
the Vary header and so at the list of headers to use for the cache key.
-``django.utils.datastructures``
-===============================
-
-.. module:: django.utils.datastructures
- :synopsis: Data structures that aren't in Python's standard library.
-
-.. class:: SortedDict
-
-.. deprecated:: 1.7
- ``SortedDict`` is deprecated and will be removed in Django 1.9. Use
- :class:`collections.OrderedDict` instead.
-
- The :class:`django.utils.datastructures.SortedDict` class is a dictionary
- that keeps its keys in the order in which they're inserted.
-
-Creating a new SortedDict
--------------------------
-
-Creating a new ``SortedDict`` must be done in a way where ordering is
-guaranteed. For example::
-
- SortedDict({'b': 1, 'a': 2, 'c': 3})
-
-will not work. Passing in a basic Python ``dict`` could produce unreliable
-results. Instead do::
-
- SortedDict([('b', 1), ('a', 2), ('c', 3)])
-
``django.utils.dateparse``
==========================
diff --git a/docs/releases/1.0-porting-guide.txt b/docs/releases/1.0-porting-guide.txt
index a3c1a95702..a8b4ccaa26 100644
--- a/docs/releases/1.0-porting-guide.txt
+++ b/docs/releases/1.0-porting-guide.txt
@@ -714,12 +714,12 @@ Data structures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django.newforms.forms.SortedDictFromList`` was removed.
-:class:`django.utils.datastructures.SortedDict` can now be instantiated with
+``django.utils.datastructures.SortedDict`` can now be instantiated with
a sequence of tuples.
To update your code:
-1. Use :class:`django.utils.datastructures.SortedDict` wherever you were
+1. Use ``django.utils.datastructures.SortedDict`` wherever you were
using ``django.newforms.forms.SortedDictFromList``.
2. Because ``django.utils.datastructures.SortedDict.copy`` doesn't
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index b5888bc52a..2592d64983 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -1511,8 +1511,7 @@ Python versions, this module isn't useful anymore. It has been deprecated. Use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As :class:`~collections.OrderedDict` was added to the standard library in
-Python 2.7, :class:`~django.utils.datastructures.SortedDict` is no longer
-needed and has been deprecated.
+Python 2.7, ``SortedDict`` is no longer needed and has been deprecated.
Custom SQL location for models package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/topics/python3.txt b/docs/topics/python3.txt
index 2f12809163..5dc2cf464c 100644
--- a/docs/topics/python3.txt
+++ b/docs/topics/python3.txt
@@ -181,7 +181,7 @@ versions of Python.
:meth:`dict.keys`, :meth:`dict.items` and :meth:`dict.values` return lists in
Python 2 and iterators in Python 3. :class:`~django.http.QueryDict` and the
-:class:`dict`-like classes defined in :mod:`django.utils.datastructures`
+:class:`dict`-like classes defined in ``django.utils.datastructures``
behave likewise in Python 3.
six_ provides compatibility functions to work around this change:
diff --git a/tests/utils_tests/test_datastructures.py b/tests/utils_tests/test_datastructures.py
index fafb0cfdce..425186c578 100644
--- a/tests/utils_tests/test_datastructures.py
+++ b/tests/utils_tests/test_datastructures.py
@@ -3,140 +3,13 @@ Tests for stuff in django.utils.datastructures.
"""
import copy
-import pickle
-from django.test import SimpleTestCase, ignore_warnings
+from django.test import SimpleTestCase
from django.utils.datastructures import (DictWrapper, ImmutableList,
- MultiValueDict, MultiValueDictKeyError, OrderedSet, SortedDict)
-from django.utils.deprecation import RemovedInDjango19Warning
+ MultiValueDict, MultiValueDictKeyError, OrderedSet)
from django.utils import six
-@ignore_warnings(category=RemovedInDjango19Warning)
-class SortedDictTests(SimpleTestCase):
- def setUp(self):
- super(SortedDictTests, self).setUp()
- self.d1 = SortedDict()
- self.d1[7] = 'seven'
- self.d1[1] = 'one'
- self.d1[9] = 'nine'
-
- self.d2 = SortedDict()
- self.d2[1] = 'one'
- self.d2[9] = 'nine'
- self.d2[0] = 'nil'
- self.d2[7] = 'seven'
-
- def test_basic_methods(self):
- self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9])
- self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'one', 'nine'])
- self.assertEqual(list(six.iteritems(self.d1)), [(7, 'seven'), (1, 'one'), (9, 'nine')])
-
- def test_overwrite_ordering(self):
- """ Overwriting an item keeps its place. """
- self.d1[1] = 'ONE'
- self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'ONE', 'nine'])
-
- def test_append_items(self):
- """ New items go to the end. """
- self.d1[0] = 'nil'
- self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9, 0])
-
- def test_delete_and_insert(self):
- """
- Deleting an item, then inserting the same key again will place it
- at the end.
- """
- del self.d2[7]
- self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0])
- self.d2[7] = 'lucky number 7'
- self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0, 7])
-
- if six.PY2:
- def test_change_keys(self):
- """
- Changing the keys won't do anything, it's only a copy of the
- keys dict.
-
- This test doesn't make sense under Python 3 because keys is
- an iterator.
- """
- k = self.d2.keys()
- k.remove(9)
- self.assertEqual(self.d2.keys(), [1, 9, 0, 7])
-
- def test_init_keys(self):
- """
- Initialising a SortedDict with two keys will just take the first one.
-
- A real dict will actually take the second value so we will too, but
- we'll keep the ordering from the first key found.
- """
- tuples = ((2, 'two'), (1, 'one'), (2, 'second-two'))
- d = SortedDict(tuples)
-
- self.assertEqual(list(six.iterkeys(d)), [2, 1])
-
- real_dict = dict(tuples)
- self.assertEqual(sorted(six.itervalues(real_dict)), ['one', 'second-two'])
-
- # Here the order of SortedDict values *is* what we are testing
- self.assertEqual(list(six.itervalues(d)), ['second-two', 'one'])
-
- def test_overwrite(self):
- self.d1[1] = 'not one'
- self.assertEqual(self.d1[1], 'not one')
- self.assertEqual(list(six.iterkeys(self.d1)), list(six.iterkeys(self.d1.copy())))
-
- def test_append(self):
- self.d1[13] = 'thirteen'
- self.assertEqual(
- repr(self.d1),
- "{7: 'seven', 1: 'one', 9: 'nine', 13: 'thirteen'}"
- )
-
- def test_pop(self):
- self.assertEqual(self.d1.pop(1, 'missing'), 'one')
- self.assertEqual(self.d1.pop(1, 'missing'), 'missing')
-
- # We don't know which item will be popped in popitem(), so we'll
- # just check that the number of keys has decreased.
- l = len(self.d1)
- self.d1.popitem()
- self.assertEqual(l - len(self.d1), 1)
-
- def test_dict_equality(self):
- d = SortedDict((i, i) for i in range(3))
- self.assertEqual(d, {0: 0, 1: 1, 2: 2})
-
- def test_tuple_init(self):
- d = SortedDict(((1, "one"), (0, "zero"), (2, "two")))
- self.assertEqual(repr(d), "{1: 'one', 0: 'zero', 2: 'two'}")
-
- def test_pickle(self):
- self.assertEqual(
- pickle.loads(pickle.dumps(self.d1, 2)),
- {7: 'seven', 1: 'one', 9: 'nine'}
- )
-
- def test_copy(self):
- orig = SortedDict(((1, "one"), (0, "zero"), (2, "two")))
- copied = copy.copy(orig)
- self.assertEqual(list(six.iterkeys(orig)), [1, 0, 2])
- self.assertEqual(list(six.iterkeys(copied)), [1, 0, 2])
-
- def test_clear(self):
- self.d1.clear()
- self.assertEqual(self.d1, {})
- self.assertEqual(self.d1.keyOrder, [])
-
- def test_reversed(self):
- self.assertEqual(list(self.d1), [7, 1, 9])
- self.assertEqual(list(self.d2), [1, 9, 0, 7])
- self.assertEqual(list(reversed(self.d1)), [9, 1, 7])
- self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1])
-
-
class OrderedSetTests(SimpleTestCase):
def test_bool(self):