Skip to content

Commit

Permalink
fix(validation-utility): validation for model value dictionary (#65)
Browse files Browse the repository at this point in the history
This commit fixes the validation of a dictionary that contains a simple model value as the deserialized model is treated as a dictionary. This dictionary was conflicting with the dictionary of some primitive or non-primitive types.
  • Loading branch information
sufyankhanrao authored Jun 4, 2024
1 parent ee63212 commit efd954e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 39 deletions.
11 changes: 7 additions & 4 deletions apimatic_core/utilities/api_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,17 @@ def is_file_wrapper_instance(param):
return isinstance(param, FileWrapper)

@staticmethod
def is_valid_type(value, type_callable, is_value_nullable=False):
def is_valid_type(value, type_callable, is_value_nullable=False, is_model_dict=False,
is_inner_model_dict=False):
if value is None and is_value_nullable:
return True

if isinstance(value, list):
return all(ApiHelper.is_valid_type(item, type_callable) for item in value)
elif isinstance(value, dict):
return all(ApiHelper.is_valid_type(item, type_callable) for item in value.values())
return all(ApiHelper.is_valid_type(item, type_callable, is_value_nullable, is_model_dict,
is_inner_model_dict) for item in value)
elif isinstance(value, dict) and (not is_model_dict or is_inner_model_dict):
return all(ApiHelper.is_valid_type(item, type_callable, is_value_nullable, is_model_dict)
for item in value.values())

return value is not None and type_callable(value)

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name='apimatic-core',
version='0.2.13',
version='0.2.14',
description='A library that contains core logic and utilities for '
'consuming REST APIs using Python SDKs generated by APIMatic.',
long_description=long_description,
Expand Down
95 changes: 61 additions & 34 deletions tests/apimatic_core/utility_tests/test_api_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import jsonpickle
import pytest
from tests.apimatic_core.mocks.models.atom import Atom

from apimatic_core.types.union_types.leaf_type import LeafType
from apimatic_core.types.union_types.one_of import OneOf
from apimatic_core.types.union_types.union_type_context import UnionTypeContext
Expand Down Expand Up @@ -850,40 +852,65 @@ def test_resolve_template_placeholders_using_json_pointer(self, input_placeholde
input_template)
assert actual_message == expected_message

@pytest.mark.parametrize('input_value, input_callable, is_value_nullable, expected_value', [
(100, lambda value: isinstance(value, int), False, True),
('100', lambda value: isinstance(value, str), False, True),
("Sunday", lambda value: Days.validate(value), False, True),
(100.5, lambda value: isinstance(value, str), False, False),
("Invalid", lambda value: Days.validate(value), False, False),
(None, lambda value: isinstance(value, str), False, False),
(None, lambda value: isinstance(value, str), True, True),
(None, None, False, False),
(None, None, True, True),
([100, 200], lambda value: isinstance(value, int), False, True),
(['100', '200'], lambda value: isinstance(value, str), False, True),
(["Sunday", "Monday"], lambda value: Days.validate(value), False, True),
([100.5, 200], lambda value: isinstance(value, str), False, False),
(["Invalid1", "Invalid2"], lambda value: Days.validate(value), False, False),
([None, None], lambda value: isinstance(value, str), False, False),
([[100, 200], [300, 400]], lambda value: isinstance(value, int), False, True),
([['100', '200'], ['abc', 'def']], lambda value: isinstance(value, str), False, True),
([["Sunday", "Monday"], ["Tuesday", "Friday"]], lambda value: Days.validate(value), False, True),
([[100.5, 200], [400, 500]], lambda value: isinstance(value, str), False, False),
([["Invalid1", "Invalid2"], ["Sunday", "Invalid4"]], lambda value: Days.validate(value), False, False),
([[None, None], [None, None]], lambda value: isinstance(value, str), False, False),
({'key0': 100, 'key2': 200}, lambda value: isinstance(value, int), False, True),
({'key0': 'abc', 'key2': 'def'}, lambda value: isinstance(value, str), False, True),
({'key0': 'Sunday', 'key2': 'Tuesday'}, lambda value: Days.validate(value), False, True),
({'key0': 100.5, 'key2': 200}, lambda value: isinstance(value, str), False, False),
({'key0': "Invalid1", 'key2': "Invalid2"}, lambda value: Days.validate(value), False, False),
({'key0': None, 'key2': None}, lambda value: isinstance(value, str), False, False),
])
def test_is_valid_type(self, input_value, input_callable, is_value_nullable, expected_value):
actual_value = ApiHelper.is_valid_type(input_value, input_callable, is_value_nullable)
@pytest.mark.parametrize(
'input_value, input_callable, is_value_nullable, is_model_dict, is_inner_model_dict, expected_value', [
(100, lambda value: isinstance(value, int), False, False, False, True),
('100', lambda value: isinstance(value, str), False, False, False, True),
("Sunday", lambda value: Days.validate(value), False, False, False, True),
(100.5, lambda value: isinstance(value, str), False, False, False, False),
("Invalid", lambda value: Days.validate(value), False, False, False, False),
(None, lambda value: isinstance(value, str), False, False, False, False),
(None, lambda value: isinstance(value, str), True, False, False, True),
(None, None, False, False, False, False),
(None, None, True, False, False, True),
([100, 200], lambda value: isinstance(value, int), False, False, False, True),
(['100', '200'], lambda value: isinstance(value, str), False, False, False, True),
(["Sunday", "Monday"], lambda value: Days.validate(value), False, False, False, True),
([100.5, 200], lambda value: isinstance(value, str), False, False, False, False),
(["Invalid1", "Invalid2"], lambda value: Days.validate(value), False, False, False, False),
([None, None], lambda value: isinstance(value, str), False, False, False, False),
([[100, 200], [300, 400]], lambda value: isinstance(value, int), False, False, False, True),
([['100', '200'], ['abc', 'def']], lambda value: isinstance(value, str), False, False, False, True),
([["Sunday", "Monday"], ["Tuesday", "Friday"]], lambda value: Days.validate(value), False, False, False,
True),
([[100.5, 200], [400, 500]], lambda value: isinstance(value, str), False, False, False, False),
(
[["Invalid1", "Invalid2"], ["Sunday", "Invalid4"]], lambda value: Days.validate(value), False, False, False,
False),
([[None, None], [None, None]], lambda value: isinstance(value, str), False, False, False, False),
({'key0': 100, 'key2': 200}, lambda value: isinstance(value, int), False, False, False, True),
({'key0': 'abc', 'key2': 'def'}, lambda value: isinstance(value, str), False, False, False, True),
({'key0': 'Sunday', 'key2': 'Tuesday'}, lambda value: Days.validate(value), False, False, False, True),
({'key0': 100.5, 'key2': 200}, lambda value: isinstance(value, str), False, False, False, False),
({'key0': "Invalid1", 'key2': "Invalid2"}, lambda value: Days.validate(value), False, False, False, False),
({'key0': None, 'key2': None}, lambda value: isinstance(value, str), False, False, False, False),
({"AtomNumberOfElectrons": 3}, lambda value: Atom.validate(value), False, True, False, True),
([{"AtomNumberOfElectrons": 3}, {"AtomNumberOfElectrons": 3}],
lambda value: Atom.validate(value), False, True, False, True),
({"item": {"AtomNumberOfElectrons": 3}}, lambda value: Atom.validate(value), False, True, True, True),
([{"item": {"AtomNumberOfElectrons": 3}}, {"item": {"AtomNumberOfElectrons": 3}}],
lambda value: Atom.validate(value), False, True, True, True),
({"item": [{"AtomNumberOfElectrons": 3}, {"AtomNumberOfElectrons": 3}]},
lambda value: Atom.validate(value), False, True, True, True),
({"InvalidAtomNumberOfElectrons": 3}, lambda value: Atom.validate(value), False, True, False, False),
([{"InvalidAtomNumberOfElectrons": 3}, {"InvalidAtomNumberOfElectrons": 3}],
lambda value: Atom.validate(value), False, True, False, False),
({"item": {"InvalidAtomNumberOfElectrons": 3}},
lambda value: Atom.validate(value), False, True, True, False),
([{"item": {"InvalidAtomNumberOfElectrons": 3}}, {"item": {"InvalidAtomNumberOfElectrons": 3}}],
lambda value: Atom.validate(value), False, True, True, False),
({"item": [{"InvalidAtomNumberOfElectrons": 3}, {"AtomNumberOfElectrons": 3}]},
lambda value: Atom.validate(value), False, True, True, False),
])
def test_is_valid_type(self, input_value, input_callable, is_value_nullable, is_model_dict,
is_inner_model_dict, expected_value):
actual_value = ApiHelper.is_valid_type(input_value, input_callable, is_value_nullable, is_model_dict,
is_inner_model_dict)
assert actual_value == expected_value

@pytest.mark.parametrize('input_value, input_union_type, input_should_deserialize, expected_value', [
Expand Down

0 comments on commit efd954e

Please sign in to comment.