Removed django.utils.datastructures.MergeDict per deprecation timeline; refs #18659.

This commit is contained in:
Tim Graham 2014-11-18 12:09:20 -05:00
parent 75f107b884
commit 37b7776a01
4 changed files with 8 additions and 202 deletions

View File

@ -9,7 +9,7 @@ from itertools import chain
from django.conf import settings from django.conf import settings
from django.forms.utils import flatatt, to_current_timezone 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.encoding import force_text, python_2_unicode_compatible
from django.utils.html import conditional_escape, format_html from django.utils.html import conditional_escape, format_html
from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext_lazy
@ -319,7 +319,7 @@ class MultipleHiddenInput(HiddenInput):
return mark_safe('\n'.join(inputs)) return mark_safe('\n'.join(inputs))
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
if isinstance(data, (MultiValueDict, MergeDict)): if isinstance(data, MultiValueDict):
return data.getlist(name) return data.getlist(name)
return data.get(name, None) return data.get(name, None)
@ -587,7 +587,7 @@ class SelectMultiple(Select):
return mark_safe('\n'.join(output)) return mark_safe('\n'.join(output))
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
if isinstance(data, (MultiValueDict, MergeDict)): if isinstance(data, MultiValueDict):
return data.getlist(name) return data.getlist(name)
return data.get(name, None) return data.get(name, None)

View File

@ -6,121 +6,6 @@ from django.utils import six
from django.utils.deprecation import RemovedInDjango19Warning 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 "<object meta-data>" inherited from object.
'''
return str(dict(self.items()))
def __repr__(self):
'''
Returns something like
MergeDict({'key1': 'val1', 'key2': 'val2'}, {'key3': 'val3'})
instead of generic "<object meta-data>" inherited from object.
'''
dictreprs = ', '.join(repr(d) for d in self.dicts)
return '%s(%s)' % (self.__class__.__name__, dictreprs)
class SortedDict(dict): class SortedDict(dict):
""" """
A dictionary that keeps its keys in the order in which they're inserted. A dictionary that keeps its keys in the order in which they're inserted.

View File

@ -18,10 +18,9 @@ from django.forms import (
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.http import QueryDict from django.http import QueryDict
from django.template import Template, Context 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.test.utils import str_prefix
from django.utils.datastructures import MultiValueDict, MergeDict from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango19Warning
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.safestring import mark_safe, SafeData from django.utils.safestring import mark_safe, SafeData
@ -552,11 +551,9 @@ class FormsTestCase(TestCase):
<li><label for="composers_id_1"><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li> <li><label for="composers_id_1"><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li>
</ul>""") </ul>""")
@ignore_warnings(category=RemovedInDjango19Warning) # MergeDict deprecation
def test_multiple_choice_list_data(self): def test_multiple_choice_list_data(self):
# Data for a MultipleChoiceField should be a list. QueryDict, MultiValueDict and # Data for a MultipleChoiceField should be a list. QueryDict and
# MergeDict (when created as a merge of MultiValueDicts) conveniently work with # MultiValueDict conveniently work with this.
# this.
class SongForm(Form): class SongForm(Form):
name = CharField() name = CharField()
composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple)
@ -573,11 +570,6 @@ class FormsTestCase(TestCase):
f = SongForm(data) f = SongForm(data)
self.assertEqual(f.errors, {}) 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): def test_multiple_hidden(self):
class SongForm(Form): class SongForm(Form):
name = CharField() name = CharField()

View File

@ -7,7 +7,7 @@ import pickle
from django.test import SimpleTestCase, ignore_warnings from django.test import SimpleTestCase, ignore_warnings
from django.utils.datastructures import (DictWrapper, ImmutableList, 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.deprecation import RemovedInDjango19Warning
from django.utils import six from django.utils import six
@ -137,77 +137,6 @@ class SortedDictTests(SimpleTestCase):
self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1]) 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): class OrderedSetTests(SimpleTestCase):
def test_bool(self): def test_bool(self):