diff --git a/requirements.txt b/requirements.txt index 4cbad45780..26bc63b21f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,6 +28,7 @@ flake8-bugbear==22.7.1 flake8-pie==0.16.0; python_version>='3.7' importlib-metadata==4.13.0; python_version>='3.7' isort==5.10.1 +multipart==0.2.4 mypy==0.982 types-certifi==2021.10.8.2 pytest==7.1.2 diff --git a/setup.cfg b/setup.cfg index d421afb6dc..3b085d087c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,8 +20,6 @@ combine_as_imports = True addopts = -rxXs filterwarnings = error - default:path is deprecated:DeprecationWarning:certifi - default:'cgi' is deprecated:DeprecationWarning asyncio_mode = strict markers = copied_from(source, changes=None): mark test as copied from somewhere else, along with a description of changes made to accodomate e.g. our test setup diff --git a/tests/test_multipart.py b/tests/test_multipart.py index a4e9796bd7..1d9c12feea 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -1,4 +1,3 @@ -import cgi import io import os import tempfile @@ -6,6 +5,7 @@ from unittest import mock import pytest +from multipart import MultipartParser import httpx from httpx._content import encode_request @@ -26,15 +26,14 @@ def test_multipart(value, output): response = client.post("http://127.0.0.1:8000/", data=data, files=files) assert response.status_code == 200 - # We're using the cgi module to verify the behavior here, which is a - # bit grungy, but sufficient just for our testing purposes. boundary = response.request.headers["Content-Type"].split("boundary=")[-1] - content_length = response.request.headers["Content-Length"] - pdict: dict = { - "boundary": boundary.encode("ascii"), - "CONTENT-LENGTH": content_length, - } - multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict) + content_length = int(response.request.headers["Content-Length"]) + + multipart = {} + for part in MultipartParser( + io.BytesIO(response.content), boundary=boundary, content_length=content_length + ): + multipart[part.name] = [part.raw] # Note that the expected return type for text fields # appears to differs from 3.6 to 3.7+ @@ -63,15 +62,14 @@ def test_multipart_explicit_boundary(header: str) -> None: response = client.post("http://127.0.0.1:8000/", files=files, headers=headers) assert response.status_code == 200 - # We're using the cgi module to verify the behavior here, which is a - # bit grungy, but sufficient just for our testing purposes. assert response.request.headers["Content-Type"] == header - content_length = response.request.headers["Content-Length"] - pdict: dict = { - "boundary": b"+++", - "CONTENT-LENGTH": content_length, - } - multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict) + content_length = int(response.request.headers["Content-Length"]) + + multipart = {} + for part in MultipartParser( + io.BytesIO(response.content), boundary="+++", content_length=content_length + ): + multipart[part.name] = [part.raw] assert multipart["file"] == [b""] @@ -131,15 +129,14 @@ def test_multipart_file_tuple(): response = client.post("http://127.0.0.1:8000/", data=data, files=files) assert response.status_code == 200 - # We're using the cgi module to verify the behavior here, which is a - # bit grungy, but sufficient just for our testing purposes. boundary = response.request.headers["Content-Type"].split("boundary=")[-1] - content_length = response.request.headers["Content-Length"] - pdict: dict = { - "boundary": boundary.encode("ascii"), - "CONTENT-LENGTH": content_length, - } - multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict) + content_length = int(response.request.headers["Content-Length"]) + + multipart = {} + for part in MultipartParser( + io.BytesIO(response.content), boundary=boundary, content_length=content_length + ): + multipart[part.name] = [part.raw] # Note that the expected return type for text fields # appears to differs from 3.6 to 3.7+