Skip to content

Support Python 3.14 partial() changes#488

Open
s-t-e-v-e-n-k wants to merge 1 commit intogabrielfalcao:mainfrom
s-t-e-v-e-n-k:support-python-314
Open

Support Python 3.14 partial() changes#488
s-t-e-v-e-n-k wants to merge 1 commit intogabrielfalcao:mainfrom
s-t-e-v-e-n-k:support-python-314

Conversation

@s-t-e-v-e-n-k
Copy link
Copy Markdown

functools.partial() was changed in Python 3.14 to be a method descriptor, which means we need to wrap it in staticmethod now. This change does appear to be backward compatible, so I haven't guarded it with a version check.

functools.partial() was changed in Python 3.14 to be a method
descriptor, which means we need to wrap it in staticmethod now. This
change does appear to be backward compatible, so I haven't guarded it
with a version check.
@mgorny
Copy link
Copy Markdown
Contributor

mgorny commented Apr 15, 2026

Thanks for the patch. However, it seems to be causing a test regression for me (on all implementations, including py3.14):

_____________________________________________________________ test_httpx ______________________________________________________________

    @httpretty.activate(verbose=True, allow_net_connect=False)
    def test_httpx():
        "#414 httpx support"
        httpretty.register_uri(httpretty.GET, "https://blog.falcao.it/",
                               body="Posts")
    
>       response = httpx.get('https://blog.falcao.it')
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


