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-03-11 20:49:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-regex (Old)
 and      /work/SRC/openSUSE:Factory/.python-regex.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-regex"

Wed Mar 11 20:49:38 2026 rev:31 rq:1337895 version:2026.2.28

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-regex/python-regex.changes        
2026-01-28 15:07:29.290853193 +0100
+++ /work/SRC/openSUSE:Factory/.python-regex.new.8177/python-regex.changes      
2026-03-11 20:49:47.428320997 +0100
@@ -1,0 +2,13 @@
+Tue Mar 10 08:15:10 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2026.2.28:
+  * Replaced atomic operations with mutex on pattern object for
+    free-threaded Python.
+  * PR #598: Fix race condition in storage caching with atomic
+    operations.
+  * Replaced use of PyUnicode_GET_LENGTH with
+    PyUnicode_GetLength.
+  * Added \z as alias of \Z, like in re module.
+  * Added prefixmatch as alias of match, like in re module.
+
+-------------------------------------------------------------------

Old:
----
  regex-2026.1.15.tar.gz

New:
----
  regex-2026.2.28.tar.gz

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

Other differences:
------------------
++++++ python-regex.spec ++++++
--- /var/tmp/diff_new_pack.Scy4D4/_old  2026-03-11 20:49:47.924341107 +0100
+++ /var/tmp/diff_new_pack.Scy4D4/_new  2026-03-11 20:49:47.928341269 +0100
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-regex
-Version:        2026.1.15
+Version:        2026.2.28
 Release:        0
 Summary:        Alternative regular expression module for Python
 License:        Apache-2.0

++++++ regex-2026.1.15.tar.gz -> regex-2026.2.28.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/PKG-INFO new/regex-2026.2.28/PKG-INFO
--- old/regex-2026.1.15/PKG-INFO        2026-01-14 23:06:53.833961200 +0100
+++ new/regex-2026.2.28/PKG-INFO        2026-02-28 02:12:31.823559800 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: regex
-Version: 2026.1.15
+Version: 2026.2.28
 Summary: Alternative regular expression module, to replace re.
 Author-email: Matthew Barnett <[email protected]>
 License-Expression: Apache-2.0 AND CNRI-Python
@@ -8,7 +8,6 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
@@ -18,7 +17,7 @@
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Text Processing
 Classifier: Topic :: Text Processing :: General
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 Dynamic: license-file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/changelog.txt 
new/regex-2026.2.28/changelog.txt
--- old/regex-2026.1.15/changelog.txt   2026-01-14 23:06:49.000000000 +0100
+++ new/regex-2026.2.28/changelog.txt   2026-02-28 02:12:26.000000000 +0100
@@ -1,3 +1,19 @@
+Version: 2026.2.28
+
+    Replaced atomic operations with mutex on pattern object for free-threaded 
Python.
+
+Version: 2026.2.26
+
+    PR #598: Fix race condition in storage caching with atomic operations.
+
+    Replaced use of PyUnicode_GET_LENGTH with PyUnicode_GetLength.
+
+Version: 2026.2.19
+
+    Added \z as alias of \Z, like in re module.
+
+    Added prefixmatch as alias of match, like in re module.
+
 Version: 2026.1.15
 
     Re-uploaded.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/pyproject.toml 
new/regex-2026.2.28/pyproject.toml
--- old/regex-2026.1.15/pyproject.toml  2026-01-14 23:06:49.000000000 +0100
+++ new/regex-2026.2.28/pyproject.toml  2026-02-28 02:12:26.000000000 +0100
@@ -4,7 +4,7 @@
 
 [project]
 name = "regex"
-version = "2026.1.15"
+version = "2026.2.28"
 description = "Alternative regular expression module, to replace re."
 readme = "README.rst"
 authors = [
@@ -17,7 +17,6 @@
     "Development Status :: 5 - Production/Stable",
     "Intended Audience :: Developers",
     "Operating System :: OS Independent",
-    "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
@@ -29,7 +28,7 @@
     "Topic :: Text Processing :: General",
 ]
 
-requires-python = ">= 3.9"
+requires-python = ">= 3.10"
 
 [project.urls]
 Homepage = "https://github.com/mrabarnett/mrab-regex";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/regex/_main.py 
new/regex-2026.2.28/regex/_main.py
--- old/regex-2026.1.15/regex/_main.py  2026-01-14 23:06:49.000000000 +0100
+++ new/regex-2026.2.28/regex/_main.py  2026-02-28 02:12:26.000000000 +0100
@@ -167,28 +167,31 @@
     \xXX            Matches the character with 2-digit hex code XX.
     \X              Matches a grapheme.
     \Z              Matches only at the end of the string.
+    \z              Matches only at the end of the string. Alias of \Z.
     \\              Matches a literal backslash.
 
 This module exports the following functions:
-    match      Match a regular expression pattern at the beginning of a string.
-    fullmatch  Match a regular expression pattern against all of a string.
-    search     Search a string for the presence of a pattern.
-    sub        Substitute occurrences of a pattern found in a string using a
-               template string.
-    subf       Substitute occurrences of a pattern found in a string using a
-               format string.
-    subn       Same as sub, but also return the number of substitutions made.
-    subfn      Same as subf, but also return the number of substitutions made.
-    split      Split a string by the occurrences of a pattern. VERSION1: will
-               split at zero-width match; VERSION0: won't split at zero-width
-               match.
-    splititer  Return an iterator yielding the parts of a split string.
-    findall    Find all occurrences of a pattern in a string.
-    finditer   Return an iterator yielding a match object for each match.
-    compile    Compile a pattern into a Pattern object.
-    purge      Clear the regular expression cache.
-    escape     Backslash all non-alphanumerics or special characters in a
-               string.
+    match        Match a regular expression pattern at the beginning of a 
string.
+    prefixmatch  Match a regular expression pattern at the beginning of a 
string.
+                 Alias of match.
+    fullmatch    Match a regular expression pattern against all of a string.
+    search       Search a string for the presence of a pattern.
+    sub          Substitute occurrences of a pattern found in a string using a
+                 template string.
+    subf         Substitute occurrences of a pattern found in a string using a
+                 format string.
+    subn         Same as sub, but also return the number of substitutions made.
+    subfn        Same as subf, but also return the number of substitutions 
made.
+    split        Split a string by the occurrences of a pattern. VERSION1: will
+                 split at zero-width match; VERSION0: won't split at zero-width
+                 match.
+    splititer    Return an iterator yielding the parts of a split string.
+    findall      Find all occurrences of a pattern in a string.
+    finditer     Return an iterator yielding a match object for each match.
+    compile      Compile a pattern into a Pattern object.
+    purge        Clear the regular expression cache.
+    escape       Backslash all non-alphanumerics or special characters in a
+                 string.
 
 Most of the functions support a concurrent parameter: if True, the GIL will be
 released during matching, allowing other Python threads to run concurrently. If
@@ -233,7 +236,7 @@
 
 # Public symbols.
 __all__ = ["cache_all", "compile", "DEFAULT_VERSION", "escape", "findall",
-  "finditer", "fullmatch", "match", "purge", "search", "split", "splititer",
+  "finditer", "fullmatch", "match", "prefixmatch", "purge", "search", "split", 
"splititer",
   "sub", "subf", "subfn", "subn", "template", "Scanner", "A", "ASCII", "B",
   "BESTMATCH", "D", "DEBUG", "E", "ENHANCEMATCH", "S", "DOTALL", "F",
   "FULLCASE", "I", "IGNORECASE", "L", "LOCALE", "M", "MULTILINE", "P", "POSIX",
@@ -241,7 +244,7 @@
   "VERSION1", "X", "VERBOSE", "W", "WORD", "error", "Regex", "__version__",
   "__doc__", "RegexFlag"]
 
-__version__ = "2026.1.15"
+__version__ = "2026.2.28"
 
 # --------------------------------------------------------------------
 # Public interface.
@@ -253,6 +256,13 @@
     pat = _compile(pattern, flags, ignore_unused, kwargs, True)
     return pat.match(string, pos, endpos, concurrent, partial, timeout)
 
