Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-regex for openSUSE:Factory 
checked in at 2026-04-14 17:48:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-regex (Old)
 and      /work/SRC/openSUSE:Factory/.python-regex.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-regex"

Tue Apr 14 17:48:12 2026 rev:33 rq:1346265 version:2026.4.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-regex/python-regex.changes        
2026-03-30 18:30:24.984868592 +0200
+++ /work/SRC/openSUSE:Factory/.python-regex.new.21863/python-regex.changes     
2026-04-14 17:48:22.275667985 +0200
@@ -1,0 +2,6 @@
+Sun Apr 12 21:05:52 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2026.4.4:
+  * more fixes for free-threading
+
+-------------------------------------------------------------------

Old:
----
  regex-2026.3.32.tar.gz

New:
----
  regex-2026.4.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-regex.spec ++++++
--- /var/tmp/diff_new_pack.0NviJI/_old  2026-04-14 17:48:23.219707006 +0200
+++ /var/tmp/diff_new_pack.0NviJI/_new  2026-04-14 17:48:23.219707006 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-regex
-Version:        2026.3.32
+Version:        2026.4.4
 Release:        0
 Summary:        Alternative regular expression module for Python
 License:        Apache-2.0

++++++ regex-2026.3.32.tar.gz -> regex-2026.4.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.3.32/PKG-INFO new/regex-2026.4.4/PKG-INFO
--- old/regex-2026.3.32/PKG-INFO        2026-03-28 21:45:50.057209300 +0100
+++ new/regex-2026.4.4/PKG-INFO 2026-04-03 22:01:02.882440000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: regex
-Version: 2026.3.32
+Version: 2026.4.4
 Summary: Alternative regular expression module, to replace re.
 Author-email: Matthew Barnett <[email protected]>
 License-Expression: Apache-2.0 AND CNRI-Python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.3.32/pyproject.toml 
new/regex-2026.4.4/pyproject.toml
--- old/regex-2026.3.32/pyproject.toml  2026-03-28 21:45:46.000000000 +0100
+++ new/regex-2026.4.4/pyproject.toml   2026-04-03 22:00:59.000000000 +0200
@@ -4,7 +4,7 @@
 
 [project]
 name = "regex"
-version = "2026.3.32"
+version = "2026.4.4"
 description = "Alternative regular expression module, to replace re."
 readme = "README.rst"
 authors = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.3.32/regex/_main.py 
new/regex-2026.4.4/regex/_main.py
--- old/regex-2026.3.32/regex/_main.py  2026-03-28 21:45:46.000000000 +0100
+++ new/regex-2026.4.4/regex/_main.py   2026-04-03 22:00:59.000000000 +0200
@@ -244,7 +244,7 @@
   "VERSION1", "X", "VERBOSE", "W", "WORD", "error", "Regex", "__version__",
   "__doc__", "RegexFlag"]
 
-__version__ = "2026.3.32"
+__version__ = "2026.4.4"
 
 # --------------------------------------------------------------------
 # Public interface.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.3.32/regex.egg-info/PKG-INFO 
new/regex-2026.4.4/regex.egg-info/PKG-INFO
--- old/regex-2026.3.32/regex.egg-info/PKG-INFO 2026-03-28 21:45:50.000000000 
+0100
+++ new/regex-2026.4.4/regex.egg-info/PKG-INFO  2026-04-03 22:01:02.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: regex
-Version: 2026.3.32
+Version: 2026.4.4
 Summary: Alternative regular expression module, to replace re.
 Author-email: Matthew Barnett <[email protected]>
 License-Expression: Apache-2.0 AND CNRI-Python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.3.32/src/_regex.c 
new/regex-2026.4.4/src/_regex.c
--- old/regex-2026.3.32/src/_regex.c    2026-03-28 21:45:46.000000000 +0100
+++ new/regex-2026.4.4/src/_regex.c     2026-04-03 22:00:59.000000000 +0200
@@ -212,7 +212,7 @@
     " RE 2.3.0 Copyright (c) 1997-2002 by Secret Labs AB ";
 
 /* The exception to raise on error. */
-static PyObject* error_exception;
+static PyObject* error_exception = NULL;
 
 /* The dictionary of Unicode properties. */
 static PyObject* property_dict = NULL;
@@ -2064,6 +2064,31 @@
 
 Py_LOCAL_INLINE(PyObject*) get_object(char* module_name, char* object_name);
 
+/* Ensures that the error_exception object is initialised.
+ *
+ * Unfortunately, because it's imported from the Python code, it can't be
+ * imported when the extension starts.
+ */
+Py_LOCAL_INLINE(BOOL) ensure_error_exception(void) {
+    if (error_exception)
+        return TRUE;
+
+    #if defined(Py_GIL_DISABLED)
+    static PyMutex init_mutex = {0};
+    PyMutex_Lock(&init_mutex);
+    #endif
+
+    if (!error_exception) {
+        error_exception = get_object("regex._regex_core", "error");
+    }
+
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Unlock(&init_mutex);
+    #endif
+
+    return error_exception != NULL;
+}
+
 /* Sets the error message. */
 Py_LOCAL_INLINE(void) set_error(int status, PyObject* object) {
     TRACE(("<<set_error>>\n"))
@@ -2096,14 +2121,7 @@
         PyErr_SetString(PyExc_TypeError, "string indices must be integers");
         break;
     case RE_ERROR_INVALID_GROUP_REF:
-        if (!error_exception) {
-            error_exception = get_object("regex._regex_core", "error");
-            if (!error_exception) {
-                PyErr_SetString(PyExc_RuntimeError, "cannot import 
regex._regex_core.error");
-                break;
-            }
-        }
-
+        ensure_error_exception();
         PyErr_SetString(error_exception, "invalid group reference");
         break;
     case RE_ERROR_MEMORY:
@@ -2126,14 +2144,7 @@
         PyErr_SetString(PyExc_IndexError, "no such group");
         break;
     case RE_ERROR_REPLACEMENT:
-        if (!error_exception) {
-            error_exception = get_object("regex._regex_core", "error");
-            if (!error_exception) {
-                PyErr_SetString(PyExc_RuntimeError, "cannot import 
regex._regex_core.error");
-                break;
-            }
-        }
-
+        ensure_error_exception();
         PyErr_SetString(error_exception, "invalid replacement");
         break;
     case RE_ERROR_TIMED_OUT:
@@ -6547,6 +6558,40 @@
     return TRUE;
 }
 
+/* Gets the status of a node in a thread-safe way. */
+Py_LOCAL_INLINE(RE_STATUS_T) safe_get_status(RE_Node* node) {
+    #if defined(Py_GIL_DISABLED)
+    return _Py_atomic_load_uint32_relaxed(&node->status);
+    #else
+    return node->status;
+    #endif
+}
+
+/* Sets the status of a node in a thread-safe way. */
+Py_LOCAL_INLINE(void) safe_set_status(RE_Node* node, RE_STATUS_T status) {
+    #if defined(Py_GIL_DISABLED)
+    _Py_atomic_or_uint32(&node->status, status);
+    #else
+    node->status |= status;
+    #endif
+}
+
+/* Locks a pattern in a thread-safe way. */
+Py_LOCAL_INLINE(void) lock_pattern(RE_State* state) {
+    acquire_GIL(state);
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Lock(&state->pattern->mutex);
+    #endif
+}
+
+/* Unlocks a pattern in a thread-safe way. */
+Py_LOCAL_INLINE(void) unlock_pattern(RE_State* state) {
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Unlock(&state->pattern->mutex);
+    #endif
+    release_GIL(state);
+}
+
 /* Performs a string search. */
 Py_LOCAL_INLINE(Py_ssize_t) string_search(RE_State* state, RE_Node* node,
   Py_ssize_t text_pos, Py_ssize_t limit, BOOL try_fast, BOOL* is_partial) {
@@ -6555,25 +6600,19 @@
     *is_partial = FALSE;
 
     /* Has the node been initialised for fast searching, if necessary? */
-    if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) {
+    if (try_fast && !(safe_get_status(node) & RE_STATUS_FAST_INIT)) {
         /* Ideally the pattern should immutable and shareable across threads.
          * Internally, however, it isn't. For safety we need to hold the GIL.
          */
-        acquire_GIL(state);
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Lock(&state->pattern->mutex);
-        #endif
+        lock_pattern(state);
 
         /* Double-check because of multithreading. */
         if (!(node->status & RE_STATUS_FAST_INIT)) {
             build_fast_tables(state, node, FALSE);
-            node->status |= RE_STATUS_FAST_INIT;
+            safe_set_status(node, RE_STATUS_FAST_INIT);
         }
 
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Unlock(&state->pattern->mutex);
-        #endif
-        release_GIL(state);
+        unlock_pattern(state);
     }
 
     if (try_fast && node->string.bad_character_offset) {
@@ -6749,25 +6788,19 @@
     *is_partial = FALSE;
 
     /* Has the node been initialised for fast searching, if necessary? */
-    if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) {
+    if (try_fast && !(safe_get_status(node) & RE_STATUS_FAST_INIT)) {
         /* Ideally the pattern should immutable and shareable across threads.
          * Internally, however, it isn't. For safety we need to hold the GIL.
          */
-        acquire_GIL(state);
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Lock(&state->pattern->mutex);
-        #endif
+        lock_pattern(state);
 
         /* Double-check because of multithreading. */
         if (!(node->status & RE_STATUS_FAST_INIT)) {
             build_fast_tables(state, node, TRUE);
-            node->status |= RE_STATUS_FAST_INIT;
+            safe_set_status(node, RE_STATUS_FAST_INIT);
         }
 
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Unlock(&state->pattern->mutex);
-        #endif
-        release_GIL(state);
+        unlock_pattern(state);
     }
 
     if (try_fast && node->string.bad_character_offset) {
@@ -6797,25 +6830,19 @@
     *is_partial = FALSE;
 
     /* Has the node been initialised for fast searching, if necessary? */
-    if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) {
+    if (try_fast && !(safe_get_status(node) & RE_STATUS_FAST_INIT)) {
         /* Ideally the pattern should immutable and shareable across threads.
          * Internally, however, it isn't. For safety we need to hold the GIL.
          */
-        acquire_GIL(state);
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Lock(&state->pattern->mutex);
-        #endif
+        lock_pattern(state);
 
         /* Double-check because of multithreading. */
         if (!(node->status & RE_STATUS_FAST_INIT)) {
             build_fast_tables_rev(state, node, TRUE);
-            node->status |= RE_STATUS_FAST_INIT;
+            safe_set_status(node, RE_STATUS_FAST_INIT);
         }
 
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Unlock(&state->pattern->mutex);
-        #endif
-        release_GIL(state);
+        unlock_pattern(state);
     }
 
     if (try_fast && node->string.bad_character_offset) {
@@ -6844,25 +6871,19 @@
     *is_partial = FALSE;
 
     /* Has the node been initialised for fast searching, if necessary? */
-    if (try_fast && !(node->status & RE_STATUS_FAST_INIT)) {
+    if (try_fast && !(safe_get_status(node) & RE_STATUS_FAST_INIT)) {
         /* Ideally the pattern should immutable and shareable across threads.
          * Internally, however, it isn't. For safety we need to hold the GIL.
          */
-        acquire_GIL(state);
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Lock(&state->pattern->mutex);
-        #endif
+        lock_pattern(state);
 
         /* Double-check because of multithreading. */
         if (!(node->status & RE_STATUS_FAST_INIT)) {
             build_fast_tables_rev(state, node, FALSE);
-            node->status |= RE_STATUS_FAST_INIT;
+            safe_set_status(node, RE_STATUS_FAST_INIT);
         }
 
-        release_GIL(state);
-        #if defined(Py_GIL_DISABLED)
-        PyMutex_Unlock(&state->pattern->mutex);
-        #endif
+        unlock_pattern(state);
     }
 
     if (try_fast && node->string.bad_character_offset) {
@@ -20415,6 +20436,9 @@
 /* MatchObject's 'lastgroup' attribute. */
 static PyObject* match_lastgroup(PyObject* self_, void* unused) {
     MatchObject* self;
+#if Py_VERSION_HEX >= 0x030D0000
+    int status;
+#endif
 
     self = (MatchObject*)self_;
 
@@ -20426,6 +20450,15 @@
         if (!index)
             return NULL;
 
+#if Py_VERSION_HEX >= 0x030D0000
+        /* PyDict_GetItemRef returns a new reference or NULL for 'result'. */
+        status = PyDict_GetItemRef(self->pattern->indexgroup, index, &result);
+        Py_DECREF(index);
+        if (status < 0)
+            return NULL;
+        if (result)
+            return result;
+#else
         /* PyDict_GetItem returns borrows a reference. */
         result = PyDict_GetItem(self->pattern->indexgroup, index);
         Py_DECREF(index);
@@ -20433,6 +20466,7 @@
             Py_INCREF(result);
             return result;
         }
+#endif
     }
 
     Py_RETURN_NONE;

Reply via email to