chore: bump minimum Python to 3.10#2260
Conversation
- Drop Python 3.9 from CI test matrix - requires-python = ">=3.10" in pyproject.toml - ruff target-version py39 → py310 - mypy python_version 3.9 → 3.10 - Remove Python 3.9 classifier --- Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (80%) is below the target coverage (95%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## develop #2260 +/- ##
========================================
+ Coverage 78% 79% +1%
========================================
Files 66 67 +1
Lines 8410 8811 +401
========================================
+ Hits 6552 6927 +375
- Misses 1858 1884 +26 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This pull request raises the project’s minimum supported Python version to 3.10 and aligns configuration/typing across the repo to use Python 3.10+ features and tooling settings.
Changes:
- Bump
requires-pythonto>=3.10and update lint/type-checker target versions accordingly. - Drop Python 3.9 from CI and modernize type annotations (e.g.,
Optional[T]→T | None,typing.Callable→collections.abc.Callable). - Update docs dependency markers to reflect the new minimum Python version.
Assessment (n/5):
- Code quality: 4/5
- Testing: 4/5
- Docs: 3/5
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
tests/metrics/conftest.py |
Updates type annotations to Python 3.10 union syntax. |
src/supervision/dataset/formats/coco.py |
Replaces typing.Union with ` |
pyproject.toml |
Bumps minimum Python, updates classifiers and tool target versions (ruff/mypy), and adjusts docs dependency markers. |
examples/heatmap_and_track/script.py |
Updates optional parameter typing to Python 3.10 union syntax. |
examples/compact_mask/benchmark.py |
Switches Callable import to collections.abc for modern typing. |
.github/workflows/ci-tests.yml |
Updates the CI Python matrix to reflect supported versions. |
…nnotations compliance
Co-authored-by: Codex <codex@openai.com>
…into bump/py3.10
- Replace float arrays with explicit integer or float types, e.g., `dtype=int32` or `dtype=float32`. - Improve type safety by adding explicit casting in key computations. - Update Ruff ignore rules for additional per-file scenarios. - Refactor imports for cleaner and more direct typing references.
- boxes.py: clip/pad/move/spread restore input-dtype-preserving behavior (was forcing float64/float32); revert doctests - detection/core.py + key_points/core.py: restore __setitem__ runtime isinstance validation and list→ndarray coercion - smoother.py: remove forced float32 on xyxy/confidence stacks; keep null-safety for confidence=None case; revert doctests - metrics/detection.py: revert ConfusionMatrix matrix dtype int32→float64 default; revert doctests - annotators/core.py: polygon cast int64→int32 (cv2 requires CV_32S); HeatMapAnnotator local mask float32→float64 - pyproject.toml: remove ANN (flake8-annotations) from lint.select and all ANN per-file-ignores — policy change unrelated to py3.10 compat --- Co-authored-by: Claude Code <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 84 out of 85 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (2)
src/supervision/utils/conversion.py:71
- Same as above: this wrapper should preserve the wrapped function’s metadata via @functools.wraps(image_processing_fun). Without it, the exported function’s docstring/signature become those of the wrapper, which can break documentation/introspection tooling.
src/supervision/utils/conversion.py:105 - This wrapper should preserve annotate_func metadata via @functools.wraps(annotate_func) for consistent introspection/docs. Currently the wrapper replaces the original function name/docstring/signature.
Agent-Logs-Url: https://github.com/roboflow/supervision/sessions/1d14ff8a-1497-43a2-a1c9-0a79637c1924 Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Agent-Logs-Url: https://github.com/roboflow/supervision/sessions/0e999045-cc3c-4b57-8369-3221cf3c9c52 Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
…cross the codebase
…into bump/py3.10
[resolve #1] Review by @Copilot (PR #2260): "_extract_class_names() removed isinstance(data, dict) guard; can raise AttributeError on malformed YAML" Challenge: evidence=VALID (self-verified) suggestion=VALID resolution=as-suggested - Restore isinstance(data, dict) check before .get("names") in yolo.py - Fix pre-existing [no-any-return] mypy error in annotators/core.py:_load_icon --- Co-authored-by: Claude Code <noreply@anthropic.com>
- requires-python: ">=3.9" → ">=3.10" - Remove Programming Language :: Python :: 3.9 classifier - Drop "3.9" from CI test matrix in ci-tests.yml - Tighten mkdocs-git-committers-plugin-2 env marker to python_version>='3.10' --- Co-authored-by: Claude Code <noreply@anthropic.com>
--- Co-authored-by: Claude Code <noreply@anthropic.com>
…nt uint8 truncation np.asarray(icon, dtype=np.uint8) would silently truncate 16-bit PNG icons; cast() is a typing-only no-op that preserves source data unchanged. [resolve #3] /review finding by foundry:challenger (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com>
…cs modules - metrics/detection.py:749: .astype(np.float32, copy=False) for float64→float32 mismatch - metrics/detection.py:763: fix variadic unpack type mismatch - detection/core.py, converters.py, annotators/core.py, byte_tracker: wrap no-any-return sites with cast() to satisfy strict return-type checks [resolve #2] /review finding by foundry:challenger (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: OpenAI Codex <codex@openai.com>
Precision, Recall, F1Score, MeanAverageRecall all raise ValueError when predictions/targets.class_id is None or predictions.confidence is None. [resolve #4] /review finding by foundry:qa-specialist (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: OpenAI Codex <codex@openai.com>
Keep isinstance(segmentation, dict) check (correct for COCO RLE format) but guard against malformed dicts without 'counts' key — warn and skip. Add tests for dict-RLE, polygon, and malformed-dict segmentation paths. [resolve #5] /review finding by codex (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: OpenAI Codex <codex@openai.com>
…ng and edge cases [resolve #6] /review finding by foundry:qa-specialist (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: OpenAI Codex <codex@openai.com>
[resolve #9] /review finding by codex (report: .reports/review/2026-05-22T05-56-29Z/review-report.md) --- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: OpenAI Codex <codex@openai.com>
- Add 0.29.0 upcoming section with failure admonition block documenting Python 3.9 termination - Update uv.lock to reflect py3.10 minimum (Python 3.9 deps removed from lock) --- Co-authored-by: Claude Code <noreply@anthropic.com>
- Change per_class_ap50_95 field annotation float64 → float32 - Change _average_precisions_per_class return type and array init to float32 - Aligns code with 0.28.0 changelog claim (PR #2169) that metric arrays are float32 --- Co-authored-by: Claude Code <noreply@anthropic.com>
- Remove forced dtype=np.float64 in np.array copy — was silently doubling memory when callers passed float32 inputs - Preserves input floating dtype; integer arrays still upcast naturally - Update return annotation to npt.NDArray[np.number] and docstring --- Co-authored-by: Claude Code <noreply@anthropic.com>
- Add match= parameter to all pytest.raises(ValueError/OSError) in test files - Shorten over-long docstrings to stay within 88-char limit - Rename one test function to fit line-length constraint - Fix ruff-format whitespace in detection/core.py --- Co-authored-by: Claude Code <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 92 out of 93 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/supervision/detection/utils/internal.py:463
get_data_item()now declares it acceptslist[bool]as an index, but theisinstance(index, list)branch treats the list elements as integer indices (value[i] for i in index). For boolean-mask lists this silently indexes withTrue/False(i.e., 1/0) rather than filtering, producing incorrect subsets (and potentially IndexError). Handlelist[bool]explicitly (e.g.,if index and isinstance(index[0], bool): ...) and keep the existing list[int] behavior separate; also consider the empty-list case.
| if len(targets) > 0: | ||
| if predictions.class_id is None or targets.class_id is None: | ||
| raise ValueError( | ||
| "Precision metric requires `class_id` on both predictions " | ||
| "and targets." | ||
| ) | ||
| if len(predictions) == 0: | ||
| stats.append( | ||
| ( | ||
| np.zeros((0, iou_thresholds.size), dtype=bool), | ||
| np.zeros((0,), dtype=np.float32), | ||
| np.zeros((0,), dtype=int), | ||
| targets.class_id, | ||
| np.zeros((0,), dtype=np.int32), | ||
| np.asarray(targets.class_id, dtype=np.int32), | ||
| ) | ||
| ) | ||
|
|
||
| else: | ||
| if predictions.confidence is None: | ||
| raise ValueError( | ||
| "Precision metric requires `confidence` on predictions." | ||
| ) |
This pull request updates the minimum supported Python version for the project from 3.9 to 3.10. The changes ensure consistency across documentation, configuration, and CI workflows, and remove references to Python 3.9 throughout the codebase.
Python version support updates:
pyproject.tomlfrom 3.9 to 3.10, and removed Python 3.9 from the supported classifiers. [1] [2].github/workflows/ci-tests.yml) to start from 3.10 instead of 3.9.Configuration and tooling updates:
ruff(linter) topy310instead ofpy39inpyproject.toml.python_versionsetting formypytype checking from 3.9 to 3.10 inpyproject.toml.