+def prefixmatch(pattern, string, flags=0, pos=None, endpos=None, partial=False,
+  concurrent=None, timeout=None, ignore_unused=False, **kwargs):
+    """Try to apply the pattern at the start of the string, returning a match
+    object, or None if no match was found. Alias of match()."""
+    pat = _compile(pattern, flags, ignore_unused, kwargs, True)
+    return pat.match(string, pos, endpos, concurrent, partial, timeout)
+
 def fullmatch(pattern, string, flags=0, pos=None, endpos=None, partial=False,
   concurrent=None, timeout=None, ignore_unused=False, **kwargs):
     """Try to apply the pattern against all of the string, returning a match
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/regex/_regex_core.py 
new/regex-2026.2.28/regex/_regex_core.py
--- old/regex-2026.1.15/regex/_regex_core.py    2026-01-14 23:06:49.000000000 
+0100
+++ new/regex-2026.2.28/regex/_regex_core.py    2026-02-28 02:12:26.000000000 
+0100
@@ -4641,6 +4641,7 @@
     "m": StartOfWord(),
     "M": EndOfWord(),
     "Z": EndOfString(),
+    "z": EndOfString(),
 }
 ASCII_POSITION_ESCAPES = dict(POSITION_ESCAPES)
 ASCII_POSITION_ESCAPES.update({
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/regex.egg-info/PKG-INFO 
new/regex-2026.2.28/regex.egg-info/PKG-INFO
--- old/regex-2026.1.15/regex.egg-info/PKG-INFO 2026-01-14 23:06:53.000000000 
+0100
+++ new/regex-2026.2.28/regex.egg-info/PKG-INFO 2026-02-28 02:12:31.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: regex
-Version: 2026.1.15
+Version: 2026.2.28
 Summary: Alternative regular expression module, to replace re.
 Author-email: Matthew Barnett <[email protected]>
 License-Expression: Apache-2.0 AND CNRI-Python
@@ -8,7 +8,6 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
@@ -18,7 +17,7 @@
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Text Processing
 Classifier: Topic :: Text Processing :: General
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 Dynamic: license-file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/regex-2026.1.15/src/_regex.c 
new/regex-2026.2.28/src/_regex.c
--- old/regex-2026.1.15/src/_regex.c    2026-01-14 23:06:49.000000000 +0100
+++ new/regex-2026.2.28/src/_regex.c    2026-02-28 02:12:26.000000000 +0100
@@ -585,6 +585,9 @@
     RE_Node* req_string; /* The required string. */
     BOOL is_fuzzy; /* Whether it's a fuzzy pattern. */
     BOOL do_search_start; /* Whether to do an initial search. */
+    #if defined(Py_GIL_DISABLED)
+    PyMutex mutex;
+    #endif
 } PatternObject;
 
 /* The MatchObject created when a match is found. */
@@ -18161,7 +18164,7 @@
             return FALSE;
 
         str_info->characters = (void*)PyUnicode_DATA(string);
-        str_info->length = PyUnicode_GET_LENGTH(string);
+        str_info->length = PyUnicode_GetLength(string);
         str_info->charsize = PyUnicode_KIND(string);
         str_info->is_unicode = TRUE;
         str_info->should_release = FALSE;
@@ -18219,6 +18222,10 @@
     ByteStack_init(state, &state->pstack);
 
     /* We might already have some cached storage we can use for bstack. */
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Lock(&pattern->mutex);
+    #endif
+
     if (pattern->stack_storage) {
         state->bstack.storage = pattern->stack_storage;
         state->bstack.capacity = pattern->stack_capacity;
@@ -18226,6 +18233,10 @@
         pattern->stack_capacity = 0;
     }
 
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Unlock(&pattern->mutex);
+    #endif
+
     state->groups = NULL;
     state->best_match_groups = NULL;
     state->repeats = NULL;
@@ -18252,10 +18263,22 @@
     if (pattern->true_group_count) {
         size_t g;
 
+        #if defined(Py_GIL_DISABLED)
+        PyMutex_Lock(&pattern->mutex);
+        #endif
+
         if (pattern->groups_storage) {
             state->groups = pattern->groups_storage;
             pattern->groups_storage = NULL;
+
+            #if defined(Py_GIL_DISABLED)
+            PyMutex_Unlock(&pattern->mutex);
+            #endif
         } else {
+            #if defined(Py_GIL_DISABLED)
+            PyMutex_Unlock(&pattern->mutex);
+            #endif
+
             state->groups = (RE_GroupData*)re_alloc(pattern->true_group_count *
               sizeof(RE_GroupData));
             if (!state->groups)
@@ -18297,6 +18320,9 @@
     else if (end > str_info->length)
         end = str_info->length;
 
+    if (end < start)
+        end = start;
+
     state->overlapped = overlapped;
     state->min_width = pattern->min_width;
 
@@ -18396,10 +18422,22 @@
     state->string = string;
 
     if (pattern->repeat_count) {
+        #if defined(Py_GIL_DISABLED)
+        PyMutex_Lock(&pattern->mutex);
+        #endif
+
         if (pattern->repeats_storage) {
             state->repeats = pattern->repeats_storage;
             pattern->repeats_storage = NULL;
+
+            #if defined(Py_GIL_DISABLED)
+            PyMutex_Unlock(&pattern->mutex);
+            #endif
         } else {
+            #if defined(Py_GIL_DISABLED)
+            PyMutex_Unlock(&pattern->mutex);
+            #endif
+
             state->repeats = (RE_RepeatData*)re_alloc(pattern->repeat_count *
               sizeof(RE_RepeatData));
             if (!state->repeats)
@@ -18567,6 +18605,10 @@
 
     pattern = state->pattern;
 
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Lock(&pattern->mutex);
+    #endif
+
     /* If possible cache the storage of bstack. */
     if (!pattern->stack_storage) {
         pattern->stack_storage = state->bstack.storage;
@@ -18587,14 +18629,6 @@
         }
     }
 
-    /* Clear the stacks. */
-    ByteStack_fini(state, &state->sstack);
-    ByteStack_fini(state, &state->bstack);
-    ByteStack_fini(state, &state->pstack);
-
-    if (state->best_match_groups)
-        dealloc_groups(state->best_match_groups, pattern->true_group_count);
-
     if (pattern->groups_storage)
         dealloc_groups(state->groups, pattern->true_group_count);
     else
@@ -18605,6 +18639,18 @@
     else
         pattern->repeats_storage = state->repeats;
 
+    #if defined(Py_GIL_DISABLED)
+    PyMutex_Unlock(&pattern->mutex);
+    #endif
+
+    if (state->best_match_groups)
+        dealloc_groups(state->best_match_groups, pattern->true_group_count);
+
+    /* Clear the stacks. */
+    ByteStack_fini(state, &state->sstack);
+    ByteStack_fini(state, &state->bstack);
+    ByteStack_fini(state, &state->pstack);
+
     for (i = 0; i < pattern->call_ref_info_count; i++)
         re_dealloc(state->group_call_guard_list[i].spans);
 
@@ -18694,7 +18740,7 @@
   Py_ssize_t end) {
     Py_ssize_t length;
 
-    length = PyUnicode_GET_LENGTH(string);
+    length = PyUnicode_GetLength(string);
     start = limited_range(start, 0, length);
     end = limited_range(end, 0, length);
 
@@ -22358,6 +22404,10 @@
     "match(string, pos=None, endpos=None, concurrent=None, timeout=None) --> 
MatchObject or None.\n\
     Match zero or more characters at the beginning of the string.");
 
+PyDoc_STRVAR(pattern_prefixmatch_doc,
+    "prefixmatch(string, pos=None, endpos=None, concurrent=None, timeout=None) 
--> MatchObject or None.\n\
+    Match zero or more characters at the beginning of the string. Alias of 
match()");
+
 PyDoc_STRVAR(pattern_fullmatch_doc,
     "fullmatch(string, pos=None, endpos=None, concurrent=None, timeout=None) 
--> MatchObject or None.\n\
     Match zero or more characters against all of the string.");
@@ -22419,6 +22469,8 @@
 static PyMethodDef pattern_methods[] = {
     {"match", (PyCFunction)pattern_match, METH_VARARGS|METH_KEYWORDS,
       pattern_match_doc},
+    {"prefixmatch", (PyCFunction)pattern_match, METH_VARARGS|METH_KEYWORDS,
+      pattern_prefixmatch_doc},
     {"fullmatch", (PyCFunction)pattern_fullmatch, METH_VARARGS|METH_KEYWORDS,
       pattern_fullmatch_doc},
     {"search", (PyCFunction)pattern_search, METH_VARARGS|METH_KEYWORDS,
@@ -25793,6 +25845,9 @@
     self->req_flags = req_flags;
     self->req_string = NULL;
     self->locale_info = NULL;
+    #if defined(Py_GIL_DISABLED)
+    memset(&self->mutex, 0, sizeof(self->mutex));
+    #endif
     Py_INCREF(self->pattern);
     if (unpacked) {
         Py_INCREF(self->packed_code_list);
@@ -26401,9 +26456,9 @@
     if (!m)
         return NULL;
 
-#if defined(Py_GIL_DISABLED)
+    #if defined(Py_GIL_DISABLED)
     PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
-#endif
+    #endif
 
     d = PyModule_GetDict(m);
 

Reply via email to