tests/bugfixes/nosetests/test_414_httpx.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.13/site-packages/httpx/_api.py:195: in get
    return request(
        auth       = None
        cookies    = None
        follow_redirects = False
        headers    = None
        params     = None
        proxy      = None
        timeout    = Timeout(timeout=5.0)
        trust_env  = True
        url        = 'https://blog.falcao.it'
        verify     = True
/usr/lib/python3.13/site-packages/httpx/_api.py:102: in request
    with Client(
        auth       = None
        content    = None
        cookies    = None
        data       = None
        files      = None
        follow_redirects = False
        headers    = None
        json       = None
        method     = 'GET'
        params     = None
        proxy      = None
        timeout    = Timeout(timeout=5.0)
        trust_env  = True
        url        = 'https://blog.falcao.it'
        verify     = True
/usr/lib/python3.13/site-packages/httpx/_client.py:688: in __init__
    self._transport = self._init_transport(
        __class__  = <class 'httpx.Client'>
        allow_env_proxies = True
        auth       = None
        base_url   = ''
        cert       = None
        cookies    = None
        default_encoding = 'utf-8'
        event_hooks = None
        follow_redirects = False
        headers    = None
        http1      = True
        http2      = False
        limits     = Limits(max_connections=100, max_keepalive_connections=20, keepalive_expiry=5.0)
        max_redirects = 20
        mounts     = None
        params     = None
        proxy      = None
        proxy_map  = {}
        self       = <httpx.Client object at 0x7fae15c342f0>
        timeout    = Timeout(timeout=5.0)
        transport  = None
        trust_env  = True
        verify     = True
/usr/lib/python3.13/site-packages/httpx/_client.py:731: in _init_transport
    return HTTPTransport(
        cert       = None
        http1      = True
        http2      = False
        limits     = Limits(max_connections=100, max_keepalive_connections=20, keepalive_expiry=5.0)
        self       = <httpx.Client object at 0x7fae15c342f0>
        transport  = None
        trust_env  = True
        verify     = True
/usr/lib/python3.13/site-packages/httpx/_transports/default.py:150: in __init__
    import httpcore
        cert       = None
        http1      = True
        http2      = False
        limits     = Limits(max_connections=100, max_keepalive_connections=20, keepalive_expiry=5.0)
        local_address = None
        proxy      = None
        retries    = 0
        self       = <httpx.HTTPTransport object at 0x7fae15c34980>
        socket_options = None
        trust_env  = True
        uds        = None
        verify     = True
/usr/lib/python3.13/site-packages/httpcore/__init__.py:1: in <module>
    from ._api import request, stream
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/httpcore/__pycache__/__init__.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/httpcore/__init__.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15704d10>
        __name__   = 'httpcore'
        __package__ = 'httpcore'
        __path__   = ['/usr/lib/python3.13/site-packages/httpcore']
        __spec__   = ModuleSpec(name='httpcore', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15704d10>, origin='/usr/lib/python3.13/site-packages/httpcore/__init__.py', submodule_search_locations=['/usr/lib/python3.13/site-packages/httpcore'])
        _backends  = <module 'httpcore._backends' from '/usr/lib/python3.13/site-packages/httpcore/_backends/__init__.py'>
        _exceptions = <module 'httpcore._exceptions' from '/usr/lib/python3.13/site-packages/httpcore/_exceptions.py'>
        _models    = <module 'httpcore._models' from '/usr/lib/python3.13/site-packages/httpcore/_models.py'>
        _ssl       = <module 'httpcore._ssl' from '/usr/lib/python3.13/site-packages/httpcore/_ssl.py'>
        _utils     = <module 'httpcore._utils' from '/usr/lib/python3.13/site-packages/httpcore/_utils.py'>
/usr/lib/python3.13/site-packages/httpcore/_api.py:7: in <module>
    from ._sync.connection_pool import ConnectionPool
        Extensions = typing.MutableMapping[str, typing.Any]
        HeaderTypes = typing.Union[typing.Sequence[typing.Tuple[typing.Union[str, bytes], typing.Union[str, bytes]]], typing.Mapping[typing.Union[bytes, str], typing.Union[bytes, str]], NoneType]
        Response   = <class 'httpcore._models.Response'>
        URL        = <class 'httpcore._models.URL'>
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/httpcore/__pycache__/_api.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/httpcore/_api.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15705010>
        __name__   = 'httpcore._api'
        __package__ = 'httpcore'
        __spec__   = ModuleSpec(name='httpcore._api', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15705010>, origin='/usr/lib/python3.13/site-packages/httpcore/_api.py')
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        contextlib = <module 'contextlib' from '/usr/lib/python3.13/contextlib.py'>
        typing     = <module 'typing' from '/usr/lib/python3.13/typing.py'>
/usr/lib/python3.13/site-packages/httpcore/_sync/__init__.py:1: in <module>
    from .connection import HTTPConnection
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/httpcore/_sync/__pycache__/__init__.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/httpcore/_sync/__init__.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15705c70>
        __name__   = 'httpcore._sync'
        __package__ = 'httpcore._sync'
        __path__   = ['/usr/lib/python3.13/site-packages/httpcore/_sync']
        __spec__   = ModuleSpec(name='httpcore._sync', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15705c70>, origin='/usr/lib/python3.13/site-packages/httpcore/_sync/__init__.py', submodule_search_locations=['/usr/lib/python3.13/site-packages/httpcore/_sync'])
/usr/lib/python3.13/site-packages/httpcore/_sync/connection.py:14: in <module>
    from .._synchronization import Lock
        ConnectError = <class 'httpcore._exceptions.ConnectError'>
        ConnectTimeout = <class 'httpcore._exceptions.ConnectTimeout'>
        NetworkBackend = <class 'httpcore._backends.base.NetworkBackend'>
        NetworkStream = <class 'httpcore._backends.base.NetworkStream'>
        Origin     = <class 'httpcore._models.Origin'>
        Request    = <class 'httpcore._models.Request'>
        Response   = <class 'httpcore._models.Response'>
        SOCKET_OPTION = typing.Union[typing.Tuple[int, int, int], typing.Tuple[int, int, typing.Union[bytes, bytearray]], typing.Tuple[int, int, NoneType, int]]
        SyncBackend = <class 'httpcore._backends.sync.SyncBackend'>
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/httpcore/_sync/__pycache__/connection.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/httpcore/_sync/connection.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15705d90>
        __name__   = 'httpcore._sync.connection'
        __package__ = 'httpcore._sync'
        __spec__   = ModuleSpec(name='httpcore._sync.connection', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15705d90>, origin='/usr/lib/python3.13/site-packages/httpcore/_sync/connection.py')
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        default_ssl_context = <function default_ssl_context at 0x7fae157118a0>
        itertools  = <module 'itertools' (built-in)>
        logging    = <module 'logging' from '/usr/lib/python3.13/logging/__init__.py'>
        ssl        = <module 'ssl' from '/usr/lib/python3.13/ssl.py'>
        types      = <module 'types' from '/usr/lib/python3.13/types.py'>
        typing     = <module 'typing' from '/usr/lib/python3.13/typing.py'>
/usr/lib/python3.13/site-packages/httpcore/_synchronization.py:12: in <module>
    import trio
        ExceptionMapping = typing.Mapping[typing.Type[Exception], typing.Type[Exception]]
        PoolTimeout = <class 'httpcore._exceptions.PoolTimeout'>
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/httpcore/__pycache__/_synchronization.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/httpcore/_synchronization.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15706690>
        __name__   = 'httpcore._synchronization'
        __package__ = 'httpcore'
        __spec__   = ModuleSpec(name='httpcore._synchronization', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15706690>, origin='/usr/lib/python3.13/site-packages/httpcore/_synchronization.py')
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        map_exceptions = <function map_exceptions at 0x7fae15c63f60>
        threading  = <module 'threading' from '/usr/lib/python3.13/threading.py'>
        types      = <module 'types' from '/usr/lib/python3.13/types.py'>
/usr/lib/python3.13/site-packages/trio/__init__.py:25: in <module>
    from . import abc, from_thread, lowlevel, socket, to_thread
        TASK_STATUS_IGNORED = TASK_STATUS_IGNORED
        TYPE_CHECKING = False
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/trio/__pycache__/__init__.cpython-313.pyc'
        __doc__    = 'Trio - A friendly Python library for async concurrency and I/O'
        __file__   = '/usr/lib/python3.13/site-packages/trio/__init__.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae15706870>
        __name__   = 'trio'
        __package__ = 'trio'
        __path__   = ['/usr/lib/python3.13/site-packages/trio']
        __spec__   = ModuleSpec(name='trio', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae15706870>, origin='/usr/lib/python3.13/site-packages/trio/__init__.py', submodule_search_locations=['/usr/lib/python3.13/site-packages/trio'])
        _abc       = <module 'trio._abc' from '/usr/lib/python3.13/site-packages/trio/_abc.py'>
        _core      = <module 'trio._core' from '/usr/lib/python3.13/site-packages/trio/_core/__init__.py'>
        _deprecate = <module 'trio._deprecate' from '/usr/lib/python3.13/site-packages/trio/_deprecate.py'>
        _highlevel_generic = <module 'trio._highlevel_generic' from '/usr/lib/python3.13/site-packages/trio/_highlevel_generic.py'>
        _subprocess = <module 'trio._subprocess' from '/usr/lib/python3.13/site-packages/trio/_subprocess.py'>
        _subprocess_platform = <module 'trio._subprocess_platform' from '/usr/lib/python3.13/site-packages/trio/_subprocess_platform/__init__.py'>
        _sync      = <module 'trio._sync' from '/usr/lib/python3.13/site-packages/trio/_sync.py'>
        _threads   = <module 'trio._threads' from '/usr/lib/python3.13/site-packages/trio/_threads.py'>
        _unix_pipes = <module 'trio._unix_pipes' from '/usr/lib/python3.13/site-packages/trio/_unix_pipes.py'>
        _util      = <module 'trio._util' from '/usr/lib/python3.13/site-packages/trio/_util.py'>
        abc        = <module 'trio.abc' from '/usr/lib/python3.13/site-packages/trio/abc.py'>
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        from_thread = <module 'trio.from_thread' from '/usr/lib/python3.13/site-packages/trio/from_thread.py'>
        lowlevel   = <module 'trio.lowlevel' from '/usr/lib/python3.13/site-packages/trio/lowlevel.py'>
/usr/lib/python3.13/site-packages/trio/socket.py:16: in <module>
    from . import _socket
        __annotations__ = {}
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/trio/__pycache__/socket.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/trio/socket.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae153f0cb0>
        __name__   = 'trio.socket'
        __package__ = 'trio'
        __spec__   = ModuleSpec(name='trio.socket', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae153f0cb0>, origin='/usr/lib/python3.13/site-packages/trio/socket.py')
        _stdlib_socket = <module 'socket' from '/usr/lib/python3.13/socket.py'>
        _t         = <module 'typing' from '/usr/lib/python3.13/typing.py'>
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        sys        = <module 'sys' (built-in)>
/usr/lib/python3.13/site-packages/trio/_socket.py:546: in <module>
    class SocketType:
        AddressFamily = <enum 'AddressFamily'>
        AddressFormat = typing.Any
        Any        = typing.Any
        Concatenate = typing.Concatenate
        FamilyDefault = None
        FamilyT    = int | socket.AddressFamily | None
        SocketKind = <enum 'SocketKind'>
        SupportsIndex = <class 'typing.SupportsIndex'>
        T          = ~T
        TYPE_CHECKING = False
        TypeAlias  = typing.TypeAlias
        TypeT      = httpretty.core.fakesock.socket | int
        TypeVar    = <class 'typing.TypeVar'>
        _NUMERIC_ONLY = <AddressInfo.AI_NUMERICHOST|AI_NUMERICSERV: 1028>
        _SOCK_TYPE_MASK = -526337
        __annotations__ = {'AddressFormat': 'TypeAlias',
 'FamilyDefault': 'None',
 'FamilyT': 'TypeAlias',
 'TypeT': 'TypeAlias',
 '_resolver': '_core.RunVar[HostnameResolver | None]',
 '_socket_factory': '_core.RunVar[SocketFactory | None]'}
        __builtins__ = <builtins>
        __cached__ = '/usr/lib/python3.13/site-packages/trio/__pycache__/_socket.cpython-313.pyc'
        __doc__    = None
        __file__   = '/usr/lib/python3.13/site-packages/trio/_socket.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fae153f15b0>
        __name__   = 'trio._socket'
        __package__ = 'trio'
        __spec__   = ModuleSpec(name='trio._socket', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fae153f15b0>, origin='/usr/lib/python3.13/site-packages/trio/_socket.py')
        _core      = <module 'trio._core' from '/usr/lib/python3.13/site-packages/trio/_core/__init__.py'>
        _idna      = <module 'idna' from '/usr/lib/python3.13/site-packages/idna/__init__.py'>
        _make_simple_sock_method_wrapper = <function _make_simple_sock_method_wrapper at 0x7fae153fcf40>
        _resolve_address_nocp = <function _resolve_address_nocp at 0x7fae153fcfe0>
        _resolver  = <RunVar name='hostname_resolver'>
        _sniff_sockopts_for_fileno = <function _sniff_sockopts_for_fileno at 0x7fae153fcea0>
        _socket_factory = <RunVar name='socket_factory'>
        _stdlib_socket = <module 'socket' from '/usr/lib/python3.13/socket.py'>
        _try_sync  = <class 'trio._socket._try_sync'>
        _wraps     = <function wraps at 0x7fae19fef100>
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        from_stdlib_socket = <function from_stdlib_socket at 0x7fae153fcc20>
        fromfd     = <function fromfd at 0x7fae153fccc0>
        getaddrinfo = <function getaddrinfo at 0x7fae153fca40>
        getnameinfo = <function getnameinfo at 0x7fae153fcae0>
        getprotobyname = <function getprotobyname at 0x7fae153fcb80>
        index      = <built-in function index>
        os         = <module 'os' (frozen)>
        overload   = <function overload at 0x7fae19df51c0>
        select     = <module 'select' from '/usr/lib/python3.13/lib-dynload/select.cpython-313-x86_64-linux-gnu.so'>
        set_custom_hostname_resolver = <function set_custom_hostname_resolver at 0x7fae153fc220>
        set_custom_socket_factory = <function set_custom_socket_factory at 0x7fae153fc9a0>
        socket     = <function socket at 0x7fae153fce00>
        socketpair = <function socketpair at 0x7fae153fcd60>
        sys        = <module 'sys' (built-in)>
        trio       = <module 'trio' from '/usr/lib/python3.13/site-packages/trio/__init__.py'>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    class SocketType:
        def __init__(self) -> None:
            # make sure this __init__ works with multiple inheritance
            super().__init__()
            # and only raises error if it's directly constructed
            if type(self) is SocketType:
                raise TypeError(
                    "SocketType is an abstract class; use trio.socket.socket if you "
                    "want to construct a socket object",
                )
    
        def detach(self) -> int:
            raise NotImplementedError
    
        def fileno(self) -> int:
            raise NotImplementedError
    
        def getpeername(self) -> AddressFormat:
            raise NotImplementedError
    
        def getsockname(self) -> AddressFormat:
            raise NotImplementedError
    
        @overload
        def getsockopt(self, level: int, optname: int) -> int: ...
    
        @overload
        def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ...
    
        def getsockopt(
            self,
            level: int,
            optname: int,
            buflen: int | None = None,
        ) -> int | bytes:
            raise NotImplementedError
    
        @overload
        def setsockopt(self, level: int, optname: int, value: int | Buffer) -> None: ...
    
        @overload
        def setsockopt(
            self,
            level: int,
            optname: int,
            value: None,
            optlen: int,
        ) -> None: ...
    
        def setsockopt(
            self,
            level: int,
            optname: int,
            value: int | Buffer | None,
            optlen: int | None = None,
        ) -> None:
            raise NotImplementedError
    
        def listen(self, backlog: int = min(_stdlib_socket.SOMAXCONN, 128)) -> None:
            raise NotImplementedError
    
        def get_inheritable(self) -> bool:
            raise NotImplementedError
    
        def set_inheritable(self, inheritable: bool) -> None:
            raise NotImplementedError
    
        if sys.platform == "win32" or (
            not TYPE_CHECKING and hasattr(_stdlib_socket.socket, "share")
        ):
    
            def share(self, process_id: int) -> bytes:
                raise NotImplementedError
    
        def __enter__(self) -> Self:
            raise NotImplementedError
    
        def __exit__(
            self,
            exc_type: type[BaseException] | None,
            exc_value: BaseException | None,
            traceback: TracebackType | None,
        ) -> None:
            raise NotImplementedError
    
        @property
        def family(self) -> AddressFamily:
            raise NotImplementedError
    
        @property
        def type(self) -> SocketKind:
            raise NotImplementedError
    
        @property
        def proto(self) -> int:
            raise NotImplementedError
    
        @property
        def did_shutdown_SHUT_WR(self) -> bool:
            """Return True if the socket has been shut down with the SHUT_WR flag"""
            raise NotImplementedError
    
        def __repr__(self) -> str:
            raise NotImplementedError
    
        def dup(self) -> SocketType:
            raise NotImplementedError
    
        def close(self) -> None:
            raise NotImplementedError
    
        async def bind(self, address: AddressFormat) -> None:
            raise NotImplementedError
    
        def shutdown(self, flag: int) -> None:
            raise NotImplementedError
    
        def is_readable(self) -> bool:
            """Return True if the socket is readable. This is checked with `select.select` on Windows, otherwise `select.poll`."""
            raise NotImplementedError
    
        async def wait_writable(self) -> None:
            """Convenience method that calls trio.lowlevel.wait_writable for the object."""
            raise NotImplementedError
    
        async def accept(self) -> tuple[SocketType, AddressFormat]:
            raise NotImplementedError
    
        async def connect(self, address: AddressFormat) -> None:
            raise NotImplementedError
    
        def recv(self, buflen: int, flags: int = 0, /) -> Awaitable[bytes]:
            raise NotImplementedError
    
        def recv_into(
            self,
            buffer: Buffer,
            nbytes: int = 0,
            flags: int = 0,
        ) -> Awaitable[int]:
            raise NotImplementedError
    
        # return type of socket.socket.recvfrom in typeshed is tuple[bytes, Any]
        def recvfrom(
            self,
            bufsize: int,
            flags: int = 0,
            /,
        ) -> Awaitable[tuple[bytes, AddressFormat]]:
            raise NotImplementedError
    
        # return type of socket.socket.recvfrom_into in typeshed is tuple[bytes, Any]
        def recvfrom_into(
            self,
            buffer: Buffer,
            nbytes: int = 0,
            flags: int = 0,
        ) -> Awaitable[tuple[int, AddressFormat]]:
            raise NotImplementedError
    
        if sys.platform != "win32" or (
            not TYPE_CHECKING and hasattr(_stdlib_socket.socket, "recvmsg")
        ):
    
            def recvmsg(
                self,
                bufsize: int,
                ancbufsize: int = 0,
                flags: int = 0,
                /,
            ) -> Awaitable[tuple[bytes, list[tuple[int, int, bytes]], int, object]]:
                raise NotImplementedError
    
        if sys.platform != "win32" or (
            not TYPE_CHECKING and hasattr(_stdlib_socket.socket, "recvmsg_into")
        ):
    
            def recvmsg_into(
                self,
                buffers: Iterable[Buffer],
                ancbufsize: int = 0,
                flags: int = 0,
                /,
            ) -> Awaitable[tuple[int, list[tuple[int, int, bytes]], int, object]]:
                raise NotImplementedError
    
        def send(self, bytes: Buffer, flags: int = 0, /) -> Awaitable[int]:
            raise NotImplementedError
    
        @overload
        async def sendto(
            self,
            data: Buffer,
            address: tuple[object, ...] | str | Buffer,
            /,
        ) -> int: ...
    
        @overload
        async def sendto(
            self,
            data: Buffer,
            flags: int,
            address: tuple[object, ...] | str | Buffer,
            /,
        ) -> int: ...
    
        async def sendto(self, *args: object) -> int:
            raise NotImplementedError
    
        if sys.platform != "win32" or (
            not TYPE_CHECKING and hasattr(_stdlib_socket.socket, "sendmsg")
        ):
    
>           @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E           AttributeError: type object 'socket' has no attribute 'sendmsg'

__enter__  = <function SocketType.__enter__ at 0x7fae153fdb20>
__exit__   = <function SocketType.__exit__ at 0x7fae153fdbc0>
__firstlineno__ = 546
__init__   = <function SocketType.__init__ at 0x7fae153fd120>
__module__ = 'trio._socket'
__qualname__ = 'SocketType'
__repr__   = <function SocketType.__repr__ at 0x7fae153fdee0>
accept     = <function SocketType.accept at 0x7fae153fe340>
bind       = <function SocketType.bind at 0x7fae153fe0c0>
close      = <function SocketType.close at 0x7fae153fe020>
connect    = <function SocketType.connect at 0x7fae153fe3e0>
detach     = <function SocketType.detach at 0x7fae153fd1c0>
did_shutdown_SHUT_WR = <property object at 0x7fae1270a2a0>
dup        = <function SocketType.dup at 0x7fae153fdf80>
family     = <property object at 0x7fae127098a0>
fileno     = <function SocketType.fileno at 0x7fae153fd260>
get_inheritable = <function SocketType.get_inheritable at 0x7fae153fd9e0>
getpeername = <function SocketType.getpeername at 0x7fae153fd300>
getsockname = <function SocketType.getsockname at 0x7fae153fd3a0>
getsockopt = <function SocketType.getsockopt at 0x7fae153fd620>
is_readable = <function SocketType.is_readable at 0x7fae153fe200>
listen     = <function SocketType.listen at 0x7fae153fd940>
proto      = <property object at 0x7fae1270a250>
recv       = <function SocketType.recv at 0x7fae153fe480>
recv_into  = <function SocketType.recv_into at 0x7fae153fe520>
recvfrom   = <function SocketType.recvfrom at 0x7fae153fe5c0>
recvfrom_into = <function SocketType.recvfrom_into at 0x7fae153fe660>
recvmsg    = <function SocketType.recvmsg at 0x7fae153fe700>
recvmsg_into = <function SocketType.recvmsg_into at 0x7fae153fe7a0>
send       = <function SocketType.send at 0x7fae153fe840>
sendto     = <function SocketType.sendto at 0x7fae153feac0>
set_inheritable = <function SocketType.set_inheritable at 0x7fae153fda80>
setsockopt = <function SocketType.setsockopt at 0x7fae153fd8a0>
shutdown   = <function SocketType.shutdown at 0x7fae153fe160>
type       = <property object at 0x7fae1270a200>
wait_writable = <function SocketType.wait_writable at 0x7fae153fe2a0>

/usr/lib/python3.13/site-packages/trio/_socket.py:759: AttributeError

Ofc it's possible that it's just uncovering an existing issue…

@s-t-e-v-e-n-k
Copy link
Copy Markdown
Author

My build environment building for Python 3.11, Python 3.13 and Python 3.14 gives me:

[   29s] tests/bugfixes/nosetests/test_414_httpx.py::test_httpx PASSED            [  0%]
[   51s] tests/bugfixes/nosetests/test_414_httpx.py::test_httpx PASSED            [  0%]
[   76s] tests/bugfixes/nosetests/test_414_httpx.py::test_httpx PASSED            [  0%]

@mgorny
Copy link
Copy Markdown
Contributor

mgorny commented Apr 17, 2026

Ah, sorry, my bad. I have accidentally disabled pytest-httpx plugin. Now they pass fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants