Skip to content

Add Message.reply_paid_media #4551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 4, 2024
Merged

Add Message.reply_paid_media #4551

merged 5 commits into from
Nov 4, 2024

Conversation

Bibo-Joshi
Copy link
Member

Apparently this was forgotten in some earlier api update …

  • Added .. versionadded:: NEXT.VERSION, .. versionchanged:: NEXT.VERSION, .. deprecated:: NEXT.VERSION or .. versionremoved:: NEXT.VERSION to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
  • Created new or adapted existing unit tests
  • Documented code changes according to the CSI standard
  • [ ] Added myself alphabetically to AUTHORS.rst (optional)
  • Added new classes & modules to the docs and all suitable all s
  • Checked the Stability Policy in case of deprecations or changes to documented behavior

ToDo:

Copy link

codecov bot commented Nov 2, 2024

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
5981 3 5978 281
View the full list of 3 ❄️ flaky tests
tests.test_bot.TestBotWithRequest test_do_api_request_list_return_type[Message]

Flake rate in main: 31.52% (Passed 630 times, Failed 290 times)

Stack Traces | 0.251s run time
@contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
>           yield

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:72: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:377: in handle_async_request
    resp = await self._pool.handle_async_request(req)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <AsyncConnectionPool [Requests: 0 active, 0 queued | Connections: 0 active, 1 idle]>
request = <Request [b'GET']>

    async def handle_async_request(self, request: Request) -> Response:
        """
        Send an HTTP request, and return an HTTP response.
    
        This is the core implementation that is called into by `.request()` or `.stream()`.
        """
        scheme = request.url.scheme.decode()
        if scheme == "":
>           raise UnsupportedProtocol(
                "Request URL is missing an 'http://' or 'https://' protocol."
            )
E           httpcore.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpcore\_async\connection_pool.py:167: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000001BACAA25590>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
>           res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )

telegram\request\_httpxrequest.py:293: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1585: in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1674: in send
    response = await self._send_handling_auth(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1702: in _send_handling_auth
    response = await self._send_handling_redirects(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1739: in _send_handling_redirects
    response = await self._send_single_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1776: in _send_single_request
    response = await transport.handle_async_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:376: in handle_async_request
    with map_httpcore_exceptions():
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\contextlib.py:162: in __exit__
    self.gen.throw(value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    @contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
            yield
        except Exception as exc:
            mapped_exc = None
    
            for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
                if not isinstance(exc, from_exc):
                    continue
                # We want to map to the most specific exception we can find.
                # Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
                # `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
                if mapped_exc is None or issubclass(to_exc, mapped_exc):
                    mapped_exc = to_exc
    
            if mapped_exc is None:  # pragma: no cover
                raise
    
            message = str(exc)
>           raise mapped_exc(message) from exc
E           httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:89: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests.test_bot.TestBotWithRequest object at 0x000001BAC8B84320>
bot = PytestExtBot[token=5737018356:AAH138SuiKQF0LDCWsfgWeXfjJ5d63kCWLA]
chat_id = '675666224', return_type = <class 'telegram._message.Message'>

    @pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
    @pytest.mark.parametrize("return_type", [Message, None])
    async def test_do_api_request_list_return_type(self, bot, chat_id, return_type):
        result = await bot.do_api_request(
            "send_media_group",
            api_kwargs={
                "chat_id": chat_id,
                "media": [
                    InputMediaDocument(
                        InputFile(
                            data_file("text_file.txt").open("rb"),
                            attach=True,
                        )
                    ),
                    InputMediaDocument(
                        InputFile(
                            data_file("local_file.txt").open("rb"),
                            attach=True,
                        )
                    ),
                ],
            },
            return_type=return_type,
        )
        if return_type is None:
            assert isinstance(result, list)
            for entry in result:
                assert isinstance(entry, dict)
            result = Message.de_list(result, bot)
    
        for message, file_name in zip(result, ("text_file.txt", "local_file.txt")):
            assert isinstance(message, Message)
            assert message.chat_id == int(chat_id)
            out = BytesIO()
>           await (await message.document.get_file()).download_to_memory(out)

tests\test_bot.py:4273: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
telegram\_files\file.py:264: in download_to_memory
    buf = await self.get_bot().request.retrieve(
telegram\request\_baserequest.py:254: in retrieve
    return await self._request_wrapper(
tests\auxil\networking.py:48: in _request_wrapper
    return await super()._request_wrapper(
telegram\request\_baserequest.py:334: in _request_wrapper
    code, payload = await self.do_request(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000001BACAA25590>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
            res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )
        except httpx.TimeoutException as err:
            if isinstance(err, httpx.PoolTimeout):
                raise TimedOut(
                    message=(
                        "Pool timeout: All connections in the connection pool are occupied. "
                        "Request was *not* sent to Telegram. Consider adjusting the connection "
                        "pool size or the pool timeout."
                    )
                ) from err
            raise TimedOut from err
        except httpx.HTTPError as err:
            # HTTPError must come last as its the base httpx exception class
            # TODO p4: do something smart here; for now just raise NetworkError
    
            # We include the class name for easier debugging. Especially useful if the error
            # message of `err` is empty.
>           raise NetworkError(f"httpx.{err.__class__.__name__}: {err}") from err
E           telegram.error.NetworkError: httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

telegram\request\_httpxrequest.py:317: NetworkError
tests.test_bot.TestBotWithRequest test_do_api_request_list_return_type[None]

Flake rate in main: 30.91% (Passed 637 times, Failed 285 times)

Stack Traces | 0.258s run time
@contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
>           yield

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:72: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:377: in handle_async_request
    resp = await self._pool.handle_async_request(req)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <AsyncConnectionPool [Requests: 0 active, 0 queued | Connections: 0 active, 1 idle]>
request = <Request [b'GET']>

    async def handle_async_request(self, request: Request) -> Response:
        """
        Send an HTTP request, and return an HTTP response.
    
        This is the core implementation that is called into by `.request()` or `.stream()`.
        """
        scheme = request.url.scheme.decode()
        if scheme == "":
>           raise UnsupportedProtocol(
                "Request URL is missing an 'http://' or 'https://' protocol."
            )
E           httpcore.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpcore\_async\connection_pool.py:167: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000001BACAA25590>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
>           res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )

telegram\request\_httpxrequest.py:293: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1585: in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1674: in send
    response = await self._send_handling_auth(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1702: in _send_handling_auth
    response = await self._send_handling_redirects(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1739: in _send_handling_redirects
    response = await self._send_single_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1776: in _send_single_request
    response = await transport.handle_async_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:376: in handle_async_request
    with map_httpcore_exceptions():
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\contextlib.py:162: in __exit__
    self.gen.throw(value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    @contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
            yield
        except Exception as exc:
            mapped_exc = None
    
            for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
                if not isinstance(exc, from_exc):
                    continue
                # We want to map to the most specific exception we can find.
                # Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
                # `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
                if mapped_exc is None or issubclass(to_exc, mapped_exc):
                    mapped_exc = to_exc
    
            if mapped_exc is None:  # pragma: no cover
                raise
    
            message = str(exc)
>           raise mapped_exc(message) from exc
E           httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:89: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests.test_bot.TestBotWithRequest object at 0x000001BAC8B842D0>
bot = PytestExtBot[token=5737018356:AAH138SuiKQF0LDCWsfgWeXfjJ5d63kCWLA]
chat_id = '675666224', return_type = None

    @pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
    @pytest.mark.parametrize("return_type", [Message, None])
    async def test_do_api_request_list_return_type(self, bot, chat_id, return_type):
        result = await bot.do_api_request(
            "send_media_group",
            api_kwargs={
                "chat_id": chat_id,
                "media": [
                    InputMediaDocument(
                        InputFile(
                            data_file("text_file.txt").open("rb"),
                            attach=True,
                        )
                    ),
                    InputMediaDocument(
                        InputFile(
                            data_file("local_file.txt").open("rb"),
                            attach=True,
                        )
                    ),
                ],
            },
            return_type=return_type,
        )
        if return_type is None:
            assert isinstance(result, list)
            for entry in result:
                assert isinstance(entry, dict)
            result = Message.de_list(result, bot)
    
        for message, file_name in zip(result, ("text_file.txt", "local_file.txt")):
            assert isinstance(message, Message)
            assert message.chat_id == int(chat_id)
            out = BytesIO()
>           await (await message.document.get_file()).download_to_memory(out)

tests\test_bot.py:4273: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
telegram\_files\file.py:264: in download_to_memory
    buf = await self.get_bot().request.retrieve(
telegram\request\_baserequest.py:254: in retrieve
    return await self._request_wrapper(
tests\auxil\networking.py:48: in _request_wrapper
    return await super()._request_wrapper(
telegram\request\_baserequest.py:334: in _request_wrapper
    code, payload = await self.do_request(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000001BACAA25590>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
            res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )
        except httpx.TimeoutException as err:
            if isinstance(err, httpx.PoolTimeout):
                raise TimedOut(
                    message=(
                        "Pool timeout: All connections in the connection pool are occupied. "
                        "Request was *not* sent to Telegram. Consider adjusting the connection "
                        "pool size or the pool timeout."
                    )
                ) from err
            raise TimedOut from err
        except httpx.HTTPError as err:
            # HTTPError must come last as its the base httpx exception class
            # TODO p4: do something smart here; for now just raise NetworkError
    
            # We include the class name for easier debugging. Especially useful if the error
            # message of `err` is empty.
>           raise NetworkError(f"httpx.{err.__class__.__name__}: {err}") from err
E           telegram.error.NetworkError: httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

telegram\request\_httpxrequest.py:317: NetworkError
tests._files.test_inputfile.TestInputFileWithRequest test_send_bytes

Flake rate in main: 33.02% (Passed 635 times, Failed 313 times)

Stack Traces | 0.755s run time
@contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
>           yield

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:72: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:377: in handle_async_request
    resp = await self._pool.handle_async_request(req)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <AsyncConnectionPool [Requests: 0 active, 0 queued | Connections: 0 active, 1 idle]>
request = <Request [b'GET']>

    async def handle_async_request(self, request: Request) -> Response:
        """
        Send an HTTP request, and return an HTTP response.
    
        This is the core implementation that is called into by `.request()` or `.stream()`.
        """
        scheme = request.url.scheme.decode()
        if scheme == "":
>           raise UnsupportedProtocol(
                "Request URL is missing an 'http://' or 'https://' protocol."
            )
E           httpcore.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpcore\_async\connection_pool.py:167: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000002BEDCB30910>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
>           res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )

telegram\request\_httpxrequest.py:293: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1585: in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1674: in send
    response = await self._send_handling_auth(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1702: in _send_handling_auth
    response = await self._send_handling_redirects(
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1739: in _send_handling_redirects
    response = await self._send_single_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_client.py:1776: in _send_single_request
    response = await transport.handle_async_request(request)
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:376: in handle_async_request
    with map_httpcore_exceptions():
C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\contextlib.py:162: in __exit__
    self.gen.throw(value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    @contextlib.contextmanager
    def map_httpcore_exceptions() -> typing.Iterator[None]:
        try:
            yield
        except Exception as exc:
            mapped_exc = None
    
            for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
                if not isinstance(exc, from_exc):
                    continue
                # We want to map to the most specific exception we can find.
                # Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
                # `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
                if mapped_exc is None or issubclass(to_exc, mapped_exc):
                    mapped_exc = to_exc
    
            if mapped_exc is None:  # pragma: no cover
                raise
    
            message = str(exc)
>           raise mapped_exc(message) from exc
E           httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

C:\hostedtoolcache\windows\Python\3.13.0\x64\Lib\site-packages\httpx\_transports\default.py:89: UnsupportedProtocol

The above exception was the direct cause of the following exception:

self = <tests._files.test_inputfile.TestInputFileWithRequest object at 0x000002BED9DC2850>
bot = PytestExtBot[token=5737018356:AAH138SuiKQF0LDCWsfgWeXfjJ5d63kCWLA]
chat_id = '675666224'

    async def test_send_bytes(self, bot, chat_id):
        # We test this here and not at the respective test modules because it's not worth
        # duplicating the test for the different methods
        message = await bot.send_document(chat_id, data_file("text_file.txt").read_bytes())
        out = BytesIO()
    
>       await (await message.document.get_file()).download_to_memory(out=out)

tests\_files\test_inputfile.py:217: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
telegram\_files\file.py:264: in download_to_memory
    buf = await self.get_bot().request.retrieve(
telegram\request\_baserequest.py:254: in retrieve
    return await self._request_wrapper(
tests\auxil\networking.py:48: in _request_wrapper
    return await super()._request_wrapper(
telegram\request\_baserequest.py:334: in _request_wrapper
    code, payload = await self.do_request(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.auxil.networking.NonchalantHttpxRequest object at 0x000002BEDCB30910>
url = 'None', method = 'GET', request_data = None, read_timeout = 5.0
write_timeout = 5.0, connect_timeout = 5.0, pool_timeout = 1.0

    async def do_request(
        self,
        url: str,
        method: str,
        request_data: Optional[RequestData] = None,
        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
    ) -> tuple[int, bytes]:
        """See :meth:`BaseRequest.do_request`."""
        if self._client.is_closed:
            raise RuntimeError("This HTTPXRequest is not initialized!")
    
        files = request_data.multipart_data if request_data else None
        data = request_data.json_parameters if request_data else None
    
        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
        # created this instance.
        if isinstance(read_timeout, DefaultValue):
            read_timeout = self._client.timeout.read
        if isinstance(connect_timeout, DefaultValue):
            connect_timeout = self._client.timeout.connect
        if isinstance(pool_timeout, DefaultValue):
            pool_timeout = self._client.timeout.pool
    
        if isinstance(write_timeout, DefaultValue):
            write_timeout = self._client.timeout.write if not files else self._media_write_timeout
    
        timeout = httpx.Timeout(
            connect=connect_timeout,
            read=read_timeout,
            write=write_timeout,
            pool=pool_timeout,
        )
    
        try:
            res = await self._client.request(
                method=method,
                url=url,
                headers={"User-Agent": self.USER_AGENT},
                timeout=timeout,
                files=files,
                data=data,
            )
        except httpx.TimeoutException as err:
            if isinstance(err, httpx.PoolTimeout):
                raise TimedOut(
                    message=(
                        "Pool timeout: All connections in the connection pool are occupied. "
                        "Request was *not* sent to Telegram. Consider adjusting the connection "
                        "pool size or the pool timeout."
                    )
                ) from err
            raise TimedOut from err
        except httpx.HTTPError as err:
            # HTTPError must come last as its the base httpx exception class
            # TODO p4: do something smart here; for now just raise NetworkError
    
            # We include the class name for easier debugging. Especially useful if the error
            # message of `err` is empty.
>           raise NetworkError(f"httpx.{err.__class__.__name__}: {err}") from err
E           telegram.error.NetworkError: httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

telegram\request\_httpxrequest.py:317: NetworkError

To view individual test run time comparison to the main branch, go to the Test Analytics Dashboard

Copy link
Member

@Poolitzer Poolitzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Bibo-Joshi Bibo-Joshi added 🔌 enhancement pr description: enhancement and removed enhancement labels Nov 3, 2024
@Bibo-Joshi Bibo-Joshi merged commit dab75fb into master Nov 4, 2024
24 checks passed
@Bibo-Joshi Bibo-Joshi deleted the reply-paid-media branch November 4, 2024 19:33
@github-actions github-actions bot locked and limited conversation to collaborators Nov 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🔌 enhancement pr description: enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants