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:
parent
e0a56ad3c8
commit
bc4c7e5d68
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue