112 lines
2.6 KiB
Python
112 lines
2.6 KiB
Python
"""Tests for the private OpenCV facade."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import subprocess
|
|
import sys
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
from supervision import _cv2
|
|
|
|
try:
|
|
cv2 = importlib.import_module("cv2")
|
|
except (ImportError, OSError):
|
|
pytest.skip(
|
|
"OpenCV is required as the reference implementation for this test module",
|
|
allow_module_level=True,
|
|
)
|
|
|
|
|
|
REQUIRED_SYMBOLS = {
|
|
"VideoCapture",
|
|
"VideoWriter",
|
|
"VideoWriter_fourcc",
|
|
"addWeighted",
|
|
"approxPolyDP",
|
|
"blur",
|
|
"circle",
|
|
"connectedComponents",
|
|
"connectedComponentsWithStats",
|
|
"contourArea",
|
|
"convertScaleAbs",
|
|
"copyMakeBorder",
|
|
"cvtColor",
|
|
"drawContours",
|
|
"ellipse",
|
|
"fillPoly",
|
|
"find_contours",
|
|
"flip",
|
|
"getTextSize",
|
|
"imread",
|
|
"imwrite",
|
|
"intersectConvexConvex",
|
|
"line",
|
|
"mean",
|
|
"merge",
|
|
"polylines",
|
|
"putText",
|
|
"rectangle",
|
|
"resize",
|
|
"split",
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"symbol",
|
|
[
|
|
pytest.param(symbol, id=symbol.lower().replace("_", "-"))
|
|
for symbol in sorted(REQUIRED_SYMBOLS)
|
|
],
|
|
)
|
|
def test_facade_exports_required_opencv_symbol(symbol: str) -> None:
|
|
"""Expose each OpenCV symbol used by production call sites."""
|
|
assert symbol in _cv2.__all__
|
|
assert hasattr(_cv2, symbol)
|
|
|
|
|
|
def test_facade_reports_opencv_backend() -> None:
|
|
"""Report OpenCV when the native backend is available."""
|
|
assert _cv2.BACKEND_NAME == "opencv"
|
|
|
|
|
|
def test_facade_routes_color_calls_to_opencv() -> None:
|
|
"""Route color conversion calls through the Supervision facade."""
|
|
image = np.array([[[10, 20, 30], [40, 50, 60]]], dtype=np.uint8)
|
|
|
|
np.testing.assert_array_equal(
|
|
_cv2.cvtColor(image, _cv2.COLOR_BGR2RGB),
|
|
cv2.cvtColor(image, cv2.COLOR_BGR2RGB),
|
|
)
|
|
|
|
|
|
def test_facade_routes_resize_calls_to_opencv() -> None:
|
|
"""Route resize calls through the Supervision facade."""
|
|
image = np.array([[[10, 20, 30], [40, 50, 60]]], dtype=np.uint8)
|
|
|
|
np.testing.assert_array_equal(
|
|
_cv2.resize(image, (4, 2), interpolation=_cv2.INTER_NEAREST),
|
|
cv2.resize(image, (4, 2), interpolation=cv2.INTER_NEAREST),
|
|
)
|
|
|
|
|
|
def test_facade_does_not_hide_a_breaking_opencv_import() -> None:
|
|
"""Raise when cv2 imports but no longer exposes a required symbol."""
|
|
code = """
|
|
import sys
|
|
import types
|
|
|
|
sys.modules["cv2"] = types.ModuleType("cv2")
|
|
from supervision import _cv2
|
|
"""
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", code],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
assert result.returncode != 0
|
|
assert "cannot import name" in result.stderr
|