测试gitnore

This commit is contained in:
ladeng07
2022-05-06 15:45:57 +08:00
parent 12f390949b
commit 51552904f9
2347 changed files with 120102 additions and 53549 deletions
+111 -161
View File
@@ -17,16 +17,13 @@ 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,
CaseInsensitiveMapping, _destruct_iterable_mapping_values,
)
from django.utils.encoding import iri_to_uri
from django.utils.http import http_date
from django.utils.regex_helper import _lazy_re_compile
_charset_from_content_type_re = _lazy_re_compile(
r";\s*charset=(?P<charset>[^\s;]+)", re.I
)
_charset_from_content_type_re = _lazy_re_compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
class ResponseHeaders(CaseInsensitiveMapping):
@@ -49,12 +46,11 @@ class ResponseHeaders(CaseInsensitiveMapping):
"""
if not isinstance(value, (bytes, str)):
value = str(value)
if (isinstance(value, bytes) and (b"\n" in value or b"\r" in value)) or (
isinstance(value, str) and ("\n" in value or "\r" in value)
if (
(isinstance(value, bytes) and (b'\n' in value or b'\r' in value)) or
(isinstance(value, str) and ('\n' in value or '\r' in value))
):
raise BadHeaderError(
"Header values can't contain newlines (got %r)" % value
)
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try:
if isinstance(value, str):
# Ensure string is valid in given charset
@@ -64,9 +60,9 @@ class ResponseHeaders(CaseInsensitiveMapping):
value = value.decode(charset)
except UnicodeError as e:
if mime_encode:
value = Header(value, "utf-8", maxlinelen=sys.maxsize).encode()
value = Header(value, 'utf-8', maxlinelen=sys.maxsize).encode()
else:
e.reason += ", HTTP response headers must be in %s format" % charset
e.reason += ', HTTP response headers must be in %s format' % charset
raise
return value
@@ -74,8 +70,8 @@ class ResponseHeaders(CaseInsensitiveMapping):
self.pop(key)
def __setitem__(self, key, value):
key = self._convert_to_charset(key, "ascii")
value = self._convert_to_charset(value, "latin-1", mime_encode=True)
key = self._convert_to_charset(key, 'ascii')
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
self._store[key.lower()] = (key, value)
def pop(self, key, default=None):
@@ -100,20 +96,18 @@ class HttpResponseBase:
status_code = 200
def __init__(
self, content_type=None, status=None, reason=None, charset=None, headers=None
):
def __init__(self, content_type=None, status=None, reason=None, charset=None, headers=None):
self.headers = ResponseHeaders(headers or {})
self._charset = charset
if content_type and "Content-Type" in self.headers:
if content_type and 'Content-Type' in self.headers:
raise ValueError(
"'headers' must not contain 'Content-Type' when the "
"'content_type' parameter is provided."
)
if "Content-Type" not in self.headers:
if 'Content-Type' not in self.headers:
if content_type is None:
content_type = "text/html; charset=%s" % self.charset
self.headers["Content-Type"] = content_type
content_type = 'text/html; charset=%s' % self.charset
self.headers['Content-Type'] = content_type
self._resource_closers = []
# This parameter is set by the handler. It's necessary to preserve the
# historical behavior of request_finished.
@@ -124,10 +118,10 @@ class HttpResponseBase:
try:
self.status_code = int(status)
except (ValueError, TypeError):
raise TypeError("HTTP status code must be an integer.")
raise TypeError('HTTP status code must be an integer.')
if not 100 <= self.status_code <= 599:
raise ValueError("HTTP status code must be an integer from 100 to 599.")
raise ValueError('HTTP status code must be an integer from 100 to 599.')
self._reason_phrase = reason
@property
@@ -136,7 +130,7 @@ class HttpResponseBase:
return self._reason_phrase
# Leave self._reason_phrase unset in order to use the default
# reason phrase for status code.
return responses.get(self.status_code, "Unknown Status Code")
return responses.get(self.status_code, 'Unknown Status Code')
@reason_phrase.setter
def reason_phrase(self, value):
@@ -146,11 +140,11 @@ class HttpResponseBase:
def charset(self):
if self._charset is not None:
return self._charset
content_type = self.get("Content-Type", "")
content_type = self.get('Content-Type', '')
matched = _charset_from_content_type_re.search(content_type)
if matched:
# Extract the charset and strip its double quotes
return matched["charset"].replace('"', "")
return matched['charset'].replace('"', '')
return settings.DEFAULT_CHARSET
@charset.setter
@@ -159,22 +153,20 @@ class HttpResponseBase:
def serialize_headers(self):
"""HTTP headers as a bytestring."""
return b"\r\n".join(
[
key.encode("ascii") + b": " + value.encode("latin-1")
for key, value in self.headers.items()
]
)
def to_bytes(val, encoding):
return val if isinstance(val, bytes) else val.encode(encoding)
headers = [
(to_bytes(key, 'ascii') + b': ' + to_bytes(value, 'latin-1'))
for key, value in self.headers.items()
]
return b'\r\n'.join(headers)
__bytes__ = serialize_headers
@property
def _content_type_for_repr(self):
return (
', "%s"' % self.headers["Content-Type"]
if "Content-Type" in self.headers
else ""
)
return ', "%s"' % self.headers['Content-Type'] if 'Content-Type' in self.headers else ''
def __setitem__(self, header, value):
self.headers[header] = value
@@ -197,18 +189,8 @@ class HttpResponseBase:
def get(self, header, alternate=None):
return self.headers.get(header, alternate)
def set_cookie(
self,
key,
value="",
max_age=None,
expires=None,
path="/",
domain=None,
secure=False,
httponly=False,
samesite=None,
):
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False, samesite=None):
"""
Set a cookie.
@@ -221,9 +203,9 @@ class HttpResponseBase:
self.cookies[key] = value
if expires is not None:
if isinstance(expires, datetime.datetime):
if timezone.is_naive(expires):
expires = timezone.make_aware(expires, timezone.utc)
delta = expires - datetime.datetime.now(tz=timezone.utc)
if timezone.is_aware(expires):
expires = timezone.make_naive(expires, timezone.utc)
delta = expires - expires.utcnow()
# Add one second so the date matches exactly (a fraction of
# time gets lost between converting to a timedelta and
# then the date string).
@@ -232,51 +214,47 @@ class HttpResponseBase:
expires = None
max_age = max(0, delta.days * 86400 + delta.seconds)
else:
self.cookies[key]["expires"] = expires
self.cookies[key]['expires'] = expires
else:
self.cookies[key]["expires"] = ""
self.cookies[key]['expires'] = ''
if max_age is not None:
self.cookies[key]["max-age"] = int(max_age)
self.cookies[key]['max-age'] = int(max_age)
# IE requires expires, so set it if hasn't been already.
if not expires:
self.cookies[key]["expires"] = http_date(time.time() + max_age)
self.cookies[key]['expires'] = http_date(time.time() + max_age)
if path is not None:
self.cookies[key]["path"] = path
self.cookies[key]['path'] = path
if domain is not None:
self.cookies[key]["domain"] = domain
self.cookies[key]['domain'] = domain
if secure:
self.cookies[key]["secure"] = True
self.cookies[key]['secure'] = True
if httponly:
self.cookies[key]["httponly"] = True
self.cookies[key]['httponly'] = True
if samesite:
if samesite.lower() not in ("lax", "none", "strict"):
if samesite.lower() not in ('lax', 'none', 'strict'):
raise ValueError('samesite must be "lax", "none", or "strict".')
self.cookies[key]["samesite"] = samesite
self.cookies[key]['samesite'] = samesite
def setdefault(self, key, value):
"""Set a header unless it has already been set."""
self.headers.setdefault(key, value)
def set_signed_cookie(self, key, value, salt="", **kwargs):
def set_signed_cookie(self, key, value, salt='', **kwargs):
value = signing.get_cookie_signer(salt=key + salt).sign(value)
return self.set_cookie(key, value, **kwargs)
def delete_cookie(self, key, path="/", domain=None, samesite=None):
def delete_cookie(self, key, path='/', domain=None, samesite=None):
# Browsers can ignore the Set-Cookie header if the cookie doesn't use
# the secure flag and:
# - the cookie name starts with "__Host-" or "__Secure-", or
# - the samesite is "none".
secure = key.startswith(("__Secure-", "__Host-")) or (
samesite and samesite.lower() == "none"
secure = (
key.startswith(('__Secure-', '__Host-')) or
(samesite and samesite.lower() == 'none')
)
self.set_cookie(
key,
max_age=0,
path=path,
domain=domain,
secure=secure,
expires="Thu, 01 Jan 1970 00:00:00 GMT",
samesite=samesite,
key, max_age=0, path=path, domain=domain, secure=secure,
expires='Thu, 01 Jan 1970 00:00:00 GMT', samesite=samesite,
)
# Common methods used by subclasses
@@ -314,15 +292,13 @@ class HttpResponseBase:
signals.request_finished.send(sender=self._handler_class)
def write(self, content):
raise OSError("This %s instance is not writable" % self.__class__.__name__)
raise OSError('This %s instance is not writable' % self.__class__.__name__)
def flush(self):
pass
def tell(self):
raise OSError(
"This %s instance cannot tell its position" % self.__class__.__name__
)
raise OSError('This %s instance cannot tell its position' % self.__class__.__name__)
# These methods partially implement a stream-like object interface.
# See https://docs.python.org/library/io.html#io.IOBase
@@ -337,7 +313,7 @@ class HttpResponseBase:
return False
def writelines(self, lines):
raise OSError("This %s instance is not writable" % self.__class__.__name__)
raise OSError('This %s instance is not writable' % self.__class__.__name__)
class HttpResponse(HttpResponseBase):
@@ -349,36 +325,37 @@ class HttpResponse(HttpResponseBase):
streaming = False
def __init__(self, content=b"", *args, **kwargs):
def __init__(self, content=b'', *args, **kwargs):
super().__init__(*args, **kwargs)
# Content is a bytestring. See the `content` property methods.
self.content = content
def __repr__(self):
return "<%(cls)s status_code=%(status_code)d%(content_type)s>" % {
"cls": self.__class__.__name__,
"status_code": self.status_code,
"content_type": self._content_type_for_repr,
return '<%(cls)s status_code=%(status_code)d%(content_type)s>' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self._content_type_for_repr,
}
def serialize(self):
"""Full HTTP message, including headers, as a bytestring."""
return self.serialize_headers() + b"\r\n\r\n" + self.content
return self.serialize_headers() + b'\r\n\r\n' + self.content
__bytes__ = serialize
@property
def content(self):
return b"".join(self._container)
return b''.join(self._container)
@content.setter
def content(self, value):
# Consume iterators upon assignment to allow repeated iteration.
if hasattr(value, "__iter__") and not isinstance(
value, (bytes, memoryview, str)
if (
hasattr(value, '__iter__') and
not isinstance(value, (bytes, memoryview, str))
):
content = b"".join(self.make_bytes(chunk) for chunk in value)
if hasattr(value, "close"):
content = b''.join(self.make_bytes(chunk) for chunk in value)
if hasattr(value, 'close'):
try:
value.close()
except Exception:
@@ -425,13 +402,6 @@ class StreamingHttpResponse(HttpResponseBase):
# See the `streaming_content` property methods.
self.streaming_content = streaming_content
def __repr__(self):
return "<%(cls)s status_code=%(status_code)d%(content_type)s>" % {
"cls": self.__class__.__qualname__,
"status_code": self.status_code,
"content_type": self._content_type_for_repr,
}
@property
def content(self):
raise AttributeError(
@@ -450,37 +420,36 @@ class StreamingHttpResponse(HttpResponseBase):
def _set_streaming_content(self, value):
# Ensure we can never iterate on "value" more than once.
self._iterator = iter(value)
if hasattr(value, "close"):
if hasattr(value, 'close'):
self._resource_closers.append(value.close)
def __iter__(self):
return self.streaming_content
def getvalue(self):
return b"".join(self.streaming_content)
return b''.join(self.streaming_content)
class FileResponse(StreamingHttpResponse):
"""
A streaming HTTP response class optimized for files.
"""
block_size = 4096
def __init__(self, *args, as_attachment=False, filename="", **kwargs):
def __init__(self, *args, as_attachment=False, filename='', **kwargs):
self.as_attachment = as_attachment
self.filename = filename
super().__init__(*args, **kwargs)
def _set_streaming_content(self, value):
if not hasattr(value, "read"):
if not hasattr(value, 'read'):
self.file_to_stream = None
return super()._set_streaming_content(value)
self.file_to_stream = filelike = value
if hasattr(filelike, "close"):
if hasattr(filelike, 'close'):
self._resource_closers.append(filelike.close)
value = iter(lambda: filelike.read(self.block_size), b"")
value = iter(lambda: filelike.read(self.block_size), b'')
self.set_headers(filelike)
super()._set_streaming_content(value)
@@ -490,70 +459,59 @@ class FileResponse(StreamingHttpResponse):
Content-Disposition) based on the `filelike` response content.
"""
encoding_map = {
"bzip2": "application/x-bzip",
"gzip": "application/gzip",
"xz": "application/x-xz",
'bzip2': 'application/x-bzip',
'gzip': 'application/gzip',
'xz': 'application/x-xz',
}
filename = getattr(filelike, "name", None)
filename = (
filename if (isinstance(filename, str) and filename) else self.filename
)
filename = getattr(filelike, 'name', None)
filename = filename if (isinstance(filename, str) and filename) else self.filename
if os.path.isabs(filename):
self.headers["Content-Length"] = os.path.getsize(filelike.name)
elif hasattr(filelike, "getbuffer"):
self.headers["Content-Length"] = filelike.getbuffer().nbytes
self.headers['Content-Length'] = os.path.getsize(filelike.name)
elif hasattr(filelike, 'getbuffer'):
self.headers['Content-Length'] = filelike.getbuffer().nbytes
if self.headers.get("Content-Type", "").startswith("text/html"):
if self.headers.get('Content-Type', '').startswith('text/html'):
if filename:
content_type, encoding = mimetypes.guess_type(filename)
# Encoding isn't set to prevent browsers from automatically
# uncompressing files.
content_type = encoding_map.get(encoding, content_type)
self.headers["Content-Type"] = (
content_type or "application/octet-stream"
)
self.headers['Content-Type'] = content_type or 'application/octet-stream'
else:
self.headers["Content-Type"] = "application/octet-stream"
self.headers['Content-Type'] = 'application/octet-stream'
filename = self.filename or os.path.basename(filename)
if filename:
disposition = "attachment" if self.as_attachment else "inline"
disposition = 'attachment' if self.as_attachment else 'inline'
try:
filename.encode("ascii")
filename.encode('ascii')
file_expr = 'filename="{}"'.format(filename)
except UnicodeEncodeError:
file_expr = "filename*=utf-8''{}".format(quote(filename))
self.headers["Content-Disposition"] = "{}; {}".format(
disposition, file_expr
)
self.headers['Content-Disposition'] = '{}; {}'.format(disposition, file_expr)
elif self.as_attachment:
self.headers["Content-Disposition"] = "attachment"
self.headers['Content-Disposition'] = 'attachment'
class HttpResponseRedirectBase(HttpResponse):
allowed_schemes = ["http", "https", "ftp"]
allowed_schemes = ['http', 'https', 'ftp']
def __init__(self, redirect_to, *args, **kwargs):
super().__init__(*args, **kwargs)
self["Location"] = iri_to_uri(redirect_to)
self['Location'] = iri_to_uri(redirect_to)
parsed = urlparse(str(redirect_to))
if parsed.scheme and parsed.scheme not in self.allowed_schemes:
raise DisallowedRedirect(
"Unsafe redirect to URL with protocol '%s'" % parsed.scheme
)
raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
url = property(lambda self: self["Location"])
url = property(lambda self: self['Location'])
def __repr__(self):
return (
'<%(cls)s status_code=%(status_code)d%(content_type)s, url="%(url)s">'
% {
"cls": self.__class__.__name__,
"status_code": self.status_code,
"content_type": self._content_type_for_repr,
"url": self.url,
}
)
return '<%(cls)s status_code=%(status_code)d%(content_type)s, url="%(url)s">' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self._content_type_for_repr,
'url': self.url,
}
class HttpResponseRedirect(HttpResponseRedirectBase):
@@ -569,14 +527,12 @@ class HttpResponseNotModified(HttpResponse):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
del self["content-type"]
del self['content-type']
@HttpResponse.content.setter
def content(self, value):
if value:
raise AttributeError(
"You cannot set content to a 304 (Not Modified) response"
)
raise AttributeError("You cannot set content to a 304 (Not Modified) response")
self._container = []
@@ -597,14 +553,14 @@ class HttpResponseNotAllowed(HttpResponse):
def __init__(self, permitted_methods, *args, **kwargs):
super().__init__(*args, **kwargs)
self["Allow"] = ", ".join(permitted_methods)
self['Allow'] = ', '.join(permitted_methods)
def __repr__(self):
return "<%(cls)s [%(methods)s] status_code=%(status_code)d%(content_type)s>" % {
"cls": self.__class__.__name__,
"status_code": self.status_code,
"content_type": self._content_type_for_repr,
"methods": self["Allow"],
return '<%(cls)s [%(methods)s] status_code=%(status_code)d%(content_type)s>' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self._content_type_for_repr,
'methods': self['Allow'],
}
@@ -625,7 +581,7 @@ class JsonResponse(HttpResponse):
An HTTP response class that consumes data to be serialized to JSON.
:param data: Data to be dumped into json. By default only ``dict`` objects
are allowed to be passed due to a security flaw before ECMAScript 5. See
are allowed to be passed due to a security flaw before EcmaScript 5. See
the ``safe`` parameter for more information.
:param encoder: Should be a json encoder class. Defaults to
``django.core.serializers.json.DjangoJSONEncoder``.
@@ -634,21 +590,15 @@ class JsonResponse(HttpResponse):
:param json_dumps_params: A dictionary of kwargs passed to json.dumps().
"""
def __init__(
self,
data,
encoder=DjangoJSONEncoder,
safe=True,
json_dumps_params=None,
**kwargs,
):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if safe and not isinstance(data, dict):
raise TypeError(
"In order to allow non-dict objects to be serialized set the "
"safe parameter to False."
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False.'
)
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault("content_type", "application/json")
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)