Files
opencv-MIRROR/modules/python/src2
Kari Pikkarainen 53ebe537da Merge pull request #30139 from kari-pikkarainen:fix/python-stubs-optional-output-args
python: mark documented None output arrays as optional in typing stubs 🤖🤖🤖 - #30139

Fixes #30138

The generated Python stubs type several output arrays as required, although OpenCV's own Python samples and tutorials pass `None` for them and the function allocates the output. These arrays are `InputOutputArray`/`OutputArray` parameters without a C++ default, so the stub generator does not add `| None`. As a result, mypy rejects correct code with `No overload variant ... matches [call-overload]`.

This PR adds `make_optional_arg` entries to `NODES_TO_REFINE` in `modules/python/src2/typing_stubs_generation/api_refinement.py`, the same approach as #28470 (`calibrateCamera`) and #27564:

| Function | Argument |
|---|---|
| `calcOpticalFlowPyrLK` | `nextPts` |
| `calcOpticalFlowFarneback` | `flow` |
| `normalize` | `dst` |
| `kmeans` | `bestLabels` |
| `drawKeypoints` | `outImage` |
| `drawMatches` | `outImg` |
| `drawMatchesKnn` | `outImg` |

`None` is only valid at runtime when the corresponding flag is not set (`OPTFLOW_USE_INITIAL_FLOW`, `KMEANS_USE_INITIAL_LABELS`, `DrawMatchesFlags_DRAW_OVER_OUTIMG`). Like `distCoeffs` in #28470, the change only widens the accepted type and does not change bindings or runtime behaviour.

### Verification

- I ran `gen2.py` from this branch and from `4.x` (62587ae) using the CMake-generated `gen_python_config.json`. The only differences in the generated `cv2/__init__.pyi` are 16 signatures (Mat and UMat overloads for each function; `drawMatches` has two C++ overloads). In each one, the listed argument changes from `cv2.typing.MatLike` / `UMat` to `... | None`. With a fixed `PYTHONHASHSEED` no other file differs; without it, the import order in `cv2/typing/__init__.py` varies from run to run because `generation.py` iterates a set, independently of this change.
- mypy 2.4.0 (MYPYPATH pointing at the generated stubs) on the 7 calls from #30138, for example `cv2.calcOpticalFlowPyrLK(prev, curr, pts, None)` and `cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)`: all 7 fail with `call-overload` on the base stubs, and mypy reports no errors for these calls on the patched stubs (the generated stubs have some pre-existing internal errors, unchanged by this PR). The same calls run correctly with `opencv-python-headless` 4.14.0.94 and 5.0.0.93.
- No C++ or binding code changes. No regression test is added, because the repository has no existing test for the stub generator or `api_refinement.py` to extend.

_Prepared with AI assistance (Claude Code); I reviewed the change and the verification results._

**Update:** Added a second commit: `NODES_TO_REFINE` entries whose function, class or namespace is absent from the build (e.g. `video` or `calib3d` disabled via `BUILD_LIST`) are now skipped instead of aborting stub generation, as the `dnn`/`cuda` refinements already do. This also fixes the pre-existing failure for builds without `calib3d`. A wrong argument name in a present function still raises `RuntimeError`; a misspelled function name is now skipped like an absent one. Builds without `features2d` still fail for a separate reason (the `Feature2D` aliases in `predefined_types.py`), which I'll address in a follow-up.

### 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
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-10-05 15:04:00 +03:00
..