Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Adds patternProperties #220

Merged
merged 9 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Nullable|✗|OAS3
|OneOf|✗|OAS3
|Pattern|✓|OAS2,OAS3
|PatternProperties|✗|OAS3
|Properties|✓|OAS2,OAS3
|PropertyNames|✗|OAS3
|Required|✓|OAS2,OAS3
Expand Down
1 change: 1 addition & 0 deletions docs/generators/jaxrs-jersey.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Nullable|✗|OAS3
|OneOf|✗|OAS3
|Pattern|✓|OAS2,OAS3
|PatternProperties|✗|OAS3
|Properties|✓|OAS2,OAS3
|PropertyNames|✗|OAS3
|Required|✓|OAS2,OAS3
Expand Down
1 change: 1 addition & 0 deletions docs/generators/jmeter.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Nullable|✗|OAS3
|OneOf|✗|OAS3
|Pattern|✓|OAS2,OAS3
|PatternProperties|✗|OAS3
|Properties|✓|OAS2,OAS3
|PropertyNames|✗|OAS3
|Required|✓|OAS2,OAS3
Expand Down
1 change: 1 addition & 0 deletions docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Nullable|✗|OAS3
|OneOf|✗|OAS3
|Pattern|✓|OAS2,OAS3
|PatternProperties|✗|OAS3
|Properties|✓|OAS2,OAS3
|PropertyNames|✗|OAS3
|Required|✓|OAS2,OAS3
Expand Down
1 change: 1 addition & 0 deletions docs/generators/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Nullable|✓|OAS3
|OneOf|✓|OAS3
|Pattern|✓|OAS2,OAS3
|PatternProperties|✓|OAS3
|Properties|✓|OAS2,OAS3
|PropertyNames|✓|OAS3
|Required|✓|OAS2,OAS3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,36 @@ def validate_property_names(
return None


def validate_pattern_properties(
arg: typing.Any,
pattern_properties: typing.Mapping[PatternInfo, typing.Type[SchemaValidator]],
cls: typing.Type,
validation_metadata: ValidationMetadata,
) -> typing.Optional[PathToSchemasType]:
if not isinstance(arg, immutabledict):
return None
path_to_schemas: PathToSchemasType = {}
module_namespace = vars(sys.modules[cls.__module__])
for property_name, property_value in arg.items():
path_to_item = validation_metadata.path_to_item + (property_name,)
property_validation_metadata = ValidationMetadata(
path_to_item=path_to_item,
configuration=validation_metadata.configuration,
validated_path_to_schemas=validation_metadata.validated_path_to_schemas
)
for pattern_info, schema in pattern_properties.items():
flags = pattern_info.flags if pattern_info.flags is not None else 0
if not re.search(pattern_info.pattern, property_name, flags=flags):
continue
schema = _get_class(schema, module_namespace)
if validation_metadata.validation_ran_earlier(schema):
add_deeper_validated_schemas(validation_metadata, path_to_schemas)
continue
other_path_to_schemas = schema._validate(property_value, validation_metadata=property_validation_metadata)
update(path_to_schemas, other_path_to_schemas)
return path_to_schemas


validator_type = typing.Callable[[typing.Any, typing.Any, type, ValidationMetadata], typing.Optional[PathToSchemasType]]
json_schema_keyword_to_validator: typing.Mapping[str, validator_type] = {
'types': validate_types,
Expand Down Expand Up @@ -1157,5 +1187,6 @@ def validate_property_names(
'const_value_to_name': validate_const,
'dependent_required': validate_dependent_required,
'dependent_schemas': validate_dependent_schemas,
'property_names': validate_property_names
'property_names': validate_property_names,
'pattern_properties': validate_pattern_properties
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ docs/components/schema/any_type_dependent_required.md
docs/components/schema/any_type_dependent_schemas.md
docs/components/schema/any_type_max_contains_value.md
docs/components/schema/any_type_min_contains_value.md
docs/components/schema/any_type_pattern_properties.md
docs/components/schema/any_type_property_names.md
docs/components/schema/array_contains_value.md
docs/components/schema/array_max_contains_value.md
docs/components/schema/array_min_contains_value.md
docs/components/schema/object_dependent_required.md
docs/components/schema/object_dependent_schemas.md
docs/components/schema/object_pattern_properties.md
docs/components/schema/object_property_names.md
docs/components/schema/string_const_string.md
docs/paths/some_path/get.md
Expand Down Expand Up @@ -43,12 +45,14 @@ src/json_schema_api/components/schema/any_type_dependent_required.py
src/json_schema_api/components/schema/any_type_dependent_schemas.py
src/json_schema_api/components/schema/any_type_max_contains_value.py
src/json_schema_api/components/schema/any_type_min_contains_value.py
src/json_schema_api/components/schema/any_type_pattern_properties.py
src/json_schema_api/components/schema/any_type_property_names.py
src/json_schema_api/components/schema/array_contains_value.py
src/json_schema_api/components/schema/array_max_contains_value.py
src/json_schema_api/components/schema/array_min_contains_value.py
src/json_schema_api/components/schema/object_dependent_required.py
src/json_schema_api/components/schema/object_dependent_schemas.py
src/json_schema_api/components/schema/object_pattern_properties.py
src/json_schema_api/components/schema/object_property_names.py
src/json_schema_api/components/schema/string_const_string.py
src/json_schema_api/components/schemas/__init__.py
Expand Down
2 changes: 2 additions & 0 deletions samples/client/3_1_0_json_schema/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,14 @@ Class | Description
[AnyTypeDependentSchemas](docs/components/schema/any_type_dependent_schemas.md) |
[AnyTypeMaxContainsValue](docs/components/schema/any_type_max_contains_value.md) |
[AnyTypeMinContainsValue](docs/components/schema/any_type_min_contains_value.md) |
[AnyTypePatternProperties](docs/components/schema/any_type_pattern_properties.md) |
[AnyTypePropertyNames](docs/components/schema/any_type_property_names.md) |
[ArrayContainsValue](docs/components/schema/array_contains_value.md) |
[ArrayMaxContainsValue](docs/components/schema/array_max_contains_value.md) |
[ArrayMinContainsValue](docs/components/schema/array_min_contains_value.md) |
[ObjectDependentRequired](docs/components/schema/object_dependent_required.md) |
[ObjectDependentSchemas](docs/components/schema/object_dependent_schemas.md) |
[ObjectPatternProperties](docs/components/schema/object_pattern_properties.md) |
[ObjectPropertyNames](docs/components/schema/object_property_names.md) |
[StringConstString](docs/components/schema/string_const_string.md) |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# AnyTypePatternProperties
json_schema_api.components.schema.any_type_pattern_properties
```
type: schemas.Schema
```

## validate method
Input Type | Return Type | Notes
------------ | ------------- | -------------
dict, schemas.immutabledict, str, datetime.date, datetime.datetime, uuid.UUID, int, float, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader | schemas.immutabledict, str, float, int, bool, None, tuple, bytes, io.FileIO |

[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# ObjectPatternProperties
json_schema_api.components.schema.object_pattern_properties
```
type: schemas.Schema
```

## validate method
Input Type | Return Type | Notes
------------ | ------------- | -------------
dict, schemas.immutabledict | schemas.immutabledict |

[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# coding: utf-8

"""
Example
No description provided (generated by Openapi JSON Schema Generator https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) # noqa: E501
The version of the OpenAPI document: 1.0.0
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
"""

from __future__ import annotations
from json_schema_api.shared_imports.schema_imports import * # pyright: ignore [reportWildcardImportFromLibrary]

S: typing_extensions.TypeAlias = schemas.StrSchema
I: typing_extensions.TypeAlias = schemas.IntSchema


@dataclasses.dataclass(frozen=True)
class AnyTypePatternProperties(
schemas.AnyTypeSchema[schemas.immutabledict[str, schemas.OUTPUT_BASE_TYPES], typing.Tuple[schemas.OUTPUT_BASE_TYPES, ...]],
):
"""NOTE: This class is auto generated by OpenAPI JSON Schema Generator.
Ref: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator

Do not edit the class manually.
"""
# any type
pattern_properties: typing.Mapping[
schemas.PatternInfo,
typing.Type[schemas.Schema]
] = dataclasses.field(
default_factory=lambda: {
schemas.PatternInfo(
pattern=r'^S_' # noqa: E501
): S,
schemas.PatternInfo(
pattern=r'^I_' # noqa: E501
): I,
}
)

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# coding: utf-8

"""
Example
No description provided (generated by Openapi JSON Schema Generator https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) # noqa: E501
The version of the OpenAPI document: 1.0.0
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
"""

from __future__ import annotations
from json_schema_api.shared_imports.schema_imports import * # pyright: ignore [reportWildcardImportFromLibrary]

S: typing_extensions.TypeAlias = schemas.StrSchema
I: typing_extensions.TypeAlias = schemas.IntSchema


@dataclasses.dataclass(frozen=True)
class ObjectPatternProperties(
schemas.Schema[schemas.immutabledict[str, schemas.OUTPUT_BASE_TYPES], tuple]
):
"""NOTE: This class is auto generated by OpenAPI JSON Schema Generator.
Ref: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator

Do not edit the class manually.
"""
types: typing.FrozenSet[typing.Type] = frozenset({schemas.immutabledict})
pattern_properties: typing.Mapping[
schemas.PatternInfo,
typing.Type[schemas.Schema]
] = dataclasses.field(
default_factory=lambda: {
schemas.PatternInfo(
pattern=r'^S_' # noqa: E501
): S,
schemas.PatternInfo(
pattern=r'^I_' # noqa: E501
): I,
}
)

@classmethod
def validate(
cls,
arg: typing.Mapping[str, schemas.INPUT_TYPES_ALL],
configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None
) -> schemas.immutabledict[str, schemas.OUTPUT_BASE_TYPES]:
return super().validate_base(
arg,
configuration=configuration,
)

Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
from json_schema_api.components.schema.any_type_dependent_schemas import AnyTypeDependentSchemas
from json_schema_api.components.schema.any_type_max_contains_value import AnyTypeMaxContainsValue
from json_schema_api.components.schema.any_type_min_contains_value import AnyTypeMinContainsValue
from json_schema_api.components.schema.any_type_pattern_properties import AnyTypePatternProperties
from json_schema_api.components.schema.any_type_property_names import AnyTypePropertyNames
from json_schema_api.components.schema.array_contains_value import ArrayContainsValue
from json_schema_api.components.schema.array_max_contains_value import ArrayMaxContainsValue
from json_schema_api.components.schema.array_min_contains_value import ArrayMinContainsValue
from json_schema_api.components.schema.object_dependent_required import ObjectDependentRequired
from json_schema_api.components.schema.object_dependent_schemas import ObjectDependentSchemas
from json_schema_api.components.schema.object_pattern_properties import ObjectPatternProperties
from json_schema_api.components.schema.object_property_names import ObjectPropertyNames
from json_schema_api.components.schema.string_const_string import StringConstString
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,36 @@ def validate_property_names(
return None


def validate_pattern_properties(
arg: typing.Any,
pattern_properties: typing.Mapping[PatternInfo, typing.Type[SchemaValidator]],
cls: typing.Type,
validation_metadata: ValidationMetadata,
) -> typing.Optional[PathToSchemasType]:
if not isinstance(arg, immutabledict):
return None
path_to_schemas: PathToSchemasType = {}
module_namespace = vars(sys.modules[cls.__module__])
for property_name, property_value in arg.items():
path_to_item = validation_metadata.path_to_item + (property_name,)
property_validation_metadata = ValidationMetadata(
path_to_item=path_to_item,
configuration=validation_metadata.configuration,
validated_path_to_schemas=validation_metadata.validated_path_to_schemas
)
for pattern_info, schema in pattern_properties.items():
flags = pattern_info.flags if pattern_info.flags is not None else 0
if not re.search(pattern_info.pattern, property_name, flags=flags):
continue
schema = _get_class(schema, module_namespace)
if validation_metadata.validation_ran_earlier(schema):
add_deeper_validated_schemas(validation_metadata, path_to_schemas)
continue
other_path_to_schemas = schema._validate(property_value, validation_metadata=property_validation_metadata)
update(path_to_schemas, other_path_to_schemas)
return path_to_schemas


validator_type = typing.Callable[[typing.Any, typing.Any, type, ValidationMetadata], typing.Optional[PathToSchemasType]]
json_schema_keyword_to_validator: typing.Mapping[str, validator_type] = {
'types': validate_types,
Expand Down Expand Up @@ -1157,5 +1187,6 @@ def validate_property_names(
'const_value_to_name': validate_const,
'dependent_required': validate_dependent_required,
'dependent_schemas': validate_dependent_schemas,
'property_names': validate_property_names
'property_names': validate_property_names,
'pattern_properties': validate_pattern_properties
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# coding: utf-8

"""
Example
No description provided (generated by Openapi JSON Schema Generator https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) # noqa: E501
The version of the OpenAPI document: 1.0.0
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
"""

import unittest

import json_schema_api
from json_schema_api.components.schema.any_type_pattern_properties import AnyTypePatternProperties


class TestAnyTypePatternProperties(unittest.TestCase):
"""AnyTypePatternProperties unit test stubs"""

def test_succceds_with_other_type(self):
inst = AnyTypePatternProperties.validate(0)
assert inst == 0

def test_succceds_with_non_matching_key(self):
inst = AnyTypePatternProperties.validate({"keyword": "value"})
assert inst == {"keyword": "value"}

def test_succceds_with_matching_keys(self):
inst = AnyTypePatternProperties.validate({"S_25": "This is a string", "I_0": 42})
assert inst == {"S_25": "This is a string", "I_0": 42}

def test_fails_with_incorrect_value_type_for_s_key(self):
with self.assertRaises(json_schema_api.ApiTypeError):
AnyTypePatternProperties.validate({"S_0": 42})

def test_fails_with_incorrect_value_type_for_i_key(self):
with self.assertRaises(json_schema_api.ApiTypeError):
AnyTypePatternProperties.validate({"I_0": "This is a string"})


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# coding: utf-8

"""
Example
No description provided (generated by Openapi JSON Schema Generator https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) # noqa: E501
The version of the OpenAPI document: 1.0.0
Generated by: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator
"""

import unittest

import json_schema_api
from json_schema_api.components.schema.object_pattern_properties import ObjectPatternProperties


class TestObjectPatternProperties(unittest.TestCase):
"""ObjectPatternProperties unit test stubs"""

def test_succceds_with_non_matching_key(self):
inst = ObjectPatternProperties.validate({"keyword": "value"})
assert inst == {"keyword": "value"}

def test_succceds_with_matching_keys(self):
inst = ObjectPatternProperties.validate({"S_25": "This is a string", "I_0": 42})
assert inst == {"S_25": "This is a string", "I_0": 42}

def test_fails_with_incorrect_value_type_for_s_key(self):
with self.assertRaises(json_schema_api.ApiTypeError):
ObjectPatternProperties.validate({"S_0": 42})

def test_fails_with_incorrect_value_type_for_i_key(self):
with self.assertRaises(json_schema_api.ApiTypeError):
ObjectPatternProperties.validate({"I_0": "This is a string"})


if __name__ == '__main__':
unittest.main()
Loading