Ship Python 3.15 wheels

未关闭
#298 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
64/100
Issue 类型
功能
描述清晰度
描述清楚
活跃度
活跃
技术栈
python

调研方向

Start with python/tensorstore/garbage_collection.cc and tools/ci/cibuildwheel.py; the issue identifies the two weak reference calls and the CIBW_SKIP entries to update. Build //python/tensorstore:_tensorstore for CPython 3.15, then run pytest python/tensorstore/tests --asyncio-mode=auto; the issue reports environment-related failures in fork_test.py. Done when 3.15 wheels are enabled and the package builds and tests on that version; free-threaded cp315t support remains untested.

由索引模型根据 Issue 内容生成。

描述

Feature request: provide PyPI wheels for Python 3.15, as #254 did for 3.14.

Python 3.15 removed PyWeakref_GET_OBJECT and PyWeakref_GetObject (python/cpython#133657). As far as I can see, the only uses in TensorStore are the two calls in python/tensorstore/garbage_collection.cc, and cp315-* and cp315t-* are currently in CIBW_SKIP.

The patch below routes both calls through a small helper that keeps the existing borrowed-reference semantics, using PyWeakref_GetRef on 3.13 and later. It also drops the 3.15 entries from CIBW_SKIP.

What I checked, at 8fd9e3acc with the patch applied, on Linux x86_64 with CPython 3.15.2:

  • bazelisk.py build -c fastbuild //python/tensorstore:_tensorstore completes.
  • pytest python/tensorstore/tests --asyncio-mode=auto: 373 passed, 2 failed. The two failures are in fork_test.py. They hit PERMISSION_DENIED while listing a systemd-private directory under /tmp on my machine, so they come from my environment, not from 3.15.
  • The pinned numpy==2.4.6 in third_party/pypa/workspace.bzl has no cp315 wheel, so pip built it from source during the fetch. It works but is slow, so a bump to numpy 2.5 may be worth it.

I have not tested the free-threaded build (cp315t). The helper is exactly as safe there as the current code, which uses a borrowed reference too.

Context: orbax-checkpoint cannot be installed on 3.15 until a TensorStore release ships these wheels.

diff --git a/python/tensorstore/garbage_collection.cc b/python/tensorstore/garbage_collection.cc
index a36c4bc..b7d0d7a 100644
--- a/python/tensorstore/garbage_collection.cc
+++ b/python/tensorstore/garbage_collection.cc
@@ -34,6 +34,24 @@ namespace py = ::pybind11;
 namespace tensorstore {
 namespace internal_python {
 
+namespace {
+
+// Returns a borrowed reference to the referent of `weak_ref`, or `nullptr` if
+// the referent has been destroyed.
+PyObject* GetWeakRefReferent(PyObject* weak_ref) {
+#if PY_VERSION_HEX >= 0x030D0000
+  PyObject* obj;
+  if (PyWeakref_GetRef(weak_ref, &obj) <= 0) return nullptr;
+  Py_DECREF(obj);
+  return obj;
+#else
+  PyObject* obj = PyWeakref_GET_OBJECT(weak_ref);
+  return obj == Py_None ? nullptr : obj;
+#endif
+}
+
+}  // namespace
+
 PythonObjectReferenceManager::PythonObjectReferenceManager() = default;
 
 PythonObjectReferenceManager::PythonObjectReferenceManager(
@@ -105,8 +123,8 @@ void PythonObjectReferenceManager::Visitor::DoIndirect(
     }
 
     // Actual weak reference.
-    PyObject* python_obj = PyWeakref_GET_OBJECT(weak_ref.get());
-    if (python_obj == Py_None) return;
+    PyObject* python_obj = GetWeakRefReferent(weak_ref.get());
+    if (!python_obj) return;
 
     if (manager_.python_refs_.insert(python_obj).second) {
       Py_INCREF(python_obj);
@@ -198,12 +216,8 @@ pybind11::handle PythonWeakRef::get_value_or_null() const {
     // Actually a strong reference.
     return weak_ref.get();
   }
-  PyObject* obj = PyWeakref_GET_OBJECT(weak_ref.get());
-  if (obj == Py_None) {
-    // Since `None` does not support weak references, we know that the actual
-    // value was not `None`.
-    return pybind11::handle();
-  }
+  PyObject* obj = GetWeakRefReferent(weak_ref.get());
+  if (!obj) return pybind11::handle();
   auto* python_type = Py_TYPE(obj);
   if (python_type == &WeakRefAdapterType) {
     return reinterpret_cast<WeakRefAdapterObject*>(obj)->owned_object;
diff --git a/tools/ci/cibuildwheel.py b/tools/ci/cibuildwheel.py
index 6e8d2f5..523cfa3 100755
--- a/tools/ci/cibuildwheel.py
+++ b/tools/ci/cibuildwheel.py
@@ -132,7 +132,7 @@ def run(args, extra_args):
   env["CIBW_ARCHS_MACOS"] = "x86_64 arm64"
   # https://cibuildwheel.pypa.io/en/stable/options/#build-skip
   env["CIBW_SKIP"] = (
-      "cp38-* cp39-* cp310-* cp314t-win* cp315-* cp315t-* "
+      "cp38-* cp39-* cp310-* cp314t-win* "
       "*_i686 *-win32 *-musllinux*"
   )
   env["CIBW_TEST_COMMAND"] = (
主要语言
C++
星标
1.6k
派生
151
PR 合并指标
30 天内没有已合并 PR

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

google/tensorstore 的其他 Issue

查看 google/tensorstore 的全部 Issue

相似的 Issue

更多 C++ Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。