public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/usd] f45: Backport upstream patch for Python 3.15
@ 2026-09-19 22:03 Benjamin A. Beasley
  0 siblings, 0 replies; only message in thread
From: Benjamin A. Beasley @ 2026-09-19 22:03 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/usd
Branch : f45
Commit : 3dd9abd675ec3cc0f8e15fb6f66f93868aa26568
Author : Benjamin A. Beasley <code@musicinmybrain.net>
Date   : 2026-09-19T08:01:23+01:00
Stats  : +402/-117 in 3 file(s)
URL    : https://src.fedoraproject.org/rpms/usd/c/3dd9abd675ec3cc0f8e15fb6f66f93868aa26568?branch=f45

Log:
Backport upstream patch for Python 3.15

---
diff --git a/0001-Replace-PyWeakref_GetObject-with-PyWeakref_GetRef.patch b/0001-Replace-PyWeakref_GetObject-with-PyWeakref_GetRef.patch
deleted file mode 100644
index 97dbab3..0000000
--- a/0001-Replace-PyWeakref_GetObject-with-PyWeakref_GetRef.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-From f3e9600db6086e834c0503cdaf30b5ba7ed53ceb Mon Sep 17 00:00:00 2001
-From: Anonymous Coward <nobody@redhat.com>
-Date: Sun, 26 Jul 2026 16:13:18 +0200
-Subject: [PATCH] Replace PyWeakref_GetObject with PyWeakref_GetRef
-
-PyWeakref_GetObject was removed in Python 3.15. Replace all four call
-sites with PyWeakref_GetRef, which returns a strong reference instead
-of a borrowed one, and adjust reference counting accordingly.
-
-In Tf_PyIdHandle::Ptr(), return Py_None when the referent is dead to
-match the original behaviour (previously returned NULL erroneously).
-
-In Tf_PyWeakObject::GetObject(), explicitly return a Python None object
-on failure, matching the original semantics exactly.
-
-Fixes: https://github.com/PixarAnimationStudios/OpenUSD/issues/3966
-
-Assisted-by: Claude Opus 4.6
-Reviewed-by: OpenUSD Maintainers <usd-maintainers@fedoraproject.org>
----
- pxr/base/tf/pyFunction.h     | 13 +++++++++----
- pxr/base/tf/pyIdentity.cpp   | 10 +++++++++-
- pxr/base/tf/pyWeakObject.cpp | 12 +++++++++---
- 3 files changed, 27 insertions(+), 8 deletions(-)
-
-diff --git a/pxr/base/tf/pyFunction.h b/pxr/base/tf/pyFunction.h
-index 85af943b2..f77b5b71b 100644
---- a/pxr/base/tf/pyFunction.h
-+++ b/pxr/base/tf/pyFunction.h
-@@ -49,11 +49,13 @@ struct TfPyFunctionFromPython<Ret (Args...)>
-             using namespace pxr_boost::python;
-             // Attempt to get the referenced callable object.
-             TfPyLock lock;
--            object callable(handle<>(borrowed(PyWeakref_GetObject(weak.ptr()))));
--            if (TfPyIsNone(callable)) {
-+            PyObject *rawCallable = NULL;
-+            if (PyWeakref_GetRef(weak.ptr(), &rawCallable) <= 0) {
-                 TF_WARN("Tried to call an expired python callback");
-                 return Ret();
-             }
-+            // PyWeakref_GetRef returns a strong reference; handle<> steals it.
-+            object callable{handle<>(rawCallable)};
-             return TfPyCall<Ret>(callable)(args...);
-         }
-     };
-@@ -68,12 +70,15 @@ struct TfPyFunctionFromPython<Ret (Args...)>
-             // Attempt to get the referenced self parameter, then build a new
-             // instance method and call it.
-             TfPyLock lock;
--            PyObject *self = PyWeakref_GetObject(weakSelf.ptr());
--            if (self == Py_None) {
-+            PyObject *self = NULL;
-+            if (PyWeakref_GetRef(weakSelf.ptr(), &self) <= 0) {
-                 TF_WARN("Tried to call a method on an expired python instance");
-                 return Ret();
-             }
-+            // PyWeakref_GetRef returns a strong reference to self; PyMethod_New
-+            // takes its own reference, so release ours afterward.
-             object method(handle<>(PyMethod_New(func.ptr(), self)));
-+            Py_DECREF(self);
-             return TfPyCall<Ret>(method)(args...);
-         }
-     };
-diff --git a/pxr/base/tf/pyIdentity.cpp b/pxr/base/tf/pyIdentity.cpp
-index 5389d8f25..06b7f9b0c 100644
---- a/pxr/base/tf/pyIdentity.cpp
-+++ b/pxr/base/tf/pyIdentity.cpp
-@@ -136,7 +136,15 @@ PyObject *
- Tf_PyIdHandle::Ptr() const {
-     if (_weakRef) {
-         TfPyLock lock;
--        return PyWeakref_GetObject(_weakRef);
-+        PyObject *obj = NULL;
-+        if (PyWeakref_GetRef(_weakRef, &obj) > 0) {
-+            // Return a borrowed-style reference: decrement so the caller
-+            // does not need to release. Safe because the GIL is held by
-+            // all callers.
-+            Py_DECREF(obj);
-+            return obj;
-+        }
-+        return Py_None;   // dead referent → match original behaviour
-     }
-     return 0;
- }
-diff --git a/pxr/base/tf/pyWeakObject.cpp b/pxr/base/tf/pyWeakObject.cpp
-index 8cfddc729..ecdd7f705 100644
---- a/pxr/base/tf/pyWeakObject.cpp
-+++ b/pxr/base/tf/pyWeakObject.cpp
-@@ -115,9 +115,15 @@ Tf_PyWeakObject::GetOrCreate(pxr_boost::python::object const &obj)
- pxr_boost::python::object
- Tf_PyWeakObject::GetObject() const
- {
--    return pxr_boost::python::object
--        (pxr_boost::python::handle<>
--         (pxr_boost::python::borrowed(PyWeakref_GetObject(_weakRef.get()))));
-+    PyObject *obj = NULL;
-+    if (PyWeakref_GetRef(_weakRef.get(), &obj) > 0) {
-+        // PyWeakref_GetRef returns a strong reference; handle<> steals it.
-+        return pxr_boost::python::object(
-+            pxr_boost::python::handle<>(obj));
-+    }
-+    // Dead referent: return Py_None explicitly, as the original did.
-+    return pxr_boost::python::object(
-+        pxr_boost::python::handle<>(pxr_boost::python::borrowed(Py_None)));
- }
- 
- void
--- 
-2.55.0
-

