Skip to content

Fix Python bindings when optional modules are disabled#28660

Merged
asmorkalov merged 1 commit intoopencv:4.xfrom
PavelGuzenfeld:fix/gapi-optional-module-handling
Mar 16, 2026
Merged

Fix Python bindings when optional modules are disabled#28660
asmorkalov merged 1 commit intoopencv:4.xfrom
PavelGuzenfeld:fix/gapi-optional-module-handling

Conversation

@PavelGuzenfeld
Copy link
Copy Markdown
Contributor

Summary

Fixes two issues that cause import cv2 to fail when building OpenCV with -DBUILD_opencv_gapi=OFF -DWITH_GAPI=OFF.

PR #26633 added required_modules filtering to the typing stubs generator, which addressed the main problem. However, two issues remain:

1. Wrong variable in has_all_required_modules() (generation.py)

The function parameter is named type_node but the body uses node — the loop variable from the enclosing scope:

def has_all_required_modules(type_node: TypeNode) -> bool:
    return all(em in root.namespaces for em in node.required_modules)
    #                                          ^^^^ should be type_node

This works by accident because the function is only called as has_all_required_modules(node), so the closure variable node happens to equal the argument. Fixed by using type_node.required_modules.

2. __load_extra_py_code_for_module() only catches ImportError (cv2/__init__.py)

When a stale gapi/ submodule directory persists from a previous build (e.g., in incremental builds), the runtime loader discovers it and attempts to import it. The gapi/__init__.py calls cv.gapi_GNetPackage(...) at import time, which raises AttributeError when the gapi C++ bindings are absent. The loader only catches ImportError, so the AttributeError propagates and crashes import cv2.

Fixed by catching (ImportError, AttributeError).

Files Changed

  • modules/python/src2/typing_stubs_generation/generation.py — use function parameter instead of closure variable
  • modules/python/package/cv2/__init__.py — catch AttributeError in addition to ImportError

Testing

Verified with OpenCV 4.11.0 built with -DBUILD_opencv_gapi=OFF -DWITH_GAPI=OFF:

  • import cv2 succeeds without manual post-install cleanup
  • No regression with gapi enabled

Resolves #26098

Fix two issues that cause `import cv2` to fail when building with
-DBUILD_opencv_gapi=OFF:

1. In `has_all_required_modules()`, the function parameter `type_node`
   was ignored in favor of the enclosing scope's loop variable `node`.
   This works by accident when called as `has_all_required_modules(node)`
   but is incorrect — the parameter should be used directly.

2. In `__load_extra_py_code_for_module()`, only `ImportError` was
   caught. When a stale gapi submodule directory exists from a previous
   build, gapi/__init__.py raises `AttributeError` (not `ImportError`)
   because it tries to access C++ bindings that don't exist. Now catches
   both exception types for defense-in-depth.

Refs: opencv#26098
@asmorkalov asmorkalov merged commit 2c83996 into opencv:4.x Mar 16, 2026
24 of 26 checks passed
@PavelGuzenfeld PavelGuzenfeld deleted the fix/gapi-optional-module-handling branch March 16, 2026 21:45
@asmorkalov asmorkalov mentioned this pull request Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python bindings do not respect optional modules

3 participants