Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-cymem for openSUSE:Factory 
checked in at 2026-03-05 17:14:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cymem (Old)
 and      /work/SRC/openSUSE:Factory/.python-cymem.new.561 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-cymem"

Thu Mar  5 17:14:58 2026 rev:5 rq:1336591 version:2.0.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cymem/python-cymem.changes        
2025-01-22 16:32:19.659960296 +0100
+++ /work/SRC/openSUSE:Factory/.python-cymem.new.561/python-cymem.changes       
2026-03-05 17:18:15.834390360 +0100
@@ -1,0 +2,9 @@
+Wed Mar  4 21:28:28 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2.0.13:
+  * Adds wheels for Python 3.14, and critical sections to allow
+    thread-safe support of free-threaded Python
+  * Update to more recent cibuildwheel, to build wheels for
+    Python v3.13
+
+-------------------------------------------------------------------

Old:
----
  cymem-2.0.11.tar.gz

New:
----
  cymem-2.0.13.tar.gz

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

Other differences:
------------------
++++++ python-cymem.spec ++++++
--- /var/tmp/diff_new_pack.GxSUQp/_old  2026-03-05 17:18:16.594421814 +0100
+++ /var/tmp/diff_new_pack.GxSUQp/_new  2026-03-05 17:18:16.594421814 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-cymem
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-cymem
-Version:        2.0.11
+Version:        2.0.13
 Release:        0
 Summary:        Manage calls to calloc/free through Cython
 License:        MIT

++++++ cymem-2.0.11.tar.gz -> cymem-2.0.13.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/PKG-INFO new/cymem-2.0.13/PKG-INFO
--- old/cymem-2.0.11/PKG-INFO   2025-01-16 21:57:24.485214700 +0100
+++ new/cymem-2.0.13/PKG-INFO   2025-11-14 10:49:51.946309000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: cymem
-Version: 2.0.11
+Version: 2.0.13
 Summary: Manage calls to calloc/free through Cython
 Home-page: https://github.com/explosion/cymem
 Author: Matthew Honnibal
@@ -14,19 +14,15 @@
 Classifier: Operating System :: MacOS :: MacOS X
 Classifier: Operating System :: Microsoft :: Windows
 Classifier: Programming Language :: Cython
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
+Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
 Classifier: Topic :: Scientific/Engineering
+Requires-Python: >=3.9,<3.15
 Description-Content-Type: text/markdown
 License-File: LICENSE
 Dynamic: author
@@ -36,6 +32,8 @@
 Dynamic: description-content-type
 Dynamic: home-page
 Dynamic: license
+Dynamic: license-file
+Dynamic: requires-python
 Dynamic: summary
 
 <a href="https://explosion.ai";><img 
src="https://explosion.ai/assets/img/logo.svg"; width="125" height="125" 
align="right" /></a>
@@ -235,3 +233,28 @@
 from cymem.cymem cimport Pool, WrapMalloc, WrapFree
 cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
 ```
+
+## Thread Safety
+
+As of version 2.0.12, `cymem.Pool` is thread-safe when used with CPython 3.13+
+free-threaded builds (PEP 703). All operations on the Pool, including 
`alloc()`,
+`free()`, and `realloc()`, can be safely called from multiple threads 
concurrently.
+
+**Key guarantees:**
+- Multiple threads can safely call `alloc()`, `free()`, and `realloc()` on the
+    same `Pool` instance.
+- The Pool's internal bookkeeping (`addresses` dict and `size` accounting) is
+    protected from race conditions. Reading the internal state without
+    holding a lock on the `Pool` instance via a critical section is not
+    thread-safe.
+
+**Important notes:**
+- Individual Pool instances are thread-safe, but you are still responsible for
+    proper synchronization when accessing the memory contents themselves. Note
+    that holding a lock on the Pool itself is typically not the right approach:
+    since malloc is thread-safe, memory allocated by separate calls to `alloc`
+    can be safely accessed concurrently without locking. You should only
+    synchronize access to specific memory regions that are being shared across
+    threads, using fine-grained locks appropriate to your use case rather than 
a
+    coarse-grained lock on the entire `Pool`.
+- Custom memory allocators need to be thread-safe themselves.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/README.md new/cymem-2.0.13/README.md
--- old/cymem-2.0.11/README.md  2025-01-16 21:57:19.000000000 +0100
+++ new/cymem-2.0.13/README.md  2025-11-14 10:49:44.000000000 +0100
@@ -195,3 +195,28 @@
 from cymem.cymem cimport Pool, WrapMalloc, WrapFree
 cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
 ```
+
+## Thread Safety
+
+As of version 2.0.12, `cymem.Pool` is thread-safe when used with CPython 3.13+
+free-threaded builds (PEP 703). All operations on the Pool, including 
`alloc()`,
+`free()`, and `realloc()`, can be safely called from multiple threads 
concurrently.
+
+**Key guarantees:**
+- Multiple threads can safely call `alloc()`, `free()`, and `realloc()` on the
+    same `Pool` instance.
+- The Pool's internal bookkeeping (`addresses` dict and `size` accounting) is
+    protected from race conditions. Reading the internal state without
+    holding a lock on the `Pool` instance via a critical section is not
+    thread-safe.
+
+**Important notes:**
+- Individual Pool instances are thread-safe, but you are still responsible for
+    proper synchronization when accessing the memory contents themselves. Note
+    that holding a lock on the Pool itself is typically not the right approach:
+    since malloc is thread-safe, memory allocated by separate calls to `alloc`
+    can be safely accessed concurrently without locking. You should only
+    synchronize access to specific memory regions that are being shared across
+    threads, using fine-grained locks appropriate to your use case rather than 
a
+    coarse-grained lock on the entire `Pool`.
+- Custom memory allocators need to be thread-safe themselves.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/cymem/about.py 
new/cymem-2.0.13/cymem/about.py
--- old/cymem-2.0.11/cymem/about.py     2025-01-16 21:57:19.000000000 +0100
+++ new/cymem-2.0.13/cymem/about.py     2025-11-14 10:49:44.000000000 +0100
@@ -1,5 +1,5 @@
 __title__ = "cymem"
-__version__ = "2.0.11"
+__version__ = "2.0.13"
 __summary__ = "Manage calls to calloc/free through Cython"
 __uri__ = "https://github.com/explosion/cymem";
 __author__ = "Matthew Honnibal"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/cymem/cymem.pyx 
new/cymem-2.0.13/cymem/cymem.pyx
--- old/cymem-2.0.11/cymem/cymem.pyx    2025-01-16 21:57:19.000000000 +0100
+++ new/cymem-2.0.13/cymem/cymem.pyx    2025-11-14 10:49:44.000000000 +0100
@@ -1,7 +1,7 @@
-# cython: embedsignature=True
+# cython: embedsignature=True, freethreading_compatible=True
 
+cimport cython
 from cpython.mem cimport PyMem_Malloc, PyMem_Free
-from cpython.ref cimport Py_INCREF, Py_DECREF
 from libc.string cimport memset
 from libc.string cimport memcpy
 import warnings
@@ -44,17 +44,29 @@
         addresses (dict): The currently allocated addresses and their sizes. 
Read-only.
         pymalloc (PyMalloc): The allocator to use (default uses PyMem_Malloc).
         pyfree (PyFree): The free to use (default uses PyMem_Free).
+
+    Thread-safety:
+        All public methods in this class can be safely called from multiple 
threads.
+        Testing the thread-safety of this class can be done by checking out 
the repository
+        at https://github.com/lysnikolaou/test-cymem-threadsafety and 
following the
+        instructions on the README.
     """
 
     def __cinit__(self, PyMalloc pymalloc=Default_Malloc,
                   PyFree pyfree=Default_Free):
+        # size, addresses and refs are mutable. note that operations on
+        # dicts and lists are atomic.
         self.size = 0
         self.addresses = {}
         self.refs = []
+
+        # pymalloc and pyfree are immutable.
         self.pymalloc = pymalloc
         self.pyfree = pyfree
 
     def __dealloc__(self):
+        # No need for locking here since the methods will be unreachable
+        # by the time __dealloc__ is called
         cdef size_t addr
         if self.addresses is not None:
             for addr in self.addresses:
@@ -73,8 +85,17 @@
         if p == NULL:
             raise MemoryError("Error assigning %d bytes" % (number * 
elem_size))
         memset(p, 0, number * elem_size)
-        self.addresses[<size_t>p] = number * elem_size
-        self.size += number * elem_size
+
+        # We need a critical section here so that addresses and size get
+        # updated atomically. If we were to acquire a critical section on self,
+        # mutating the dictionary would try to acquire a critical section on
+        # the dictionary and therefore release the critical section on self.
+        # Acquiring a critical section on self.addresses works because that's
+        # the only C API that gets called inside the block and acquiring the
+        # critical section on the top-most held lock does not release it.
+        with cython.critical_section(self.addresses):
+            self.addresses[<size_t>p] = number * elem_size
+            self.size += number * elem_size
         return p
 
     cdef void* realloc(self, void* p, size_t new_size) except NULL:
@@ -82,19 +103,36 @@
         a non-NULL pointer to the new block. new_size must be larger than the
         original.
 
-        If p is not in the Pool or new_size is 0, a MemoryError is raised.
+        If p is not in the Pool or new_size isn't larger than the previous 
size,
+        a ValueError is raised.
         """
-        if <size_t>p not in self.addresses:
-            raise ValueError("Pointer %d not found in Pool %s" % (<size_t>p, 
self.addresses))
-        if new_size == 0:
-            raise ValueError("Realloc requires new_size > 0")
-        assert new_size > self.addresses[<size_t>p]
-        cdef void* new_ptr = self.alloc(1, new_size)
+        cdef size_t old_size
+        cdef void* new_ptr
+
+        new_ptr = self.pymalloc.malloc(new_size)
         if new_ptr == NULL:
             raise MemoryError("Error reallocating to %d bytes" % new_size)
-        memcpy(new_ptr, p, self.addresses[<size_t>p])
-        self.free(p)
-        self.addresses[<size_t>new_ptr] = new_size
+
+        # See comment in alloc on why we're acquiring a critical section on
+        # self.addresses instead of self.
+        with cython.critical_section(self.addresses):
+            try:
+                old_size = self.addresses.pop(<size_t>p)
+            except KeyError:
+                self.pyfree.free(new_ptr)
+                raise ValueError("Pointer %d not found in Pool %s" % 
(<size_t>p, self.addresses))
+
+            if old_size >= new_size:
+                self.addresses[<size_t>p] = old_size
+                self.pyfree.free(new_ptr)
+                raise ValueError("Realloc requires new_size > previous size")
+
+            memcpy(new_ptr, p, old_size)
+            memset(<char*> new_ptr + old_size, 0, new_size - old_size)
+            self.size += new_size - old_size
+            self.addresses[<size_t>new_ptr] = new_size
+
+        self.pyfree.free(p)
         return new_ptr
 
     cdef void free(self, void* p) except *:
