From ad66409bc74759397db5079552d455d51d18394c Mon Sep 17 00:00:00 2001 From: isaiah-harville Date: Wed, 1 Jul 2026 10:03:13 -0500 Subject: [PATCH 1/2] Add headless OpenCV extras (`*-headless`) Every extra that depends on the GUI OpenCV build (`opencv-contrib-python`) now has an auto-generated `-headless` counterpart that uses `opencv-contrib-python-headless` instead. This lets PaddleX be installed in headless environments (servers, containers, CI) without the system GUI libraries (e.g. libGL) that the GUI OpenCV build requires. Generated variants: cv-headless, multimodal-headless, ie-headless, trans-headless, ocr-core-headless, ocr-headless, video-headless, serving-headless. Existing extras are unchanged. Co-Authored-By: Claude Opus 4.8 --- setup.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/setup.py b/setup.py index 66f23a2eb5..3061ae1b4c 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ "openai": ">= 1.63", "OpenCC": "", "opencv-contrib-python": "== 4.10.0.84", + "opencv-contrib-python-headless": "== 4.10.0.84", "openpyxl": "", "packaging": "", "pandas": ">= 1.3", @@ -278,6 +279,24 @@ def _sort_dep_specs(dep_specs): return sorted(dep_specs, key=str.lower) +def _to_headless(deps): + """Swap the GUI OpenCV build for the headless one. + + Accepts a list of dependency names (as used by the ``base`` extras) or full + dependency specifiers (as used by the ``plugins`` extras) and returns a new + list where ``opencv-contrib-python`` is replaced by + ``opencv-contrib-python-headless``, preserving any version specifier. The + list is returned unchanged when it contains no OpenCV dependency. + """ + headless = [] + for dep in deps: + name = dep.split(" ", 1)[0] + if name == "opencv-contrib-python": + dep = "opencv-contrib-python-headless" + dep[len(name):] + headless.append(dep) + return headless + + def readme(): """get readme""" with open("README.md", "r", encoding="utf-8") as file: @@ -297,11 +316,25 @@ def extras(): extra_dep_specs = _get_dep_specs(extra_deps) dic[extra_name] = _sort_dep_specs(extra_dep_specs) base_dep_specs.update(extra_dep_specs) + + # For extras that pull in the GUI OpenCV build, expose a `-headless` + # counterpart that uses `opencv-contrib-python-headless` instead, so it + # can be installed in headless environments (servers, containers, CI) + # without the system GUI libraries (e.g. libGL) the GUI build requires. + headless_deps = _to_headless(extra_deps) + if headless_deps != extra_deps: + dic[extra_name + "-headless"] = _sort_dep_specs( + _get_dep_specs(headless_deps) + ) dic["base"] = _sort_dep_specs(base_dep_specs) for extra_name, extra_dep_specs in EXTRAS["plugins"].items(): dic[extra_name] = _sort_dep_specs(extra_dep_specs) + headless_dep_specs = _to_headless(extra_dep_specs) + if headless_dep_specs != extra_dep_specs: + dic[extra_name + "-headless"] = _sort_dep_specs(headless_dep_specs) + return dic From 474c6c86daf07335ee0f9a6fdd9cb61648e8304f Mon Sep 17 00:00:00 2001 From: isaiah-harville Date: Wed, 1 Jul 2026 12:39:57 -0500 Subject: [PATCH 2/2] loosen minimum version --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 3061ae1b4c..b92be9f94c 100644 --- a/setup.py +++ b/setup.py @@ -58,8 +58,8 @@ "numpy": ">= 1.24, < 2.4", "openai": ">= 1.63", "OpenCC": "", - "opencv-contrib-python": "== 4.10.0.84", - "opencv-contrib-python-headless": "== 4.10.0.84", + "opencv-contrib-python": ">=4.10", + "opencv-contrib-python-headless": ">=4.10", "openpyxl": "", "packaging": "", "pandas": ">= 1.3",