diff --git a/AUTHORS.rst b/AUTHORS.rst index fd3513fd..9d720d19 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -86,4 +86,5 @@ Source Contributors - cmays90 `@cmays90 `_ - Dio Brando `@isFakeAccount `_ - Josh Kim `@jsk56143 `_ +- Rolf Campbell `@endlisnis `_ - Add "Name and github profile link" above this line. diff --git a/asyncpraw/models/reddit/subreddit.py b/asyncpraw/models/reddit/subreddit.py index 5c36ee6d..3ae18b0b 100644 --- a/asyncpraw/models/reddit/subreddit.py +++ b/asyncpraw/models/reddit/subreddit.py @@ -24,8 +24,10 @@ from xml.etree.ElementTree import XML from aiohttp import ClientResponse +from aiohttp.http_exceptions import HttpProcessingError from aiohttp.web_ws import WebSocketError from asyncprawcore import Redirect +from asyncprawcore.exceptions import ServerError from ...const import API_PATH, JPEG_HEADER from ...exceptions import ( @@ -692,6 +694,13 @@ async def _submit_media(self, data: dict, timeout: int, websocket_url: str = Non url = ws_update["payload"]["redirect"] return await self._reddit.submission(url=url) + async def _read_and_post_media(self, media_path, upload_url, upload_data): + with open(media_path, "rb") as media: + response = await self._reddit._core._requestor._http.post( + upload_url, data=upload_data, files={"file": media} + ) + return response + async def _upload_media( self, media_path: str, @@ -744,14 +753,13 @@ async def _upload_media( upload_url = f"https:{upload_lease['action']}" upload_data = {item["name"]: item["value"] for item in upload_lease["fields"]} - with open(media_path, "rb") as media: - upload_data["file"] = media - response = await self._reddit._core._requestor._http.post( - upload_url, data=upload_data - ) + response = await self._read_and_post_media(media_path, upload_url, upload_data) if not response.status == 201: self._parse_xml_response(response) - response.raise_for_status() + try: + response.raise_for_status() + except HttpProcessingError: + raise ServerError(response=response) websocket_url = upload_response["asset"]["websocket_url"] diff --git a/tests/unit/models/reddit/test_subreddit.py b/tests/unit/models/reddit/test_subreddit.py index 6b9bce7e..968d5453 100644 --- a/tests/unit/models/reddit/test_subreddit.py +++ b/tests/unit/models/reddit/test_subreddit.py @@ -71,13 +71,36 @@ async def test_invalid_media(self, connection_mock, _mock_upload_media, _mock_po context_manager.__aenter__.return_value = recv_mock connection_mock.return_value = context_manager - # websockets_mock().__aenter__.recv = with pytest.raises(MediaPostFailed): await Subreddit(self.reddit, display_name="test").submit_image( "Test", "dummy path" ) await self.reddit._core._requestor._http.close() + @mock.patch("asyncpraw.models.Subreddit._read_and_post_media") + @mock.patch( + "asyncpraw.Reddit.post", + return_value={ + "json": {"data": {"websocket_url": ""}}, + "args": {"action": "", "fields": []}, + }, + ) + @mock.patch("aiohttp.client.ClientSession.ws_connect") + async def test_media_upload_500(self, connection_mock, _mock_post, mock_method): + from aiohttp.http_exceptions import HttpProcessingError + from asyncprawcore.exceptions import ServerError + + response = mock.Mock() + response.status = 201 + response.raise_for_status = mock.Mock( + side_effect=HttpProcessingError(code=500, message="") + ) + mock_method.return_value = response + with pytest.raises(ServerError): + await Subreddit(self.reddit, display_name="test").submit_image( + "Test", "/dev/null" + ) + def test_repr(self): subreddit = Subreddit(self.reddit, display_name="name") assert repr(subreddit) == "Subreddit(display_name='name')"