From 37b7776a015102e97b9bdd64d88c732883ff9989 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 18 Nov 2014 12:09:20 -0500 Subject: [PATCH] Removed django.utils.datastructures.MergeDict per deprecation timeline; refs #18659. --- django/forms/widgets.py | 6 +- django/utils/datastructures.py | 115 ----------------------- tests/forms_tests/tests/test_forms.py | 16 +--- tests/utils_tests/test_datastructures.py | 73 +------------- 4 files changed, 8 insertions(+), 202 deletions(-) diff --git a/django/forms/widgets.py b/django/forms/widgets.py index de75b35932..b0743b4778 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -9,7 +9,7 @@ from itertools import chain from django.conf import settings from django.forms.utils import flatatt, to_current_timezone -from django.utils.datastructures import MultiValueDict, MergeDict +from django.utils.datastructures import MultiValueDict from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.html import conditional_escape, format_html from django.utils.translation import ugettext_lazy @@ -319,7 +319,7 @@ class MultipleHiddenInput(HiddenInput): return mark_safe('\n'.join(inputs)) def value_from_datadict(self, data, files, name): - if isinstance(data, (MultiValueDict, MergeDict)): + if isinstance(data, MultiValueDict): return data.getlist(name) return data.get(name, None) @@ -587,7 +587,7 @@ class SelectMultiple(Select): return mark_safe('\n'.join(output)) def value_from_datadict(self, data, files, name): - if isinstance(data, (MultiValueDict, MergeDict)): + if isinstance(data, MultiValueDict): return data.getlist(name) return data.get(name, None) diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index 58108faa4b..275f2a428a 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -6,121 +6,6 @@ from django.utils import six from django.utils.deprecation import RemovedInDjango19Warning -class MergeDict(object): - """ - A simple class for creating new "virtual" dictionaries that actually look - up values in more than one dictionary, passed in the constructor. - - If a key appears in more than one of the given dictionaries, only the - first occurrence will be used. - """ - def __init__(self, *dicts): - warnings.warn('`MergeDict` is deprecated, use `dict.update()` ' - 'instead.', RemovedInDjango19Warning, 2) - self.dicts = dicts - - def __bool__(self): - return any(self.dicts) - - def __nonzero__(self): - return type(self).__bool__(self) - - def __getitem__(self, key): - for dict_ in self.dicts: - try: - return dict_[key] - except KeyError: - pass - raise KeyError(key) - - def __copy__(self): - return self.__class__(*self.dicts) - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - # This is used by MergeDicts of MultiValueDicts. - def getlist(self, key): - for dict_ in self.dicts: - if key in dict_: - return dict_.getlist(key) - return [] - - def _iteritems(self): - seen = set() - for dict_ in self.dicts: - for item in six.iteritems(dict_): - k = item[0] - if k in seen: - continue - seen.add(k) - yield item - - def _iterkeys(self): - for k, v in self._iteritems(): - yield k - - def _itervalues(self): - for k, v in self._iteritems(): - yield v - - if six.PY3: - items = _iteritems - keys = _iterkeys - values = _itervalues - else: - iteritems = _iteritems - iterkeys = _iterkeys - itervalues = _itervalues - - def items(self): - return list(self.iteritems()) - - def keys(self): - return list(self.iterkeys()) - - def values(self): - return list(self.itervalues()) - - def has_key(self, key): - for dict_ in self.dicts: - if key in dict_: - return True - return False - - __contains__ = has_key - - __iter__ = _iterkeys - - def copy(self): - """Returns a copy of this object.""" - return self.__copy__() - - def __str__(self): - ''' - Returns something like - - "{'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}" - - instead of the generic "" inherited from object. - ''' - return str(dict(self.items())) - - def __repr__(self): - ''' - Returns something like - - MergeDict({'key1': 'val1', 'key2': 'val2'}, {'key3': 'val3'}) - - instead of generic "" inherited from object. - ''' - dictreprs = ', '.join(repr(d) for d in self.dicts) - return '%s(%s)' % (self.__class__.__name__, dictreprs) - - class SortedDict(dict): """ A dictionary that keeps its keys in the order in which they're inserted. diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index c0ce912fe1..d938694e8f 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -18,10 +18,9 @@ from django.forms import ( from django.forms.utils import ErrorList from django.http import QueryDict from django.template import Template, Context -from django.test import TestCase, ignore_warnings +from django.test import TestCase from django.test.utils import str_prefix -from django.utils.datastructures import MultiValueDict, MergeDict -from django.utils.deprecation import RemovedInDjango19Warning +from django.utils.datastructures import MultiValueDict from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.safestring import mark_safe, SafeData @@ -552,11 +551,9 @@ class FormsTestCase(TestCase):
  • """) - @ignore_warnings(category=RemovedInDjango19Warning) # MergeDict deprecation def test_multiple_choice_list_data(self): - # Data for a MultipleChoiceField should be a list. QueryDict, MultiValueDict and - # MergeDict (when created as a merge of MultiValueDicts) conveniently work with - # this. + # Data for a MultipleChoiceField should be a list. QueryDict and + # MultiValueDict conveniently work with this. class SongForm(Form): name = CharField() composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) @@ -573,11 +570,6 @@ class FormsTestCase(TestCase): f = SongForm(data) self.assertEqual(f.errors, {}) - # MergeDict is deprecated, but is supported until removed. - data = MergeDict(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P']))) - f = SongForm(data) - self.assertEqual(f.errors, {}) - def test_multiple_hidden(self): class SongForm(Form): name = CharField() diff --git a/tests/utils_tests/test_datastructures.py b/tests/utils_tests/test_datastructures.py index 04ae61902c..fafb0cfdce 100644 --- a/tests/utils_tests/test_datastructures.py +++ b/tests/utils_tests/test_datastructures.py @@ -7,7 +7,7 @@ import pickle from django.test import SimpleTestCase, ignore_warnings from django.utils.datastructures import (DictWrapper, ImmutableList, - MultiValueDict, MultiValueDictKeyError, MergeDict, OrderedSet, SortedDict) + MultiValueDict, MultiValueDictKeyError, OrderedSet, SortedDict) from django.utils.deprecation import RemovedInDjango19Warning from django.utils import six @@ -137,77 +137,6 @@ class SortedDictTests(SimpleTestCase): self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1]) -@ignore_warnings(category=RemovedInDjango19Warning) -class MergeDictTests(SimpleTestCase): - - def test_simple_mergedict(self): - d1 = {'chris': 'cool', 'camri': 'cute', 'cotton': 'adorable', - 'tulip': 'snuggable', 'twoofme': 'firstone'} - - d2 = {'chris2': 'cool2', 'camri2': 'cute2', 'cotton2': 'adorable2', - 'tulip2': 'snuggable2'} - - d3 = {'chris3': 'cool3', 'camri3': 'cute3', 'cotton3': 'adorable3', - 'tulip3': 'snuggable3'} - - md = MergeDict(d1, d2, d3) - - self.assertEqual(md['chris'], 'cool') - self.assertEqual(md['camri'], 'cute') - self.assertEqual(md['twoofme'], 'firstone') - - md2 = md.copy() - self.assertEqual(md2['chris'], 'cool') - - def test_mergedict_merges_multivaluedict(self): - """ MergeDict can merge MultiValueDicts """ - - multi1 = MultiValueDict({'key1': ['value1'], - 'key2': ['value2', 'value3']}) - - multi2 = MultiValueDict({'key2': ['value4'], - 'key4': ['value5', 'value6']}) - - mm = MergeDict(multi1, multi2) - - # Although 'key2' appears in both dictionaries, - # only the first value is used. - self.assertEqual(mm.getlist('key2'), ['value2', 'value3']) - self.assertEqual(mm.getlist('key4'), ['value5', 'value6']) - self.assertEqual(mm.getlist('undefined'), []) - - self.assertEqual(sorted(six.iterkeys(mm)), ['key1', 'key2', 'key4']) - self.assertEqual(len(list(six.itervalues(mm))), 3) - - self.assertIn('value1', six.itervalues(mm)) - - self.assertEqual( - sorted(six.iteritems(mm), key=lambda k: k[0]), - [('key1', 'value1'), ('key2', 'value3'), ('key4', 'value6')] - ) - - self.assertEqual( - [(k, mm.getlist(k)) for k in sorted(mm)], - [('key1', ['value1']), - ('key2', ['value2', 'value3']), - ('key4', ['value5', 'value6'])] - ) - - def test_bool_casting(self): - empty = MergeDict({}, {}, {}) - not_empty = MergeDict({}, {}, {"key": "value"}) - self.assertFalse(empty) - self.assertTrue(not_empty) - - def test_key_error(self): - """ - Test that the message of KeyError contains the missing key name. - """ - d1 = MergeDict({'key1': 42}) - with six.assertRaisesRegex(self, KeyError, 'key2'): - d1['key2'] - - class OrderedSetTests(SimpleTestCase): def test_bool(self):