@@ -105,10 +143,17 @@
 
         If p is not in Pool.addresses, a KeyError is raised.
         """
-        self.size -= self.addresses.pop(<size_t>p)
+        cdef size_t size
+
+        # See comment in alloc on why we're acquiring a critical section on
+        # self.addresses instead of self.
+        with cython.critical_section(self.addresses):
+            size = self.addresses.pop(<size_t>p)
+            self.size -= size
         self.pyfree.free(p)
 
     def own_pyref(self, object py_ref):
+        # Calling append here is atomic, no critical section needed.
         self.refs.append(py_ref)
 
 
@@ -142,9 +187,9 @@
             raise MemoryError("Error assigning %d bytes" % number * elem_size)
         memset(self.ptr, 0, number * elem_size)
 
-    property addr:
-        def __get__(self):
-            return <size_t>self.ptr
+    @property
+    def addr(self):
+        return <size_t>self.ptr
 
     def __dealloc__(self):
         if self.ptr != NULL:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/cymem.egg-info/PKG-INFO 
new/cymem-2.0.13/cymem.egg-info/PKG-INFO
--- old/cymem-2.0.11/cymem.egg-info/PKG-INFO    2025-01-16 21:57:24.000000000 
+0100
+++ new/cymem-2.0.13/cymem.egg-info/PKG-INFO    2025-11-14 10:49:51.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: cymem
-Version: 2.0.11
+Version: 2.0.13
 Summary: Manage calls to calloc/free through Cython
 Home-page: https://github.com/explosion/cymem
 Author: Matthew Honnibal
@@ -14,19 +14,15 @@
 Classifier: Operating System :: MacOS :: MacOS X
 Classifier: Operating System :: Microsoft :: Windows
 Classifier: Programming Language :: Cython
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
+Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
 Classifier: Topic :: Scientific/Engineering
+Requires-Python: >=3.9,<3.15
 Description-Content-Type: text/markdown
 License-File: LICENSE
 Dynamic: author
@@ -36,6 +32,8 @@
 Dynamic: description-content-type
 Dynamic: home-page
 Dynamic: license
+Dynamic: license-file
+Dynamic: requires-python
 Dynamic: summary
 
 <a href="https://explosion.ai";><img 
src="https://explosion.ai/assets/img/logo.svg"; width="125" height="125" 
align="right" /></a>
@@ -235,3 +233,28 @@
 from cymem.cymem cimport Pool, WrapMalloc, WrapFree
 cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
 ```
+
+## Thread Safety
+
+As of version 2.0.12, `cymem.Pool` is thread-safe when used with CPython 3.13+
+free-threaded builds (PEP 703). All operations on the Pool, including 
`alloc()`,
+`free()`, and `realloc()`, can be safely called from multiple threads 
concurrently.
+
+**Key guarantees:**
+- Multiple threads can safely call `alloc()`, `free()`, and `realloc()` on the
+    same `Pool` instance.
+- The Pool's internal bookkeeping (`addresses` dict and `size` accounting) is
+    protected from race conditions. Reading the internal state without
+    holding a lock on the `Pool` instance via a critical section is not
+    thread-safe.
+
+**Important notes:**
+- Individual Pool instances are thread-safe, but you are still responsible for
+    proper synchronization when accessing the memory contents themselves. Note
+    that holding a lock on the Pool itself is typically not the right approach:
+    since malloc is thread-safe, memory allocated by separate calls to `alloc`
+    can be safely accessed concurrently without locking. You should only
+    synchronize access to specific memory regions that are being shared across
+    threads, using fine-grained locks appropriate to your use case rather than 
a
+    coarse-grained lock on the entire `Pool`.
+- Custom memory allocators need to be thread-safe themselves.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/pyproject.toml 
new/cymem-2.0.13/pyproject.toml
--- old/cymem-2.0.11/pyproject.toml     2025-01-16 21:57:19.000000000 +0100
+++ new/cymem-2.0.13/pyproject.toml     2025-11-14 10:49:44.000000000 +0100
@@ -1,15 +1,15 @@
 [build-system]
 requires = [
     "setuptools",
-    "cython>=0.25",
+    "cython>=3.1",
 ]
 build-backend = "setuptools.build_meta"
 
 [tool.cibuildwheel]
 build = "*"
-skip = "pp* cp36* cp37* cp38*"
+skip = "cp38*"
 test-skip = ""
-free-threaded-support = false
+enable = ["cpython-freethreading"]
 
 archs = ["native"]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cymem-2.0.11/setup.py new/cymem-2.0.13/setup.py
--- old/cymem-2.0.11/setup.py   2025-01-16 21:57:19.000000000 +0100
+++ new/cymem-2.0.13/setup.py   2025-11-14 10:49:44.000000000 +0100
@@ -89,6 +89,7 @@
 
         setup(
             name="cymem",
+            python_requires=">=3.9,<3.15",
             zip_safe=False,
             packages=PACKAGES,
             package_data={"": ["*.pyx", "*.pxd"]},
@@ -100,8 +101,8 @@
             version=about["__version__"],
             url=about["__uri__"],
             license=about["__license__"],
-            ext_modules=cythonize(ext_modules, language_level=2),
-            setup_requires=["cython>=0.25"],
+            ext_modules=cythonize(ext_modules),
+            setup_requires=["cython>=3.1"],
             classifiers=[
                 "Environment :: Console",
                 "Intended Audience :: Developers",
@@ -111,18 +112,13 @@
                 "Operating System :: MacOS :: MacOS X",
                 "Operating System :: Microsoft :: Windows",
                 "Programming Language :: Cython",
-                "Programming Language :: Python :: 2.6",
-                "Programming Language :: Python :: 2.7",
-                "Programming Language :: Python :: 3.3",
-                "Programming Language :: Python :: 3.4",
-                "Programming Language :: Python :: 3.5",
-                "Programming Language :: Python :: 3.6",
-                "Programming Language :: Python :: 3.7",
-                "Programming Language :: Python :: 3.8",
                 "Programming Language :: Python :: 3.9",
                 "Programming Language :: Python :: 3.10",
                 "Programming Language :: Python :: 3.11",
                 "Programming Language :: Python :: 3.12",
+                "Programming Language :: Python :: 3.13",
+                "Programming Language :: Python :: 3.14",
+                "Programming Language :: Python :: Free Threading :: 2 - Beta",
                 "Topic :: Scientific/Engineering",
             ],
             cmdclass={"build_ext": build_ext_subclass},

Reply via email to