annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/wsgiref/headers.py @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
rev   line source
jpayne@68 1 """Manage HTTP Response Headers
jpayne@68 2
jpayne@68 3 Much of this module is red-handedly pilfered from email.message in the stdlib,
jpayne@68 4 so portions are Copyright (C) 2001,2002 Python Software Foundation, and were
jpayne@68 5 written by Barry Warsaw.
jpayne@68 6 """
jpayne@68 7
jpayne@68 8 # Regular expression that matches `special' characters in parameters, the
jpayne@68 9 # existence of which force quoting of the parameter value.
jpayne@68 10 import re
jpayne@68 11 tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
jpayne@68 12
jpayne@68 13 def _formatparam(param, value=None, quote=1):
jpayne@68 14 """Convenience function to format and return a key=value pair.
jpayne@68 15
jpayne@68 16 This will quote the value if needed or if quote is true.
jpayne@68 17 """
jpayne@68 18 if value is not None and len(value) > 0:
jpayne@68 19 if quote or tspecials.search(value):
jpayne@68 20 value = value.replace('\\', '\\\\').replace('"', r'\"')
jpayne@68 21 return '%s="%s"' % (param, value)
jpayne@68 22 else:
jpayne@68 23 return '%s=%s' % (param, value)
jpayne@68 24 else:
jpayne@68 25 return param
jpayne@68 26
jpayne@68 27
jpayne@68 28 class Headers:
jpayne@68 29 """Manage a collection of HTTP response headers"""
jpayne@68 30
jpayne@68 31 def __init__(self, headers=None):
jpayne@68 32 headers = headers if headers is not None else []
jpayne@68 33 if type(headers) is not list:
jpayne@68 34 raise TypeError("Headers must be a list of name/value tuples")
jpayne@68 35 self._headers = headers
jpayne@68 36 if __debug__:
jpayne@68 37 for k, v in headers:
jpayne@68 38 self._convert_string_type(k)
jpayne@68 39 self._convert_string_type(v)
jpayne@68 40
jpayne@68 41 def _convert_string_type(self, value):
jpayne@68 42 """Convert/check value type."""
jpayne@68 43 if type(value) is str:
jpayne@68 44 return value
jpayne@68 45 raise AssertionError("Header names/values must be"
jpayne@68 46 " of type str (got {0})".format(repr(value)))
jpayne@68 47
jpayne@68 48 def __len__(self):
jpayne@68 49 """Return the total number of headers, including duplicates."""
jpayne@68 50 return len(self._headers)
jpayne@68 51
jpayne@68 52 def __setitem__(self, name, val):
jpayne@68 53 """Set the value of a header."""
jpayne@68 54 del self[name]
jpayne@68 55 self._headers.append(
jpayne@68 56 (self._convert_string_type(name), self._convert_string_type(val)))
jpayne@68 57
jpayne@68 58 def __delitem__(self,name):
jpayne@68 59 """Delete all occurrences of a header, if present.
jpayne@68 60
jpayne@68 61 Does *not* raise an exception if the header is missing.
jpayne@68 62 """
jpayne@68 63 name = self._convert_string_type(name.lower())
jpayne@68 64 self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
jpayne@68 65
jpayne@68 66 def __getitem__(self,name):
jpayne@68 67 """Get the first header value for 'name'
jpayne@68 68
jpayne@68 69 Return None if the header is missing instead of raising an exception.
jpayne@68 70
jpayne@68 71 Note that if the header appeared multiple times, the first exactly which
jpayne@68 72 occurrence gets returned is undefined. Use getall() to get all
jpayne@68 73 the values matching a header field name.
jpayne@68 74 """
jpayne@68 75 return self.get(name)
jpayne@68 76
jpayne@68 77 def __contains__(self, name):
jpayne@68 78 """Return true if the message contains the header."""
jpayne@68 79 return self.get(name) is not None
jpayne@68 80
jpayne@68 81
jpayne@68 82 def get_all(self, name):
jpayne@68 83 """Return a list of all the values for the named field.
jpayne@68 84
jpayne@68 85 These will be sorted in the order they appeared in the original header
jpayne@68 86 list or were added to this instance, and may contain duplicates. Any
jpayne@68 87 fields deleted and re-inserted are always appended to the header list.
jpayne@68 88 If no fields exist with the given name, returns an empty list.
jpayne@68 89 """
jpayne@68 90 name = self._convert_string_type(name.lower())
jpayne@68 91 return [kv[1] for kv in self._headers if kv[0].lower()==name]
jpayne@68 92
jpayne@68 93
jpayne@68 94 def get(self,name,default=None):
jpayne@68 95 """Get the first header value for 'name', or return 'default'"""
jpayne@68 96 name = self._convert_string_type(name.lower())
jpayne@68 97 for k,v in self._headers:
jpayne@68 98 if k.lower()==name:
jpayne@68 99 return v
jpayne@68 100 return default
jpayne@68 101
jpayne@68 102
jpayne@68 103 def keys(self):
jpayne@68 104 """Return a list of all the header field names.
jpayne@68 105
jpayne@68 106 These will be sorted in the order they appeared in the original header
jpayne@68 107 list, or were added to this instance, and may contain duplicates.
jpayne@68 108 Any fields deleted and re-inserted are always appended to the header
jpayne@68 109 list.
jpayne@68 110 """
jpayne@68 111 return [k for k, v in self._headers]
jpayne@68 112
jpayne@68 113 def values(self):
jpayne@68 114 """Return a list of all header values.
jpayne@68 115
jpayne@68 116 These will be sorted in the order they appeared in the original header
jpayne@68 117 list, or were added to this instance, and may contain duplicates.
jpayne@68 118 Any fields deleted and re-inserted are always appended to the header
jpayne@68 119 list.
jpayne@68 120 """
jpayne@68 121 return [v for k, v in self._headers]
jpayne@68 122
jpayne@68 123 def items(self):
jpayne@68 124 """Get all the header fields and values.
jpayne@68 125
jpayne@68 126 These will be sorted in the order they were in the original header
jpayne@68 127 list, or were added to this instance, and may contain duplicates.
jpayne@68 128 Any fields deleted and re-inserted are always appended to the header
jpayne@68 129 list.
jpayne@68 130 """
jpayne@68 131 return self._headers[:]
jpayne@68 132
jpayne@68 133 def __repr__(self):
jpayne@68 134 return "%s(%r)" % (self.__class__.__name__, self._headers)
jpayne@68 135
jpayne@68 136 def __str__(self):
jpayne@68 137 """str() returns the formatted headers, complete with end line,
jpayne@68 138 suitable for direct HTTP transmission."""
jpayne@68 139 return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
jpayne@68 140
jpayne@68 141 def __bytes__(self):
jpayne@68 142 return str(self).encode('iso-8859-1')
jpayne@68 143
jpayne@68 144 def setdefault(self,name,value):
jpayne@68 145 """Return first matching header value for 'name', or 'value'
jpayne@68 146
jpayne@68 147 If there is no header named 'name', add a new header with name 'name'
jpayne@68 148 and value 'value'."""
jpayne@68 149 result = self.get(name)
jpayne@68 150 if result is None:
jpayne@68 151 self._headers.append((self._convert_string_type(name),
jpayne@68 152 self._convert_string_type(value)))
jpayne@68 153 return value
jpayne@68 154 else:
jpayne@68 155 return result
jpayne@68 156
jpayne@68 157 def add_header(self, _name, _value, **_params):
jpayne@68 158 """Extended header setting.
jpayne@68 159
jpayne@68 160 _name is the header field to add. keyword arguments can be used to set
jpayne@68 161 additional parameters for the header field, with underscores converted
jpayne@68 162 to dashes. Normally the parameter will be added as key="value" unless
jpayne@68 163 value is None, in which case only the key will be added.
jpayne@68 164
jpayne@68 165 Example:
jpayne@68 166
jpayne@68 167 h.add_header('content-disposition', 'attachment', filename='bud.gif')
jpayne@68 168
jpayne@68 169 Note that unlike the corresponding 'email.message' method, this does
jpayne@68 170 *not* handle '(charset, language, value)' tuples: all values must be
jpayne@68 171 strings or None.
jpayne@68 172 """
jpayne@68 173 parts = []
jpayne@68 174 if _value is not None:
jpayne@68 175 _value = self._convert_string_type(_value)
jpayne@68 176 parts.append(_value)
jpayne@68 177 for k, v in _params.items():
jpayne@68 178 k = self._convert_string_type(k)
jpayne@68 179 if v is None:
jpayne@68 180 parts.append(k.replace('_', '-'))
jpayne@68 181 else:
jpayne@68 182 v = self._convert_string_type(v)
jpayne@68 183 parts.append(_formatparam(k.replace('_', '-'), v))
jpayne@68 184 self._headers.append((self._convert_string_type(_name), "; ".join(parts)))