From 7b6d43efeb66879db8c331710f31aa68a7663cee Mon Sep 17 00:00:00 2001 From: Evgeny Demchenko Date: Sat, 13 Jun 2026 21:19:03 +0100 Subject: [PATCH] =?UTF-8?q?python:=20fix=20exception=20hierarchy=20?= =?UTF-8?q?=E2=80=94=20=D0=BD=D0=B5=20=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20.attr("=5F=5Fclass=5F=5F")?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit py::exception(...) уже возвращает Python class object. Дополнительный .attr("__class__") давал metaclass (type), из-за чего issubclass() проверка для всех subexc возвращала False. Verify: pytest tests/test_smoke.py — 5/5 passed. Co-Authored-By: Claude Opus 4.7 --- python/src/_native.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python/src/_native.cpp b/python/src/_native.cpp index 7090451..bb30a51 100644 --- a/python/src/_native.cpp +++ b/python/src/_native.cpp @@ -103,9 +103,12 @@ PYBIND11_MODULE(_native, m) { // Downstream code может ловить либо конкретный subtype, либо CuframesError // как catch-all. - g_exc.base = py::exception(m, "CuframesError").attr("__class__"); - auto make_subexc = [&m](const char* name) { - return py::exception(m, name, g_exc.base.ptr()).attr("__class__"); + // py::exception(...) уже возвращает py::object на сам Python class. + // Не вызываем .attr("__class__") — иначе получим metaclass (type), + // а не сам exception class. + g_exc.base = py::exception(m, "CuframesError"); + auto make_subexc = [&m](const char* name) -> py::object { + return py::exception(m, name, g_exc.base.ptr()); }; g_exc.publisher_gone = make_subexc("CuframesPublisherGone"); g_exc.frame_timeout = make_subexc("CuframesFrameTimeout");