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 <nick@nickpope.me.uk>
This commit is contained in:
Illia Volochii 2021-09-20 22:33:42 +03:00 committed by Mariusz Felisiak
parent e0a56ad3c8
commit bc4c7e5d68
2 changed files with 20 additions and 22 deletions

View File

@ -5,7 +5,6 @@ import os
import re
import sys
import time
from collections.abc import Mapping
from email.header import Header
from http.client import responses
from urllib.parse import quote, urlparse
@ -16,9 +15,7 @@ from django.core.exceptions import DisallowedRedirect
from django.core.serializers.json import DjangoJSONEncoder
from django.http.cookie import SimpleCookie
from django.utils import timezone
from django.utils.datastructures import (
CaseInsensitiveMapping, _destruct_iterable_mapping_values,
)
from django.utils.datastructures import CaseInsensitiveMapping
from django.utils.encoding import iri_to_uri
from django.utils.http import http_date
from django.utils.regex_helper import _lazy_re_compile
@ -32,10 +29,8 @@ class ResponseHeaders(CaseInsensitiveMapping):
Populate the initial data using __setitem__ to ensure values are
correctly encoded.
"""
if not isinstance(data, Mapping):
data = {k: v for k, v in _destruct_iterable_mapping_values(data)}
self._store = {}
for header, value in data.items():
for header, value in self._unpack_items(data):
self[header] = value
def _convert_to_charset(self, value, charset, mime_encode=False):

View File

@ -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