diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index 6f6954b783a1ae..36c2923da6d132 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -39,6 +39,10 @@ Pending removal in Python 3.16 It has not been used by any function in :mod:`!shutil` since Python 3.4, and is now an alias of :exc:`RuntimeError`. +* :mod:`socket`: + :class:`socket.SocketType`: use :class:`socket.socket` type instead. + (Contributed by James Roy in :gh:`88427`.) + * :mod:`symtable`: * The :meth:`Class.get_methods ` method diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 58323ba6514eac..bc1579063f0cef 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -913,6 +913,9 @@ The following functions all create :ref:`socket objects `. This is a Python type object that represents the socket object type. It is the same as ``type(socket(...))``. + .. deprecated:: next + Use :class:`socket.socket` type instead. + Other functions ''''''''''''''' diff --git a/Lib/socket.py b/Lib/socket.py index be37c24d6174a2..ff4e48c648eba2 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -69,6 +69,11 @@ "has_dualstack_ipv6", "AddressFamily", "SocketKind"] __all__.extend(os._get_exports_list(_socket)) +def __getattr__(name): + if name == "SocketType": + return _socket.SocketType + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + # Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for # nicer string representations. # Note that _socket only knows about the integer values. The public interface diff --git a/Misc/NEWS.d/next/Library/2024-11-01-20-09-53.gh-issue-88427.chYNT6.rst b/Misc/NEWS.d/next/Library/2024-11-01-20-09-53.gh-issue-88427.chYNT6.rst new file mode 100644 index 00000000000000..92564c590726b5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-01-20-09-53.gh-issue-88427.chYNT6.rst @@ -0,0 +1 @@ +:attr:`!socket.SocketType` is now deprecated and planned to be removed in Python 3.16. Use :class:`socket.socket` instead. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 9394f1c940bedf..b50226d618c9ee 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -5611,6 +5611,20 @@ static PyType_Spec sock_spec = { .slots = sock_slots, }; +static PyObject* +socket_getattr(PyObject *self, PyObject *name) +{ + if (PyUnicode_EqualToUTF8(name, "SocketType")) { + socket_state *state = get_module_state(self); + PyErr_Warn(PyExc_DeprecationWarning, "_socket.SocketType is deprecated and " + "will be removed in Python 3.16. " + "Use socket.socket instead"); + return state != NULL ? (PyObject *)state->sock_type : NULL; + } + + PyErr_Format(PyExc_AttributeError, "module _socket has no attribute '%U'", name); + return NULL; +} #ifdef HAVE_GETHOSTNAME /* Python interface to gethostname(). */ @@ -7216,6 +7230,7 @@ range of values."); /* List of functions exported by this module. */ static PyMethodDef socket_methods[] = { + {"__getattr__", socket_getattr, METH_O, "Module __getattr__"}, #ifdef HAVE_GETADDRINFO {"gethostbyname", socket_gethostbyname, METH_VARARGS, gethostbyname_doc}, @@ -7468,9 +7483,6 @@ socket_exec(PyObject *m) goto error; } state->sock_type = (PyTypeObject *)sock_type; - if (PyModule_AddObjectRef(m, "SocketType", sock_type) < 0) { - goto error; - } if (PyModule_AddType(m, state->sock_type) < 0) { goto error; }