From 9248f114162618ba8492148eb09bdcd95f5e4b9f Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 6 Nov 2025 21:17:34 +0000 Subject: [PATCH 01/10] Remove use of a helper API removed in Python 3.13. --- src/_apachemodule.c | 7 ------- src/include/_apachemodule.h | 1 - src/mod_python.c | 14 ++++++++------ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/_apachemodule.c b/src/_apachemodule.c index 1f888e96..5ba1f5da 100644 --- a/src/_apachemodule.c +++ b/src/_apachemodule.c @@ -852,13 +852,6 @@ PyObject *_apache_module_init() m = Py_InitModule("_apache", _apache_module_methods); #else m = PyModule_Create(&_apache_moduledef); - PyObject *name = PyUnicode_FromString("_apache"); - - _PyImport_FixupExtensionObject(m, name, name -#if PY_MINOR_VERSION >= 7 - ,PyImport_GetModuleDict() -#endif - ); #endif d = PyModule_GetDict(m); Mp_ServerReturn = PyErr_NewException("_apache.SERVER_RETURN", NULL, NULL); diff --git a/src/include/_apachemodule.h b/src/include/_apachemodule.h index da2f625a..35ee6754 100644 --- a/src/include/_apachemodule.h +++ b/src/include/_apachemodule.h @@ -29,6 +29,5 @@ */ PyObject *get_ServerReturn(void); -PyMODINIT_FUNC init_apache(void); #endif /* !Mp_APACHEMODULE_H */ diff --git a/src/mod_python.c b/src/mod_python.c index 44873c10..55bc2962 100644 --- a/src/mod_python.c +++ b/src/mod_python.c @@ -69,12 +69,6 @@ static PyObject * make_obcallback(const char *name) PyObject *m = NULL; PyObject *obCallBack = NULL; - /* This makes _apache appear imported, and subsequent - * >>> import _apache - * will not give an error. - */ - _apache_module_init(); - /* Now execute the equivalent of * >>> import * >>> @@ -787,6 +781,14 @@ static int python_init(apr_pool_t *p, apr_pool_t *ptemp, Py_NoSiteFlag = 1; #endif +#if PY_MAJOR_VERSION == 2 + PyMODINIT_FUNC init_apache(void); + PyImport_AppendInittab("_apache", &init_apache); +#else + PyMODINIT_FUNC PyInit_apache(void); + PyImport_AppendInittab("_apache", &PyInit_apache); +#endif + Py_Initialize(); #if PY_MAJOR_VERSION == 2 && \ From d469ddee235219052b9754f6ec8adaf8af01a4d1 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 7 Nov 2025 05:37:28 +0000 Subject: [PATCH 02/10] Fix mod_python.publisher controls for Python 3.14. --- lib/python/mod_python/publisher.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/python/mod_python/publisher.py b/lib/python/mod_python/publisher.py index 8419cc13..ecc7c79b 100644 --- a/lib/python/mod_python/publisher.py +++ b/lib/python/mod_python/publisher.py @@ -255,8 +255,16 @@ def lookup(name): if name in names: i = list(names).index(name) if i is not None: - if PY2 or sys.hexversion >= 0x030b0000: # 3.12.0 - return (1, func_code.co_consts[i+1]) + # Python 3.11 moved qualified name into code object + # https://github.com/python/cpython/pull/26941 + # commit 2f180ce2cb6e6a7e3c517495e0f4873d6aaf5f2f + if PY2 or sys.hexversion >= 0x030b0000: + # Python 3.14 added CO_HAS_DOCSTRING (0x4000000) + # https://github.com/python/cpython/issues/126072 + # https://github.com/python/cpython/pull/126101 + # commit 35df4eb959b3923c08aaaeff728c5ed1706f31cf + offset = 1 if sys.hexversion < 0x030e0000 or (func_code.co_flags & 0x4000000) != 0 else 0 + return (1, func_code.co_consts[offset+i]) else: return (1, func_code.co_consts[1+i*2]) From 95207a0aacd806f976b767905eb7fed6c6ec14a9 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 7 Nov 2025 06:53:42 +0000 Subject: [PATCH 03/10] Attempt to work around Python 3.13 GIL strictness. --- src/mod_python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_python.c b/src/mod_python.c index 55bc2962..b79a5a6a 100644 --- a/src/mod_python.c +++ b/src/mod_python.c @@ -2643,7 +2643,7 @@ static void PythonChildInitHandler(apr_pool_t *p, server_rec *s) #if PY_VERSION_HEX < 0x03070000 PyOS_AfterFork(); -#else +#elif PY_VERSION_HEX < 0x030D0000 PyOS_AfterFork_Child(); #endif From 9693a38ef91e592fb5dd92ac89a0a5a54e6c9d5b Mon Sep 17 00:00:00 2001 From: Gregory Trubetskoy Date: Sat, 8 Nov 2025 12:03:51 -0500 Subject: [PATCH 04/10] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 3713cf2b..8bbfdd26 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +Nov 8 2025 - 3.5.0.5 Compatibility with Python 3.13 and 3.14. + Sep 5 2024 - 3.5.0.4 fix sys.version bug and quiet compiler warnings. May 7 2024 - 3.5.0.3 release tagged, it addresses test failures and From 7e197f5f6c32696de69f56e5d9d2cc29607610a8 Mon Sep 17 00:00:00 2001 From: David Miguel Susano Pinto Date: Fri, 21 Nov 2025 13:52:38 +0000 Subject: [PATCH 05/10] Makefile: do not install shared libraries with executable permissions --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 15ab6931..8e08617b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -61,7 +61,7 @@ install_dso: dso @echo "Performing DSO installation." @echo $(INSTALL) -d $(DESTDIR)$(LIBEXECDIR) - $(INSTALL) src/mod_python.so $(DESTDIR)$(LIBEXECDIR) + $(INSTALL) -m 0644 src/mod_python.so $(DESTDIR)$(LIBEXECDIR) install_py_lib: cd dist && $(MAKE) install_py_lib From 641e341ba04e66180b5aabb319048703101a1799 Mon Sep 17 00:00:00 2001 From: David Miguel Susano Pinto Date: Fri, 21 Nov 2025 14:08:30 +0000 Subject: [PATCH 06/10] scripts/mod_python.in: replace use of execfile removed in Python 3 (#139) Python 3 removed the builtin execfile so this replaces it with read, compile, and exec (see https://stackoverflow.com/questions/436198/). Because this works in both Python 2 and Python 3, we use this alternative unconditionally. --- scripts/mod_python.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/mod_python.in b/scripts/mod_python.in index f824a8dc..17e96160 100644 --- a/scripts/mod_python.in +++ b/scripts/mod_python.in @@ -64,7 +64,9 @@ def cmd_genconfig(): if len(args) != 1: parser.error("Must specify ") - execfile(args[0]) + src = args[0] + with open(src, "rb") as fh: + exec(compile(fh.read(), src, "exec")) def cmd_create(): From 9f2ef9b6642f265bf3a7709dabe71bd50ce119a0 Mon Sep 17 00:00:00 2001 From: Gregory Trubetskoy Date: Mon, 29 Dec 2025 20:38:39 -0500 Subject: [PATCH 07/10] Refresh pointers in parse_qsl(). Fixes #144 --- src/_apachemodule.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/_apachemodule.c b/src/_apachemodule.c index 5ba1f5da..976e8da5 100644 --- a/src/_apachemodule.c +++ b/src/_apachemodule.c @@ -370,6 +370,10 @@ static PyObject *parse_qsl(PyObject *self, PyObject *args) _PyBytes_Resize(&val, strlen(cval)); if (key && val) { + + ckey = PyBytes_AS_STRING(key); + cval = PyBytes_AS_STRING(val); + PyObject *listitem = NULL; if (unicode) { PyObject *ukey, *uval; From 52f8975829a0a3c467f089894e884d29c83e8a5e Mon Sep 17 00:00:00 2001 From: Gregory Trubetskoy Date: Tue, 30 Dec 2025 11:21:30 -0500 Subject: [PATCH 08/10] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 8bbfdd26..178c688e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +Dec 30 2025 - 3.5.0.6 Fix publisher query string bug + Nov 8 2025 - 3.5.0.5 Compatibility with Python 3.13 and 3.14. Sep 5 2024 - 3.5.0.4 fix sys.version bug and quiet compiler warnings. From 0c0962214abf1a174574de5827c33bc67861553c Mon Sep 17 00:00:00 2001 From: Gregory Trubetskoy Date: Thu, 22 Jan 2026 17:16:26 -0500 Subject: [PATCH 09/10] Use Py_hash_t return type for table_nohash(). Fixes #149 On 32-bit systems, tp_hash expects Py_hash_t (int) not long, causing a build failure due to incompatible pointer types. --- src/tableobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tableobject.c b/src/tableobject.c index 80d76d57..6d317085 100644 --- a/src/tableobject.c +++ b/src/tableobject.c @@ -1158,7 +1158,7 @@ static int table_init(tableobject *self, PyObject *args, PyObject *kwds) return result; } -static long table_nohash(PyObject *self) +static Py_hash_t table_nohash(PyObject *self) { TABLE_DEBUG("table_nohash"); From a638e01b7eb50d0cf127ac14c3e1b64347ee682e Mon Sep 17 00:00:00 2001 From: Gregory Trubetskoy Date: Fri, 23 Jan 2026 10:33:24 -0500 Subject: [PATCH 10/10] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 178c688e..797dc0e1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +Jan 23 2026 - 3.5.0.7 32-bit compile fix + Dec 30 2025 - 3.5.0.6 Fix publisher query string bug Nov 8 2025 - 3.5.0.5 Compatibility with Python 3.13 and 3.14.