diff --git a/docs/sdk/PLUGIN_CONTRACT.schema.json b/docs/sdk/PLUGIN_CONTRACT.schema.json index 70ffc4d33..72f277e72 100644 --- a/docs/sdk/PLUGIN_CONTRACT.schema.json +++ b/docs/sdk/PLUGIN_CONTRACT.schema.json @@ -13,7 +13,7 @@ "$defs": { "semver": { "type": "string", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+([.-][A-Za-z0-9.-]+)?$" + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+([.-][A-Za-z0-9.-]+)?(?![\\s\\S])" }, "trust_level": { "type": "string", diff --git a/tests/test_plugin_sdk_contract.py b/tests/test_plugin_sdk_contract.py index b6150bdd8..ec50e7191 100644 --- a/tests/test_plugin_sdk_contract.py +++ b/tests/test_plugin_sdk_contract.py @@ -64,6 +64,17 @@ def test_examples_validate_against_contract_schema(example_path: Path) -> None: jsonschema.validate(instance=instance, schema=schema) +def test_semver_rejects_trailing_newline_on_python_jsonschema() -> None: + """Python jsonschema uses re.search; `$` would accept a trailing newline. (#1766)""" + semver = _load_schema()["$defs"]["semver"] + jsonschema.validate(instance="1.0.0", schema=semver) + jsonschema.validate(instance="1.2.3-alpha.1", schema=semver) + with pytest.raises(jsonschema.ValidationError): + jsonschema.validate(instance="1.0.0\n", schema=semver) + with pytest.raises(jsonschema.ValidationError): + jsonschema.validate(instance="1.0.0 ", schema=semver) + + def test_invalid_decision_fails_schema() -> None: schema = _load_schema() bad = {