From bc4c7e5d68e01207268c868932eb14ae4206f02c Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Mon, 20 Sep 2021 22:33:42 +0300 Subject: Optimized handling case-insensitive mappings. Elements yielded by _destruct_iterable_mapping_values are always unpacked. Since unpacking can be done with any iterable, there is no need to convert elements to tuples. Also, such elements can be used directly in for loops, creating a dictionary of them is excessive. Co-authored-by: Nick Pope --- django/utils/datastructures.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'django/utils') diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index f1e9986ca1..18c91aa5e8 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -284,18 +284,6 @@ class DictWrapper(dict): return value -def _destruct_iterable_mapping_values(data): - for i, elem in enumerate(data): - if len(elem) != 2: - raise ValueError( - 'dictionary update sequence element #{} has ' - 'length {}; 2 is required.'.format(i, len(elem)) - ) - if not isinstance(elem[0], str): - raise ValueError('Element key %r invalid, only strings are allowed' % elem[0]) - yield tuple(elem) - - class CaseInsensitiveMapping(Mapping): """ Mapping allowing case-insensitive key lookups. Original case of keys is @@ -315,9 +303,7 @@ class CaseInsensitiveMapping(Mapping): """ def __init__(self, data): - if not isinstance(data, Mapping): - data = {k: v for k, v in _destruct_iterable_mapping_values(data)} - self._store = {k.lower(): (k, v) for k, v in data.items()} + self._store = {k.lower(): (k, v) for k, v in self._unpack_items(data)} def __getitem__(self, key): return self._store[key.lower()][1] @@ -340,3 +326,20 @@ class CaseInsensitiveMapping(Mapping): def copy(self): return self + + @staticmethod + def _unpack_items(data): + if isinstance(data, Mapping): + yield from data.items() + return + for i, elem in enumerate(data): + if len(elem) != 2: + raise ValueError( + 'dictionary update sequence element #{} has length {}; ' + '2 is required.'.format(i, len(elem)) + ) + if not isinstance(elem[0], str): + raise ValueError( + 'Element key %r invalid, only strings are allowed' % elem[0] + ) + yield elem -- cgit v1.3