typing: Populate POST and _files with `cast` and `setattr`.

`POST` is an immutable attribute and `_files` is an internal attribute
of `HttpRequest`. With type annotations provided by `django-stubs`, mypy
stops us from modifying these attributes. This uses `cast` and `setattr`
to avoid typing issues.

This is a part of django-stubs refactorings.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
Zixuan James Li 2022-05-30 18:47:39 -04:00 committed by Tim Abbott
parent 27be27560b
commit a3a0545aac
1 changed files with 30 additions and 5 deletions

View File

@ -4,7 +4,18 @@ import logging
import urllib
from functools import wraps
from io import BytesIO
from typing import Callable, Dict, Optional, Sequence, Set, TypeVar, Union, cast, overload
from typing import (
TYPE_CHECKING,
Callable,
Dict,
Optional,
Sequence,
Set,
TypeVar,
Union,
cast,
overload,
)
import django_otp
import orjson
@ -62,6 +73,9 @@ if settings.ZILENCER_ENABLED:
get_remote_server_by_uuid,
)
if TYPE_CHECKING:
from django.http.request import _ImmutableQueryDict
rate_limiter_logger = logging.getLogger("zerver.lib.rate_limiter")
webhook_logger = logging.getLogger("zulip.zerver.webhooks")
@ -719,15 +733,26 @@ def process_as_post(view_func: ViewFuncT) -> ViewFuncT:
if not request.POST:
# Only take action if POST is empty.
if request.content_type == "multipart/form-data":
# Note that request._files is just the private attribute that backs the
# FILES property, so we are essentially setting request.FILES here. (In
# Django 1.5 FILES was still a read-only property.)
request.POST, request._files = MultiPartParser(
POST, _files = MultiPartParser(
request.META,
BytesIO(request.body),
request.upload_handlers,
request.encoding,
).parse()
# request.POST is an immutable QueryDict in most cases, while
# MultiPartParser.parse() returns a mutable instance of QueryDict.
# This can be fix when https://code.djangoproject.com/ticket/17235
# is resolved.
# django-stubs makes QueryDict of different mutabilities incompatible
# types. There is no way to acknowledge the django-stubs mypy plugin
# the change of POST's mutability, so we bypass the check with cast.
# See also: https://github.com/typeddjango/django-stubs/pull/925#issue-1206399444
POST._mutable = False
request.POST = cast("_ImmutableQueryDict", POST)
# Note that request._files is just the private attribute that backs the
# FILES property, so we are essentially setting request.FILES here. (In
# Django 3.2 FILES was still a read-only property.)
setattr(request, "_files", _files)
elif request.content_type == "application/x-www-form-urlencoded":
request.POST = QueryDict(request.body, encoding=request.encoding)