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

Commit 8ff6b0e

Browse files
authored
Adds min/maxContains (#208)
* Adds python code to handle maxContains and minContains * Adds tests of any type max and min contains * Adds min and max contains tests for arrray payload * Adds max/minContains in generator docs
1 parent 6ab64ee commit 8ff6b0e

File tree

42 files changed

+1060
-88
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1060
-88
lines changed

docs/generators/java.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
324324
|ExclusiveMaximum|✓|OAS2,OAS3
325325
|Format|✓|OAS2,OAS3
326326
|Items|✓|OAS2,OAS3
327+
|MaxContains|✗|OAS3
327328
|MaxItems|✓|OAS2,OAS3
328329
|MaxLength|✓|OAS2,OAS3
329330
|MaxProperties|✓|OAS2,OAS3
330331
|Maximum|✓|OAS2,OAS3
332+
|MinContains|✗|OAS3
331333
|MinItems|✓|OAS2,OAS3
332334
|MinLength|✓|OAS2,OAS3
333335
|MinProperties|✓|OAS2,OAS3

docs/generators/jaxrs-jersey.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
307307
|ExclusiveMaximum|✓|OAS2,OAS3
308308
|Format|✓|OAS2,OAS3
309309
|Items|✓|OAS2,OAS3
310+
|MaxContains|✗|OAS3
310311
|MaxItems|✓|OAS2,OAS3
311312
|MaxLength|✓|OAS2,OAS3
312313
|MaxProperties|✓|OAS2,OAS3
313314
|Maximum|✓|OAS2,OAS3
315+
|MinContains|✗|OAS3
314316
|MinItems|✓|OAS2,OAS3
315317
|MinLength|✓|OAS2,OAS3
316318
|MinProperties|✓|OAS2,OAS3

docs/generators/jmeter.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
166166
|ExclusiveMaximum|✓|OAS2,OAS3
167167
|Format|✓|OAS2,OAS3
168168
|Items|✓|OAS2,OAS3
169+
|MaxContains|✗|OAS3
169170
|MaxItems|✓|OAS2,OAS3
170171
|MaxLength|✓|OAS2,OAS3
171172
|MaxProperties|✓|OAS2,OAS3
172173
|Maximum|✓|OAS2,OAS3
174+
|MinContains|✗|OAS3
173175
|MinItems|✓|OAS2,OAS3
174176
|MinLength|✓|OAS2,OAS3
175177
|MinProperties|✓|OAS2,OAS3

docs/generators/kotlin.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
276276
|ExclusiveMaximum|✓|OAS2,OAS3
277277
|Format|✓|OAS2,OAS3
278278
|Items|✓|OAS2,OAS3
279+
|MaxContains|✗|OAS3
279280
|MaxItems|✓|OAS2,OAS3
280281
|MaxLength|✓|OAS2,OAS3
281282
|MaxProperties|✓|OAS2,OAS3
282283
|Maximum|✓|OAS2,OAS3
284+
|MinContains|✗|OAS3
283285
|MinItems|✓|OAS2,OAS3
284286
|MinLength|✓|OAS2,OAS3
285287
|MinProperties|✓|OAS2,OAS3

docs/generators/python.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
235235
|ExclusiveMaximum|✓|OAS2,OAS3
236236
|Format|✓|OAS2,OAS3
237237
|Items|✓|OAS2,OAS3
238+
|MaxContains|✓|OAS3
238239
|MaxItems|✓|OAS2,OAS3
239240
|MaxLength|✓|OAS2,OAS3
240241
|MaxProperties|✓|OAS2,OAS3
241242
|Maximum|✓|OAS2,OAS3
243+
|MinContains|✓|OAS3
242244
|MinItems|✓|OAS2,OAS3
243245
|MinLength|✓|OAS2,OAS3
244246
|MinProperties|✓|OAS2,OAS3

samples/client/3_0_3_unit_test/python/src/unit_test_api/configurations/schema_configuration.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
'inclusive_maximum': 'maximum',
2727
'inclusive_minimum': 'minimum',
2828
'items': 'items',
29+
'max_contains': 'maxContains',
2930
'max_items': 'maxItems',
3031
'max_length': 'maxLength',
3132
'max_properties': 'maxProperties',
33+
'min_contains': 'minContains',
3234
'min_items': 'minItems',
3335
'min_length': 'minLength',
3436
'min_properties': 'minProperties',

samples/client/3_0_3_unit_test/python/src/unit_test_api/schemas/validation.py

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,22 @@ def _validate(
9696
and k
9797
not in validation_metadata.configuration.disabled_json_schema_python_keywords
9898
}
99+
contains_qty = 0
99100
path_to_schemas: PathToSchemasType = {}
101+
if 'contains' in vars(cls_schema):
102+
contains_qty = _get_contains_qty(
103+
arg,
104+
json_schema_data['contains'],
105+
validation_metadata,
106+
path_to_schemas
107+
)
100108
for keyword, val in json_schema_data.items():
109+
used_val = (val, contains_qty) if keyword in {'contains', 'min_contains', 'max_contains'} else val
101110
validator = json_schema_keyword_to_validator[keyword]
102111

103112
other_path_to_schemas = validator(
104113
arg,
105-
val,
114+
used_val,
106115
cls,
107116
validation_metadata,
108117
)
@@ -956,17 +965,17 @@ def validate_discriminator(
956965
return discriminated_cls._validate(arg, validation_metadata=updated_vm)
957966

958967

959-
def validate_contains(
968+
def _get_contains_qty(
960969
arg: typing.Any,
961970
contains_cls: typing.Type[SchemaValidator],
962-
cls: typing.Type,
963971
validation_metadata: ValidationMetadata,
964-
) -> typing.Optional[PathToSchemasType]:
972+
path_to_schemas: PathToSchemasType
973+
) -> int:
965974
if not isinstance(arg, tuple):
966-
return None
975+
return 0
967976
contains_cls = _get_class(contains_cls)
968-
path_to_schemas: PathToSchemasType = {}
969-
array_contains_item = False
977+
these_path_to_schemas: PathToSchemasType = {}
978+
contains_qty = 0
970979
for i, value in enumerate(arg):
971980
item_validation_metadata = ValidationMetadata(
972981
path_to_item=validation_metadata.path_to_item+(i,),
@@ -975,20 +984,70 @@ def validate_contains(
975984
)
976985
if item_validation_metadata.validation_ran_earlier(contains_cls):
977986
add_deeper_validated_schemas(item_validation_metadata, path_to_schemas)
978-
return path_to_schemas
987+
contains_qty += 1
988+
continue
979989
try:
980990
other_path_to_schemas = contains_cls._validate(
981991
value, validation_metadata=item_validation_metadata)
982-
update(path_to_schemas, other_path_to_schemas)
983-
return path_to_schemas
992+
update(these_path_to_schemas, other_path_to_schemas)
993+
contains_qty += 1
984994
except exceptions.OpenApiException:
985995
pass
986-
if not array_contains_item:
996+
if contains_qty:
997+
update(path_to_schemas, these_path_to_schemas)
998+
return contains_qty
999+
1000+
1001+
def validate_contains(
1002+
arg: typing.Any,
1003+
contains_qty: typing.Tuple[typing.Type[SchemaValidator], int],
1004+
cls: typing.Type,
1005+
validation_metadata: ValidationMetadata,
1006+
) -> typing.Optional[PathToSchemasType]:
1007+
if not isinstance(arg, tuple):
1008+
return None
1009+
if not contains_qty[1]:
9871010
raise exceptions.ApiValueError(
9881011
"Validation failed for contains keyword in class={} at path_to_item={}. No "
9891012
"items validated to the contains schema.".format(cls, validation_metadata.path_to_item)
9901013
)
991-
return path_to_schemas
1014+
return None
1015+
1016+
1017+
def validate_min_contains(
1018+
arg: typing.Any,
1019+
min_contains_and_qty: typing.Tuple[int, int],
1020+
cls: typing.Type,
1021+
validation_metadata: ValidationMetadata,
1022+
) -> typing.Optional[PathToSchemasType]:
1023+
if not isinstance(arg, tuple):
1024+
return None
1025+
min_contains = min_contains_and_qty[0]
1026+
contains_qty = min_contains_and_qty[1]
1027+
if not contains_qty or contains_qty < min_contains:
1028+
raise exceptions.ApiValueError(
1029+
"Validation failed for minContains keyword in class={} at path_to_item={}. No "
1030+
"items validated to the contains schema.".format(cls, validation_metadata.path_to_item)
1031+
)
1032+
return None
1033+
1034+
1035+
def validate_max_contains(
1036+
arg: typing.Any,
1037+
max_contains_and_qty: typing.Tuple[int, int],
1038+
cls: typing.Type,
1039+
validation_metadata: ValidationMetadata,
1040+
) -> typing.Optional[PathToSchemasType]:
1041+
if not isinstance(arg, tuple):
1042+
return None
1043+
max_contains = max_contains_and_qty[0]
1044+
contains_qty = max_contains_and_qty[1]
1045+
if not contains_qty or contains_qty > max_contains:
1046+
raise exceptions.ApiValueError(
1047+
"Validation failed for maxContains keyword in class={} at path_to_item={}. Too "
1048+
"many items validated to the contains schema.".format(cls, validation_metadata.path_to_item)
1049+
)
1050+
return None
9921051

9931052

9941053
validator_type = typing.Callable[[typing.Any, typing.Any, type, ValidationMetadata], typing.Optional[PathToSchemasType]]
@@ -1018,5 +1077,7 @@ def validate_contains(
10181077
'all_of': validate_all_of,
10191078
'not_': validate_not,
10201079
'discriminator': validate_discriminator,
1021-
'contains': validate_contains
1080+
'contains': validate_contains,
1081+
'min_contains': validate_min_contains,
1082+
'max_contains': validate_max_contains
10221083
}

samples/client/3_1_0_json_schema/python/.openapi-generator/FILES

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
README.md
55
docs/apis/tags/default_api.md
66
docs/components/schema/any_type_contains_value.md
7+
docs/components/schema/any_type_max_contains_value.md
8+
docs/components/schema/any_type_min_contains_value.md
79
docs/components/schema/array_contains_value.md
10+
docs/components/schema/array_max_contains_value.md
11+
docs/components/schema/array_min_contains_value.md
812
docs/paths/some_path/get.md
913
docs/paths/some_path/get/responses/response_200/content/application_json/schema.md
1014
docs/servers/server_0.md
@@ -26,7 +30,11 @@ src/json_schema_api/apis/tags/default_api.py
2630
src/json_schema_api/components/__init__.py
2731
src/json_schema_api/components/schema/__init__.py
2832
src/json_schema_api/components/schema/any_type_contains_value.py
33+
src/json_schema_api/components/schema/any_type_max_contains_value.py
34+
src/json_schema_api/components/schema/any_type_min_contains_value.py
2935
src/json_schema_api/components/schema/array_contains_value.py
36+
src/json_schema_api/components/schema/array_max_contains_value.py
37+
src/json_schema_api/components/schema/array_min_contains_value.py
3038
src/json_schema_api/components/schemas/__init__.py
3139
src/json_schema_api/configurations/__init__.py
3240
src/json_schema_api/configurations/api_configuration.py

samples/client/3_1_0_json_schema/python/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@ HTTP request | Method | Description
174174
Class | Description
175175
----- | ------------
176176
[AnyTypeContainsValue](docs/components/schema/any_type_contains_value.md) |
177+
[AnyTypeMaxContainsValue](docs/components/schema/any_type_max_contains_value.md) |
178+
[AnyTypeMinContainsValue](docs/components/schema/any_type_min_contains_value.md) |
177179
[ArrayContainsValue](docs/components/schema/array_contains_value.md) |
180+
[ArrayMaxContainsValue](docs/components/schema/array_max_contains_value.md) |
181+
[ArrayMinContainsValue](docs/components/schema/array_min_contains_value.md) |
178182

179183
## Notes for Large OpenAPI documents
180184
If the OpenAPI document is large, imports in json_schema_api.apis.tags.tag_to_api and json_schema_api.components.schemas may fail with a
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# AnyTypeMaxContainsValue
2+
json_schema_api.components.schema.any_type_max_contains_value
3+
```
4+
type: schemas.Schema
5+
```
6+
7+
## validate method
8+
Input Type | Return Type | Notes
9+
------------ | ------------- | -------------
10+
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 |
11+
12+
[[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md)

0 commit comments

Comments
 (0)