From dcda91a86459858755629eb70deba17af31815f1 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 14 Oct 2025 20:28:43 +0100 Subject: [PATCH 1/3] Commit --- Doc/deprecations/pending-removal-in-3.20.rst | 3 +- Doc/whatsnew/3.15.rst | 3 +- Lib/test/test_zlib.py | 10 ++++++ ...5-10-14-20-27-06.gh-issue-76007.2NcUbo.rst | 2 ++ Modules/zlibmodule.c | 34 ++++++++++++++++++- 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-10-14-20-27-06.gh-issue-76007.2NcUbo.rst diff --git a/Doc/deprecations/pending-removal-in-3.20.rst b/Doc/deprecations/pending-removal-in-3.20.rst index 8bc863b185d921..c86979c8ff91e9 100644 --- a/Doc/deprecations/pending-removal-in-3.20.rst +++ b/Doc/deprecations/pending-removal-in-3.20.rst @@ -19,5 +19,6 @@ Pending removal in Python 3.20 - :mod:`tabnanny` - :mod:`tkinter.font` - :mod:`tkinter.ttk` + - :mod:`zlib` - (Contributed by Hugo van Kemenade in :gh:`76007`.) + (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index c5321ee9983625..8a7577244429cb 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -828,8 +828,9 @@ New deprecations - :mod:`tabnanny` - :mod:`tkinter.font` - :mod:`tkinter.ttk` + - :mod:`zlib` - (Contributed by Hugo van Kemenade in :gh:`76007`.) + (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) .. Add deprecations above alphabetically, not here at the end. diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index c57ab51eca16b4..ed9d85408159b2 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -1222,5 +1222,15 @@ def __index__(self): return 100 +class TestModule(unittest.TestCase): + def test_deprecated__version__(self): + with self.assertWarnsRegex( + DeprecationWarning, + "'__version__' is deprecated and slated for removal in Python 3.20", + ) as cm: + getattr(zlib, "__version__") + self.assertEqual(cm.filename, __file__) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2025-10-14-20-27-06.gh-issue-76007.2NcUbo.rst b/Misc/NEWS.d/next/Library/2025-10-14-20-27-06.gh-issue-76007.2NcUbo.rst new file mode 100644 index 00000000000000..567fb5ef90475c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-14-20-27-06.gh-issue-76007.2NcUbo.rst @@ -0,0 +1,2 @@ +:mod:`zlib`: Deprecate ``__version__`` and schedule for removal in Python +3.20. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index f1312e687da71c..00151231d6c4ec 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -2137,6 +2137,30 @@ zlib_free(void *mod) zlib_clear((PyObject *)mod); } +static PyObject * +zlib_getattr(PyObject *self, PyObject *args) +{ + PyObject *name; + if (!PyArg_UnpackTuple(args, "__getattr__", 1, 1, &name)) { + return NULL; + } + + if (PyUnicode_Check(name)) { + const char *name_str = PyUnicode_AsUTF8(name); + if (name_str && strcmp(name_str, "__version__") == 0) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "'__version__' is deprecated and slated for removal in Python 3.20", + 1) < 0) { + return NULL; + } + return PyUnicode_FromString("1.0"); + } + } + + PyErr_Format(PyExc_AttributeError, "module 'zlib' has no attribute %R", name); + return NULL; +} + static int zlib_exec(PyObject *mod) { @@ -2221,9 +2245,17 @@ zlib_exec(PyObject *mod) return -1; } #endif - if (PyModule_AddStringConstant(mod, "__version__", "1.0") < 0) { + static PyMethodDef getattr_method = {"__getattr__", zlib_getattr, METH_VARARGS, "Module __getattr__"}; + PyObject *getattr_func = PyCFunction_New(&getattr_method, mod); + if (getattr_func == NULL) { + return -1; + } + + if (PyModule_AddObjectRef(mod, "__getattr__", getattr_func) < 0) { + Py_DECREF(getattr_func); return -1; } + Py_DECREF(getattr_func); return 0; } From 4aeea1ac75b8fd3adccf69611631fc00e905b58a Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Wed, 15 Oct 2025 07:45:51 +0100 Subject: [PATCH 2/3] Victor's review --- Modules/zlibmodule.c | 56 +++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 00151231d6c4ec..5d4e9bd16bc863 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -2015,6 +2015,27 @@ zlib_crc32_combine_impl(PyObject *module, unsigned int crc1, return crc32_combine(crc1, crc2, len); } +static PyObject * +zlib_getattr(PyObject *self, PyObject *args) +{ + PyObject *name; + if (!PyArg_UnpackTuple(args, "__getattr__", 1, 1, &name)) { + return NULL; + } + + if (PyUnicode_Check(name) && PyUnicode_EqualToUTF8(name, "__version__")) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "'__version__' is deprecated and slated for removal in Python 3.20", + 1) < 0) { + return NULL; + } + return PyUnicode_FromString("1.0"); + } + + PyErr_Format(PyExc_AttributeError, "module 'zlib' has no attribute %R", name); + return NULL; +} + static PyMethodDef zlib_methods[] = { ZLIB_ADLER32_METHODDEF @@ -2025,6 +2046,7 @@ static PyMethodDef zlib_methods[] = ZLIB_CRC32_COMBINE_METHODDEF ZLIB_DECOMPRESS_METHODDEF ZLIB_DECOMPRESSOBJ_METHODDEF + {"__getattr__", zlib_getattr, METH_VARARGS, "Module __getattr__"}, {NULL, NULL} }; @@ -2137,29 +2159,6 @@ zlib_free(void *mod) zlib_clear((PyObject *)mod); } -static PyObject * -zlib_getattr(PyObject *self, PyObject *args) -{ - PyObject *name; - if (!PyArg_UnpackTuple(args, "__getattr__", 1, 1, &name)) { - return NULL; - } - - if (PyUnicode_Check(name)) { - const char *name_str = PyUnicode_AsUTF8(name); - if (name_str && strcmp(name_str, "__version__") == 0) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "'__version__' is deprecated and slated for removal in Python 3.20", - 1) < 0) { - return NULL; - } - return PyUnicode_FromString("1.0"); - } - } - - PyErr_Format(PyExc_AttributeError, "module 'zlib' has no attribute %R", name); - return NULL; -} static int zlib_exec(PyObject *mod) @@ -2245,17 +2244,6 @@ zlib_exec(PyObject *mod) return -1; } #endif - static PyMethodDef getattr_method = {"__getattr__", zlib_getattr, METH_VARARGS, "Module __getattr__"}; - PyObject *getattr_func = PyCFunction_New(&getattr_method, mod); - if (getattr_func == NULL) { - return -1; - } - - if (PyModule_AddObjectRef(mod, "__getattr__", getattr_func) < 0) { - Py_DECREF(getattr_func); - return -1; - } - Py_DECREF(getattr_func); return 0; } From 37ceee0d79c56cd3cf5191b77835c179389e53a1 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Wed, 15 Oct 2025 07:54:55 +0100 Subject: [PATCH 3/3] Remove accidental line --- Modules/zlibmodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 5d4e9bd16bc863..a6e3084f84a663 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -2159,7 +2159,6 @@ zlib_free(void *mod) zlib_clear((PyObject *)mod); } - static int zlib_exec(PyObject *mod) {