From 7a4675725199788c4052286b3c6752c59ad072bc Mon Sep 17 00:00:00 2001 From: Shaurya Singh Date: Tue, 26 May 2026 14:53:00 -0700 Subject: [PATCH] docs(SSL): restore socket-derived attributes on Connection page (#1465) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Connection API page lost every `socket.socket`-derived method (`bind`, `listen`, `fileno`, `getsockname`, `getpeername`, `setsockopt`, etc.) when the doc migrated to `autoclass`. Those methods are not defined on `OpenSSL.SSL.Connection`; they are delegated at runtime through `__getattr__` to the wrapped socket, so Sphinx's autoclass introspection cannot see them. `bind()` in particular has been in use on `Connection` since Cheroot 2006 and was documented through v17.5.0, but https://www.pyopenssl.org/en/26.2.0/api/ssl.html now lists none of them — exactly the gap @webknjaz tracked to commit 737e89a. Add an explicit listing of the most-used forwarded methods under the `autoclass` block, with one-line descriptions and `:py:meth:` links back to the `socket.socket` reference docs. Also note that any other socket attribute is reachable the same way, and that new server-side code should generally bind the underlying socket directly rather than go through the Connection proxy (per the issue's second action item). Docs build with `-W` (warnings-as-errors) is clean; the rendered `api/ssl.html` now contains `Connection.bind`, `Connection.listen`, `Connection.fileno`, and the other forwarded entries. No code change; behavior is unaffected. --- doc/api/ssl.rst | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index ea7416d53..8721a58bc 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -261,6 +261,77 @@ Connection objects have the following methods: :members: +In addition to the methods documented above, :py:class:`Connection` +forwards undefined attribute access through :py:meth:`object.__getattr__` +to the underlying socket passed to its constructor. This makes the +standard :py:class:`socket.socket` server-side helpers available +directly on a TLS connection. The most frequently used ones are +listed here for discoverability — they behave exactly like their +:py:class:`socket.socket` counterparts and are documented in +the standard library: + +.. py:method:: Connection.bind(address) + + Forwarded to :py:meth:`socket.socket.bind` on the wrapped socket. + Most server-side TLS code starts by binding the connection (or its + underlying socket) to a listening address. + +.. py:method:: Connection.listen([backlog]) + + Forwarded to :py:meth:`socket.socket.listen` on the wrapped socket. + +.. py:method:: Connection.fileno() + + Forwarded to :py:meth:`socket.socket.fileno` on the wrapped socket. + +.. py:method:: Connection.getsockname() + + Forwarded to :py:meth:`socket.socket.getsockname` on the wrapped + socket. + +.. py:method:: Connection.getpeername() + + Forwarded to :py:meth:`socket.socket.getpeername` on the wrapped + socket. + +.. py:method:: Connection.setsockopt(level, optname, value) + + Forwarded to :py:meth:`socket.socket.setsockopt` on the wrapped + socket. + +.. py:method:: Connection.getsockopt(level, optname[, buflen]) + + Forwarded to :py:meth:`socket.socket.getsockopt` on the wrapped + socket. + +.. py:method:: Connection.gettimeout() + + Forwarded to :py:meth:`socket.socket.gettimeout` on the wrapped + socket. + +.. py:method:: Connection.settimeout(value) + + Forwarded to :py:meth:`socket.socket.settimeout` on the wrapped + socket. + +.. py:method:: Connection.setblocking(flag) + + Forwarded to :py:meth:`socket.socket.setblocking` on the wrapped + socket. + +.. py:method:: Connection.getblocking() + + Forwarded to :py:meth:`socket.socket.getblocking` on the wrapped + socket. + +Any other attribute defined on the wrapped :py:class:`socket.socket` +is also accessible the same way. Server-side code generally prefers +binding the underlying socket directly and handing the bound socket +to :py:class:`Connection`; binding through the :py:class:`Connection` +proxy is supported for historical reasons (see Cheroot and other +pre-2018 callers) but adds no functionality. + + .. Rubric:: Footnotes .. [#connection-context-socket] Actually, all that is required is an object that