diff --git a/cd3b9c9f031fdface3423ff7a89995dadf4b73aa.patch b/cd3b9c9f031fdface3423ff7a89995dadf4b73aa.patch
new file mode 100644
index 0000000..aade728
--- /dev/null
+++ b/cd3b9c9f031fdface3423ff7a89995dadf4b73aa.patch
@@ -0,0 +1,387 @@
+From cd3b9c9f031fdface3423ff7a89995dadf4b73aa Mon Sep 17 00:00:00 2001
+From: gitamohr <gitamohr@users.noreply.github.com>
+Date: Thu, 17 Sep 2026 15:04:37 -0700
+Subject: [PATCH] tf: Python 3.13 simultaneously deprecates PyWeakref_GetObject
+ and introduces its replacement PyWeakref_GetRef.  PyWeakref_GetObject will be
+ removed in Python 3.15.  Add a Tf_PyWeakrefGetRef shim to pyUtils.h that
+ calls PyWeakRef_GetRef directly on >=3.13, and mimics its behavior on <3.13. 
+ Port pxr's PyWeakref_GetObject callers to use Tf_PyWeakrefGetRef.
+
+Fixes #3966
+
+(Internal change: 2428356)
+---
+ pxr/base/tf/pyFunction.h     |  12 ++--
+ pxr/base/tf/pyIdentity.cpp   | 103 ++++++++++++++++++++++-------------
+ pxr/base/tf/pyUtils.h        |  42 ++++++++++++++
+ pxr/base/tf/pyWeakObject.cpp |  24 +++++---
+ pxr/base/tf/pyWeakObject.h   |   8 ++-
+ 5 files changed, 135 insertions(+), 54 deletions(-)
+
+diff --git a/pxr/base/tf/pyFunction.h b/pxr/base/tf/pyFunction.h
+index 85af943b2c3..66fc7cb8768 100644
+--- a/pxr/base/tf/pyFunction.h
++++ b/pxr/base/tf/pyFunction.h
+@@ -49,11 +49,12 @@ struct TfPyFunctionFromPython<Ret (Args...)>
+             using namespace pxr_boost::python;
+             // Attempt to get the referenced callable object.
+             TfPyLock lock;
+-            object callable(handle<>(borrowed(PyWeakref_GetObject(weak.ptr()))));
+-            if (TfPyIsNone(callable)) {
++            PyObject *callablePtr;
++            if (Tf_PyWeakrefGetRef(weak.ptr(), &callablePtr) != 1) {
+                 TF_WARN("Tried to call an expired python callback");
+                 return Ret();
+             }
++            object callable { handle<> { callablePtr } };
+             return TfPyCall<Ret>(callable)(args...);
+         }
+     };
+@@ -68,12 +69,13 @@ struct TfPyFunctionFromPython<Ret (Args...)>
+             // Attempt to get the referenced self parameter, then build a new
+             // instance method and call it.
+             TfPyLock lock;
+-            PyObject *self = PyWeakref_GetObject(weakSelf.ptr());
+-            if (self == Py_None) {
++            PyObject *selfPtr;
++            if (Tf_PyWeakrefGetRef(weakSelf.ptr(), &selfPtr) != 1) {
+                 TF_WARN("Tried to call a method on an expired python instance");
+                 return Ret();
+             }
+-            object method(handle<>(PyMethod_New(func.ptr(), self)));
++            object self { handle<> { selfPtr } };
++            object method { handle<> { PyMethod_New(func.ptr(), self.ptr()) } };
+             return TfPyCall<Ret>(method)(args...);
+         }
+     };
+diff --git a/pxr/base/tf/pyIdentity.cpp b/pxr/base/tf/pyIdentity.cpp
+index 5389d8f25e2..73db7e82f36 100644
+--- a/pxr/base/tf/pyIdentity.cpp
++++ b/pxr/base/tf/pyIdentity.cpp
+@@ -10,6 +10,7 @@
+ #include "pxr/base/tf/hash.h"
+ #include "pxr/base/tf/mallocTag.h"
+ #include "pxr/base/tf/pyIdentity.h"
++#include "pxr/base/tf/pyUtils.h"
+ #include "pxr/base/tf/staticData.h"
+ #include "pxr/base/tf/stackTrace.h"
+ 
+@@ -30,7 +31,7 @@ Tf_PyOwnershipPtrMap::_CacheType Tf_PyOwnershipPtrMap::_cache;
+ struct Tf_PyIdHandle {
+ 
+     TF_MALLOC_TAG_NEW("Tf", "Tf_PyIdHandle");
+-    
++
+     Tf_PyIdHandle();
+     explicit Tf_PyIdHandle(PyObject *obj);
+     Tf_PyIdHandle(Tf_PyIdHandle const &other);
+@@ -39,20 +40,29 @@ struct Tf_PyIdHandle {
+     void CleanUp();
+     void Release() const;
+     void Acquire() const;
+-    PyObject *Ptr() const;
+-    mutable bool _isAcquired;
++
++    // Return a new reference to the referent, or null if it has expired.
++    PyObject *GetRef() const;
++
++    // Return the referent without owning a reference to it, or null if it has
++    // expired.  Only valid for comparison and diagnostics; the result may
++    // expire as soon as the caller drops the GIL.
++    PyObject *PeekPtr() const;
++
++    // The reference acquired by Acquire(), or null when not acquired.
++    mutable PyObject *_acquired;
+     PyObject *_weakRef;
+ };
+ 
+ 
+ 
+ Tf_PyIdHandle::Tf_PyIdHandle() :
+-    _isAcquired(false), _weakRef(0)
++    _acquired(nullptr), _weakRef(nullptr)
+ {
+ }
+ 
+ Tf_PyIdHandle::Tf_PyIdHandle(PyObject *obj) :
+-    _isAcquired(false), _weakRef(0)
++    _acquired(nullptr), _weakRef(nullptr)
+ {
+     TfPyLock lock;
+     _weakRef = PyWeakref_NewRef(obj, 0);
+@@ -60,7 +70,7 @@ Tf_PyIdHandle::Tf_PyIdHandle(PyObject *obj) :
+ }
+ 
+ Tf_PyIdHandle::Tf_PyIdHandle(Tf_PyIdHandle const &other) :
+-    _isAcquired(false), _weakRef(0)
++    _acquired(nullptr), _weakRef(nullptr)
+ {
+     *this = other;
+ }
+@@ -73,8 +83,9 @@ Tf_PyIdHandle::operator=(Tf_PyIdHandle const &other)
+         _weakRef = other._weakRef;
+         TfPyLock lock;
+         Py_INCREF(_weakRef);
+-        if (other._isAcquired)
++        if (other._acquired) {
+             Acquire();
++        }
+     }
+     return *this;
+ }
+@@ -84,45 +95,36 @@ Tf_PyIdHandle::~Tf_PyIdHandle() {
+ }
+ 
+ void Tf_PyIdHandle::CleanUp() {
+-    if (_isAcquired)
++    if (_acquired) {
+         Release();
++    }
+     TfPyLock lock;
+-    Py_XDECREF(_weakRef);
++    Py_CLEAR(_weakRef);
+ }
+ 
+ void Tf_PyIdHandle::Release() const {
+-    if (_weakRef && !_isAcquired) {
++    if (_weakRef && !_acquired) {
+         // CODE_COVERAGE_OFF Can only get here if there's a bug.
+         TF_CODING_ERROR("Releasing while not acquired!");
+         return;
+         // CODE_COVERAGE_ON
+-    }            
+-    if (PyObject *ptr = Ptr()) {
+-        _isAcquired = false;
+-        TfPyLock lock;
+-        Py_DECREF(ptr);
+-    } else {
+-        // CODE_COVERAGE_OFF Can only get here if there's a bug.
+-        TF_CODING_ERROR("Acquiring Python identity with "
+-                        "expired Python object!");
+-        TfLogStackTrace("Acquiring Python identity with "
+-                        "expired Python object!");
+-        // CODE_COVERAGE_ON
+     }
++    // Holding the acquired reference keeps the referent alive, so there is no
++    // need to consult the weak reference to find it.
++    TfPyLock lock;
++    Py_CLEAR(_acquired);
+ }
+ 
+ void Tf_PyIdHandle::Acquire() const {
+-    if (_isAcquired) {
++    if (_acquired) {
+         // CODE_COVERAGE_OFF Can only get here if there's a bug.
+         TF_CODING_ERROR("Acquiring while already acquired!");
+         return;
+         // CODE_COVERAGE_ON
+     }
+-    if (PyObject *ptr = Ptr()) {
+-        _isAcquired = true;
+-        TfPyLock lock;
+-        Py_INCREF(ptr);
+-    } else {
++    TfPyLock lock;
++    // The reference returned here becomes the acquired reference.
++    if (!(_acquired = GetRef())) {
+         // CODE_COVERAGE_OFF Can only get here if there's a bug.
+         TF_CODING_ERROR("Acquiring Python identity with expired Python "
+                         "object!");
+@@ -133,12 +135,30 @@ void Tf_PyIdHandle::Acquire() const {
+ }
+ 
+ PyObject *
+-Tf_PyIdHandle::Ptr() const {
+-    if (_weakRef) {
+-        TfPyLock lock;
+-        return PyWeakref_GetObject(_weakRef);
++Tf_PyIdHandle::GetRef() const {
++    if (!_weakRef) {
++        return nullptr;
+     }
+-    return 0;
++    TfPyLock lock;
++    PyObject *obj;
++    if (Tf_PyWeakrefGetRef(_weakRef, &obj) < 0) {
++        // CODE_COVERAGE_OFF _weakRef always comes from PyWeakref_NewRef, so
++        // this can only happen if there's a bug.  Note that obj is unspecified
++        // on this path and must not be read.
++        TF_CODING_ERROR("Expected a Python weak reference");
++        PyErr_Clear();
++        return nullptr;
++        // CODE_COVERAGE_ON
++    }
++    return obj;
++}
++
++PyObject *
++Tf_PyIdHandle::PeekPtr() const {
++    TfPyLock lock;
++    PyObject *obj = GetRef();
++    Py_XDECREF(obj);
++    return obj;
+ }
+ 
+ 
+@@ -243,16 +263,21 @@ void Tf_PyIdentityHelper::Set(void const *key, PyObject *obj) {
+     _IdentityMap& _identityMap = _GetIdentityMap();
+     _IdentityMap::iterator i = _identityMap.find(key);
+ 
+-    if (i == _identityMap.end()) { 
++    if (i == _identityMap.end()) {
+         _identityMap[key] = Tf_PyIdHandle(obj);
+         _RecordEstablishedIdentityStack(key);
+-    } else if (i->second.Ptr() != obj) {
++    } else if (i->second.PeekPtr() != obj) {
+         // CODE_COVERAGE_OFF Can only get here if there's a bug.
++        // Hold a reference to the existing object while we report on it, since
++        // _GetTypeName calls back into Python.
++        pxr_boost::python::handle<> existing {
++            pxr_boost::python::allow_null(i->second.GetRef()) };
+         TF_CODING_ERROR("Multiple Python objects for C++ object %p: "
+                         "(Existing python object id %p with type %s, "
+                         "new python object id %p with type %s)",
+-                        key, i->second.Ptr(),
+-                        _GetTypeName(i->second.Ptr()).c_str(),
++                        key, existing.get(),
++                        existing ? _GetTypeName(existing.get()).c_str()
++                                 : "expired",
+                         obj, _GetTypeName(obj).c_str());
+         _IssueMultipleIdentityErrorStacks(key);
+         i->second = Tf_PyIdHandle(obj);
+@@ -274,8 +299,8 @@ PyObject *Tf_PyIdentityHelper::Get(void const *key) {
+         return 0;
+     }
+ 
+-    // use pxr_boost::python::xincref here, because it returns the increfed ptr.
+-    return pxr_boost::python::xincref(i->second.Ptr());
++    // Returns a new reference, or null if the Python object has expired.
++    return i->second.GetRef();
+ }
+ 
+ 
+diff --git a/pxr/base/tf/pyUtils.h b/pxr/base/tf/pyUtils.h
+index 51c18e3cb7c..c751eb59964 100644
+--- a/pxr/base/tf/pyUtils.h
++++ b/pxr/base/tf/pyUtils.h
+@@ -117,6 +117,48 @@ TF_API bool TfPyIsNone(pxr_boost::python::object const &obj);
+ /// Return true iff \a obj is None.
+ TF_API bool TfPyIsNone(pxr_boost::python::handle<> const &obj);
+ 
++/// Get a strong reference to the object referred to by the weak reference
++/// \a ref.
++///
++/// This behaves exactly like PyWeakref_GetRef, which was added in Python 3.13:
++/// on success, store a new strong reference to the referent in \p *pobj and
++/// return 1; if the reference is dead, store null in \p *pobj and return 0; on
++/// error, raise an exception and return -1.  Callers must hold the GIL.
++///
++/// As with PyWeakref_GetRef, \p *pobj is unspecified when this returns -1.
++/// Callers must consult the return value and must not inspect \p *pobj unless
++/// it returned 1 or 0.
++///
++/// PyWeakref_GetRef supersedes PyWeakref_GetObject, which is deprecated in 3.13
++/// and slated for removal in 3.15.  This function exists only to provide
++/// PyWeakref_GetRef on Python versions before 3.13.  Once the minimum supported
++/// Python is 3.13, every call can be replaced with a direct call to
++/// PyWeakref_GetRef and this function deleted.
++inline int
++Tf_PyWeakrefGetRef(PyObject *ref, PyObject **pobj)
++{
++#if PY_VERSION_HEX >= 0x030D0000
++    return PyWeakref_GetRef(ref, pobj);
++#else
++    PyObject *obj = PyWeakref_GetObject(ref);
++    if (!obj) {
++        // Not a weak reference; PyWeakref_GetObject has set an exception.
++        // Leave *pobj alone: PyWeakref_GetRef does not specify its value on
++        // error, so neither do we.
++        return -1;
++    }
++    if (obj == Py_None) {
++        // The referent has expired.  None itself is not weak-referenceable, so
++        // this cannot be a live referent.
++        *pobj = nullptr;
++        return 0;
++    }
++    Py_INCREF(obj);
++    *pobj = obj;
++    return 1;
++#endif
++}
++
+ // Helper for \c TfPyObject().
+ TF_API void Tf_PyObjectError(bool printError);
+ 
+diff --git a/pxr/base/tf/pyWeakObject.cpp b/pxr/base/tf/pyWeakObject.cpp
+index 8cfddc72956..84a25a52d16 100644
+--- a/pxr/base/tf/pyWeakObject.cpp
++++ b/pxr/base/tf/pyWeakObject.cpp
+@@ -115,32 +115,38 @@ Tf_PyWeakObject::GetOrCreate(pxr_boost::python::object const &obj)
+ pxr_boost::python::object
+ Tf_PyWeakObject::GetObject() const
+ {
+-    return pxr_boost::python::object
+-        (pxr_boost::python::handle<>
+-         (pxr_boost::python::borrowed(PyWeakref_GetObject(_weakRef.get()))));
++    PyObject *obj;
++    if (Tf_PyWeakrefGetRef(_weakRef.get(), &obj) != 1) {
++        // The referent has expired; report it as None.
++        return pxr_boost::python::object();
++    }
++    return pxr_boost::python::object(pxr_boost::python::handle<>(obj));
+ }
+ 
+ void
+ Tf_PyWeakObject::Delete()
+ {
+-    Tf_PyWeakObjectRegistry::GetInstance().Remove(GetObject().ptr());
++    // Use the cached key rather than GetObject(): our weak reference has
++    // already been cleared by the time this callback runs.
++    Tf_PyWeakObjectRegistry::GetInstance().Remove(_refObjKey);
+     delete this;
+ }
+-    
++
+ Tf_PyWeakObject::Tf_PyWeakObject(pxr_boost::python::object const &obj)
+     : _weakRef(
+         PyWeakref_NewRef(
+             obj.ptr(), pxr_boost::python::
+             object(Tf_PyWeakObjectDeleter(TfCreateWeakPtr(this))).ptr()))
++    , _refObjKey(obj.ptr())
+ {
+     Tf_PyWeakObjectPtr self(this);
+-    
++
+     // Set our python identity, but release it immediately, since we are a weak
+     // reference and will expire as soon as the python object does.
+-    Tf_PyReleasePythonIdentity(self, GetObject().ptr());
+-    
++    Tf_PyReleasePythonIdentity(self, _refObjKey);
++
+     // Install us in the registry.
+-    Tf_PyWeakObjectRegistry::GetInstance().Insert(GetObject().ptr(), self);
++    Tf_PyWeakObjectRegistry::GetInstance().Insert(_refObjKey, self);
+ }
+ 
+ PXR_NAMESPACE_CLOSE_SCOPE
+diff --git a/pxr/base/tf/pyWeakObject.h b/pxr/base/tf/pyWeakObject.h
+index 283887721c2..4fe2f2675fb 100644
+--- a/pxr/base/tf/pyWeakObject.h
++++ b/pxr/base/tf/pyWeakObject.h
+@@ -38,8 +38,14 @@ struct Tf_PyWeakObject : public TfWeakBase
+     
+ private:
+     explicit Tf_PyWeakObject(pxr_boost::python::object const &obj);
+-    
++
+     pxr_boost::python::handle<> _weakRef;
++
++    // The address of the referent, cached at construction for use as the
++    // registry key.  A weak reference is cleared before its callback runs, so
++    // the referent cannot be recovered from _weakRef by the time Delete() runs.
++    // Used only as a key; never dereferenced.
++    PyObject *_refObjKey;
+ };
+ 
+ PXR_NAMESPACE_CLOSE_SCOPE

diff --git a/usd.spec b/usd.spec
index f505ea3..94be5ec 100644
--- a/usd.spec
+++ b/usd.spec
@@ -148,13 +148,21 @@ Patch:          0006-Downstream-only-use-the-system-libavif.patch
 # https://github.com/PixarAnimationStudios/OpenUSD/pull/3903
 Patch:          %{forgeurl}/pull/3903.patch
 
-# Replace PyWeakref_GetObject with PyWeakref_GetRef
-# Fixes RHBZ#2433881. This patch is LLM-generated and needs expert human
-# review, but it at least builds. See discussion in
-# https://bugzilla.redhat.com/show_bug.cgi?id=2433881.
-# Mentioned upstream in
-# https://github.com/PixarAnimationStudios/OpenUSD/issues/3966#issuecomment-5128542913.
-Patch:          0001-Replace-PyWeakref_GetObject-with-PyWeakref_GetRef.patch
+# tf: Python 3.13 simultaneously deprecates PyWeakref_GetObject and introduces
+# its replacement PyWeakref_GetRef.  PyWeakref_GetObject will be removed in
+# Python 3.15.  Add a Tf_PyWeakrefGetRef shim to pyUtils.h that calls
+# PyWeakRef_GetRef directly on >=3.13, and mimics its behavior on <3.13.  Port
+# pxr's PyWeakref_GetObject callers to use Tf_PyWeakrefGetRef.
+#
+# https://github.com/PixarAnimationStudios/OpenUSD/commit/cd3b9c9f031fdface3423ff7a89995dadf4b73aa
+#
+# Fixes:
+#
+# PyWeakref_GetObject removed in Python 3.15
+# https://github.com/PixarAnimationStudios/OpenUSD/issues/3966
+#
+# Fixes RHBZ#2433881.
+Patch:          %{forgeurl}/commit/cd3b9c9f031fdface3423ff7a89995dadf4b73aa.patch
 
 # Base
 BuildRequires:  gcc-c++

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-19 22:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-19 22:03 [rpms/usd] f45: Backport upstream patch for Python 3.15 Benjamin A. Beasley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox