From 4bcffafb21c93b72718469aae266884f3e16b325 Mon Sep 17 00:00:00 2001 From: fraware Date: Wed, 22 Jul 2026 23:46:25 -0700 Subject: [PATCH] Fix CI import crash by requiring jsonschema format checkers. Bare jsonschema omits date-time/uri/duration/hostname checkers, so FormatChecker(formats=ASSERTED_FORMATS) raised KeyError and broke python, lean, and validate-release-chain jobs. Depend on jsonschema[format-nongpl], pin the extras in requirements.lock, and fail with an actionable error if asserted formats are missing. --- docs/json-schema-formats.md | 4 +++- python/pcs_core/validate_detect.py | 22 +++++++++++++++++++++- python/pyproject.toml | 5 +++-- python/requirements.lock | 13 +++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/docs/json-schema-formats.md b/docs/json-schema-formats.md index 06b7963..d28b5d5 100644 --- a/docs/json-schema-formats.md +++ b/docs/json-schema-formats.md @@ -2,7 +2,9 @@ PCS Draft 2020-12 schemas declare `"format"` keywords. In Python, `Draft202012Validator` is constructed with `jsonschema.FormatChecker` so those formats are **assertions**, not -annotations. +annotations. The Python package depends on `jsonschema[format-nongpl]` so checkers for +`date-time`, `uri`, `duration`, and `hostname` are registered at import time (bare +`jsonschema` omits them and raises on asserted-format construction). ## Asserted formats diff --git a/python/pcs_core/validate_detect.py b/python/pcs_core/validate_detect.py index 171b0f4..666b117 100644 --- a/python/pcs_core/validate_detect.py +++ b/python/pcs_core/validate_detect.py @@ -27,7 +27,27 @@ } ) -_FORMAT_CHECKER = FormatChecker(formats=sorted(ASSERTED_FORMATS)) + +def _build_asserted_format_checker() -> FormatChecker: + """Build a FormatChecker limited to ASSERTED_FORMATS. + + jsonschema only registers optional formats (date-time, uri, …) when the + corresponding format extras are installed. Constructing FormatChecker with + unknown names raises KeyError; fail with an actionable message instead. + """ + available = FormatChecker.checkers + missing = sorted(fmt for fmt in ASSERTED_FORMATS if fmt not in available) + if missing: + raise RuntimeError( + "jsonschema format checkers unavailable for: " + + ", ".join(missing) + + ". Install pcs-core dependencies including " + "jsonschema[format-nongpl] (see python/pyproject.toml)." + ) + return FormatChecker(formats=sorted(ASSERTED_FORMATS)) + + +_FORMAT_CHECKER = _build_asserted_format_checker() class DetectionMode(str, Enum): diff --git a/python/pyproject.toml b/python/pyproject.toml index 6fae2cc..84d4aa4 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -10,7 +10,8 @@ readme = "../README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ - "jsonschema>=4.23.0", + # format-nongpl registers date-time/uri/duration/hostname checkers used as assertions + "jsonschema[format-nongpl]>=4.23.0", "referencing>=0.35.0,<0.37.0", ] @@ -27,7 +28,7 @@ quality = [ # Verifier extras document the Lean/OCI path; Lean assets ship via the # verifier OCI image or a PCS_BUILD_VERIFIER=1 wheel (see docs/distribution.md). verifier = [ - "jsonschema>=4.23.0", + "jsonschema[format-nongpl]>=4.23.0", "referencing>=0.35.0,<0.37.0", ] diff --git a/python/requirements.lock b/python/requirements.lock index 89b8a26..b3afd29 100644 --- a/python/requirements.lock +++ b/python/requirements.lock @@ -8,6 +8,19 @@ jsonschema-specifications==2025.9.1 referencing==0.36.2 rpds-py==0.30.0 +# jsonschema[format-nongpl] — required so FormatChecker registers asserted formats +arrow==1.3.0 +fqdn==1.5.1 +idna==3.10 +isoduration==20.11.0 +jsonpointer==3.0.0 +python-dateutil==2.9.0.post0 +rfc3339-validator==0.1.4 +rfc3986-validator==0.1.1 +rfc3987-syntax==1.1.0 +uri-template==1.3.0 +webcolors==24.11.1 + # Optional-dev (CI) pytest==8.3.5 ruff==0.15.9