1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00
Files
kirtijindal14 8756e68bff Merge pull request #29206 from kirtijindal14:doc_optimizations_v3
OpenCV New Documentation #29206

This PR introduces end to end working new Documentation in OpenCV.

Co-authored by: @abhishek-gola @omrope79 @Akansha-977 @Prasadayus @varun-jaiswal17 
### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
2026-06-01 21:39:16 +03:00

172 lines
5.3 KiB
Python

# 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()