# This file is part of OpenCV project. # It is subject to the license terms in the LICENSE file found in the top-level directory # of this distribution and at http://opencv.org/license.html. # Copyright (C) 2026, BigVision LLC, all rights reserved. # Third party copyrights are property of their respective owners. """Runtime patches for Sphinx C++ domain and breathe; applied at import.""" from __future__ import annotations def _patch_cpp_xref_resolver(): """Work around Sphinx 8.1.x parentSymbol assert in _resolve_xref_inner.""" try: from sphinx.domains.cpp import CPPDomain except ImportError: return original = CPPDomain._resolve_xref_inner def guarded(self, env, fromdocname, builder, typ, target, node, contnode): try: return original(self, env, fromdocname, builder, typ, target, node, contnode) except AssertionError: return None, None CPPDomain._resolve_xref_inner = guarded # Drop breathe unresolvable-xref log noise; text still renders. import logging _UNRESOLVED_XREF_PATTERNS = ( "Unable to resolve function", "Unable to resolve class", "Cannot find function", "Cannot find class", "Cannot find variable", "Cannot find typedef", "Cannot find enum", "Cannot find enumerator", "Cannot find define", "Duplicate C++ declaration", ) class _UnresolvedXrefFilter(logging.Filter): def filter(self, record: logging.LogRecord) -> bool: msg = record.getMessage() return not any(p in msg for p in _UNRESOLVED_XREF_PATTERNS) _filt = _UnresolvedXrefFilter() for _logger_name in ("sphinx", "docutils"): logging.getLogger(_logger_name).addFilter(_filt) _patch_cpp_xref_resolver() def _silence_breathe_anon_enum_warning(): """Mute Sphinx parser warning on Doxygen's anonymous nested enums.""" import logging class _AnonEnumFilter(logging.Filter): def filter(self, record: logging.LogRecord) -> bool: msg = record.getMessage() return not ( "Invalid C++ declaration" in msg and "Expected identifier in nested name" in msg ) for _name in ("sphinx", "docutils"): logging.getLogger(_name).addFilter(_AnonEnumFilter()) _silence_breathe_anon_enum_warning() def _patch_breathe_operator_signatures(): """Fix breathe {doxygenfunction} mis-splitting operator overloads.""" try: import breathe.directives.function as _bf except ImportError: return def _split_operator(s: str): rp = s.rfind(")") if rp == -1: return None depth, j = 0, rp while j >= 0: if s[j] == ")": depth += 1 elif s[j] == "(": depth -= 1 if depth == 0: break j -= 1 if j < 0: return None func_part, args_part = s[:j].strip(), s[j:] k = func_part.find("::operator") if k != -1: return func_part[:k], func_part[k + 2:], args_part if "::" in func_part: ns, fn = func_part.rsplit("::", 1) return ns, fn, args_part return "", func_part, args_part class _Shim: __slots__ = ("_g",) def __init__(self, g1, g2, g3): self._g = (None, g1, g2, g3) def group(self, i=0): return self._g[i] class _OperatorAwareRe: def __init__(self, real): object.__setattr__(self, "_real", real) def __getattr__(self, name): return getattr(self._real, name) def match(self, pattern, string, *args, **kwargs): m = self._real.match(pattern, string, *args, **kwargs) if (m is not None and getattr(m.re, "groups", 0) >= 3 and "::operator" in string): res = _split_operator(string) if res is not None: ns, fn, ar = res return _Shim(ns or None, fn, ar) return m if not isinstance(_bf.re, _OperatorAwareRe): _bf.re = _OperatorAwareRe(_bf.re) _patch_breathe_operator_signatures() def _patch_breathe_docsect(): """Render title-less docSectN nodes breathe 4.36 drops.""" try: from breathe.renderer import sphinxrenderer as _bsr except ImportError: return _methods = _bsr.SphinxRenderer.methods if getattr(_methods.get("docsect1"), "_opencv_docsect_patch", False): return _orig_visit = _methods["docsect1"] def _visit_docsectN(self, node): if not getattr(node, "title", None): return self.render_iterable(node.content_) return _orig_visit(self, node) _visit_docsectN._opencv_docsect_patch = True for _kind in ("docsect1", "docsect2", "docsect3"): _methods[_kind] = _visit_docsectN _patch_breathe_docsect() def _silence_orphan_toctree_warning(): """Mute toctree-orphan warning for intentionally unlinked external pages.""" import logging class _OrphanFilter(logging.Filter): def filter(self, record: logging.LogRecord) -> bool: return "included in any toctree" not in record.getMessage() for _name in ("sphinx", "docutils"): logging.getLogger(_name).addFilter(_OrphanFilter()) _silence_orphan_toctree_warning()