From 9761ca4ee0ddabe9c8b9642b1e09ffcd5388e69e Mon Sep 17 00:00:00 2001 From: p1c2u Date: Thu, 26 Feb 2026 12:46:15 +0000 Subject: [PATCH] Align pattern error behavior with jsonschema validation paths --- docs/validation.rst | 16 ++++++++++++++++ openapi_schema_validator/shortcuts.py | 8 +++++++- tests/integration/test_validators.py | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/validation.rst b/docs/validation.rst index 7eccd33..23fd1f1 100644 --- a/docs/validation.rst +++ b/docs/validation.rst @@ -127,6 +127,22 @@ In order to validate OpenAPI 3.0 schema, import and use ``OAS30Validator`` inste validate({"name": "John", "age": None}, schema, cls=OAS30Validator) +Schema errors vs instance errors +-------------------------------- + +The high-level ``validate(...)`` helper checks schema validity before instance +validation, following ``jsonschema.validate(...)`` behavior. +Malformed schema values (for example an invalid regex in ``pattern``) raise +``SchemaError``. + +If you instantiate a validator class directly and call ``.validate(...)``, +schema checking is not performed automatically, matching +``jsonschema`` validator-class behavior. +For malformed regex patterns this may raise a lower-level regex error. + +Use ``.check_schema(schema)`` first when you need deterministic +schema-validation errors with direct validator usage. + Read/write context ------------------ diff --git a/openapi_schema_validator/shortcuts.py b/openapi_schema_validator/shortcuts.py index bb486ba..ae0ebae 100644 --- a/openapi_schema_validator/shortcuts.py +++ b/openapi_schema_validator/shortcuts.py @@ -19,7 +19,13 @@ def validate( **kwargs: Any ) -> None: """ - Validate an instance against a given schema using the specified validator class. + Validate an instance against a given schema using the specified + validator class. + + Unlike direct ``Validator(schema).validate(instance)`` usage, this helper + checks schema validity first. + Invalid schemas therefore raise ``SchemaError`` before any instance + validation occurs. """ schema_dict = cast(dict[str, Any], schema) diff --git a/tests/integration/test_validators.py b/tests/integration/test_validators.py index d9e928b..461e881 100644 --- a/tests/integration/test_validators.py +++ b/tests/integration/test_validators.py @@ -1,3 +1,4 @@ +import re import warnings from base64 import b64encode from typing import Any @@ -30,6 +31,7 @@ from openapi_schema_validator import oas30_strict_format_checker from openapi_schema_validator import oas31_format_checker from openapi_schema_validator import oas32_format_checker +from openapi_schema_validator import validate from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_METASCHEMA from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID @@ -124,6 +126,21 @@ def test_string_invalid(self, validator_class, value): with pytest.raises(ValidationError): validator.validate(value) + def test_invalid_pattern_raises_regex_error(self, validator_class): + schema = {"type": "string", "pattern": "["} + validator = validator_class(schema) + + with pytest.raises(re.error): + validator.validate("foo") + + def test_invalid_pattern_rejected_by_validate_helper( + self, validator_class + ): + schema = {"type": "string", "pattern": "["} + + with pytest.raises(SchemaError, match="is not a 'regex'"): + validate("foo", schema, cls=validator_class) + def test_referencing(self, validator_class): name_schema = Resource.from_contents( {