-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tree-wide: correctly handle null values
Only a declared property knows if it accepts Null or not. I was playing with nullable Type but than I would have to have also nullable TypeTraits and there result would be a complete mess. Therefore I decided to move the responsibility to serialize/deserialize the declared property. The decision led to a simpler code which is a good sign. I could have used a better exception type but we currently evaluating the best exception strategies, so I used a generic type. Part of the issue #95
- Loading branch information
Showing
5 changed files
with
222 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
"""Tests of OData Model: class VariableDeclaration""" | ||
|
||
import pytest | ||
import datetime | ||
from pyodata.v2.model import EdmStructTypeSerializer, Types, StructType, StructTypeProperty | ||
from pyodata.exceptions import PyODataException | ||
|
||
|
||
@pytest.fixture | ||
def complex_type_property_declarations(): | ||
return { | ||
'TestString': (Types.parse_type_name('Edm.String'), "'FooBar'", "'FooBar'", 'FooBar'), | ||
'TestBoolean': (Types.parse_type_name('Edm.Boolean'), False, 'false', False), | ||
'TestInt64': (Types.parse_type_name('Edm.Int64'), '123L', '123L', 123), | ||
'TestDateTime': (Types.parse_type_name('Edm.DateTime'), "/Date(2147483647000)/", "datetime'2038-01-19T3:14:7'", | ||
datetime.datetime(2038, 1, 19, hour=3, minute=14, second=7, tzinfo=datetime.timezone.utc)) | ||
} | ||
|
||
|
||
def define_complex_type(complex_type_property_declarations, nullable = True): | ||
complex_typ = StructType('TestComplexType', 'Label Complex Type', False) | ||
|
||
for name, prop_decl in complex_type_property_declarations.items(): | ||
prop = StructTypeProperty(name, prop_decl[0], nullable, None, None, None, | ||
None, None, None, None, None, None, None, None, None, None, None, None) | ||
|
||
prop.typ = Types.from_name(prop.type_info.name) | ||
complex_typ._properties[prop.name] = prop | ||
prop.struct_type = complex_typ | ||
|
||
return complex_typ | ||
|
||
|
||
@pytest.fixture | ||
def complex_type_with_nullable_props(complex_type_property_declarations, nullable = True): | ||
return define_complex_type(complex_type_property_declarations, nullable=True) | ||
|
||
|
||
@pytest.fixture | ||
def complex_type_without_nullable_props(complex_type_property_declarations, nullable = True): | ||
return define_complex_type(complex_type_property_declarations, nullable=False) | ||
|
||
|
||
def test_nullable_from_json_null_properties(complex_type_with_nullable_props, complex_type_property_declarations): | ||
entity_json = { prop_name: None for prop_name in complex_type_property_declarations.keys() } | ||
|
||
entity_odata = complex_type_with_nullable_props.traits.from_json(entity_json) | ||
|
||
assert entity_json.keys() == entity_odata.keys() | ||
|
||
for name, value in entity_odata.items(): | ||
assert value is None, f'Property: {name}' | ||
|
||
|
||
def test_non_nullable_from_json_null_properties(complex_type_without_nullable_props, complex_type_property_declarations): | ||
for prop_name in complex_type_property_declarations.keys(): | ||
entity_json = { prop_name : None } | ||
with pytest.raises(PyODataException): | ||
entity_odata = complex_type_without_nullable_props.traits.from_json(entity_json) | ||
|
||
|
||
def test_non_nullable_from_json(complex_type_without_nullable_props, complex_type_property_declarations): | ||
entity_json = { prop_name : prop_decl[1] for prop_name, prop_decl in complex_type_property_declarations.items() } | ||
|
||
entity_odata =complex_type_without_nullable_props.traits.from_json(entity_json) | ||
|
||
assert entity_json.keys() == entity_odata.keys() | ||
|
||
for name, value in entity_odata.items(): | ||
assert value == complex_type_property_declarations[name][3], f'Value of {name}' | ||
|
||
|
||
def test_nullable_from_literal_null_properties(complex_type_with_nullable_props, complex_type_property_declarations): | ||
entity_literal = { prop_name: None for prop_name in complex_type_property_declarations.keys() } | ||
|
||
entity_odata = complex_type_with_nullable_props.traits.from_literal(entity_literal) | ||
|
||
assert entity_literal.keys() == entity_odata.keys() | ||
|
||
for name, value in entity_odata.items(): | ||
assert value is None, f'Property: {name}' | ||
|
||
|
||
def test_non_nullable_from_literal_null_properties(complex_type_without_nullable_props, complex_type_property_declarations): | ||
for prop_name in complex_type_property_declarations.keys(): | ||
entity_literal = { prop_name : None } | ||
with pytest.raises(PyODataException): | ||
entity_odata = complex_type_without_nullable_props.traits.from_literal(entity_literal) | ||
|
||
|
||
def test_non_nullable_from_literal(complex_type_without_nullable_props, complex_type_property_declarations): | ||
entity_literal = { prop_name : prop_decl[2] for prop_name, prop_decl in complex_type_property_declarations.items() } | ||
|
||
entity_odata =complex_type_without_nullable_props.traits.from_literal(entity_literal) | ||
|
||
assert entity_literal.keys() == entity_odata.keys() | ||
|
||
for name, value in entity_odata.items(): | ||
assert value == complex_type_property_declarations[name][3], f'Value of {name}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
"""Tests of OData Model: class VariableDeclaration""" | ||
|
||
import pytest | ||
from pyodata.v2.model import VariableDeclaration, Types | ||
from pyodata.exceptions import PyODataException | ||
|
||
|
||
@pytest.fixture | ||
def variable_of_string_nullable(): | ||
variable = VariableDeclaration('TestVariable', Types.parse_type_name('Edm.String'), True, None, None, None) | ||
variable.typ = Types.from_name(variable.type_info.name) | ||
return variable | ||
|
||
@pytest.fixture | ||
def variable_of_string(): | ||
variable = VariableDeclaration('TestVariable', Types.parse_type_name('Edm.String'), False, None, None, None) | ||
variable.typ = Types.from_name(variable.type_info.name) | ||
return variable | ||
|
||
|
||
def test_variable_of_string_nullable_from_json_none(variable_of_string_nullable): | ||
assert variable_of_string_nullable.from_json(None) is None | ||
|
||
|
||
def test_variable_of_string_nullable_to_json_none(variable_of_string_nullable): | ||
assert variable_of_string_nullable.to_json(None) is None | ||
|
||
|
||
def test_variable_of_string_nullable_from_literal_none(variable_of_string_nullable): | ||
assert variable_of_string_nullable.from_literal(None) is None | ||
|
||
|
||
def test_variable_of_string_nullable_to_literal_none(variable_of_string_nullable): | ||
assert variable_of_string_nullable.to_literal(None) is None | ||
|
||
|
||
def test_variable_of_string_nullable_from_json_non_none(variable_of_string_nullable): | ||
assert variable_of_string_nullable.from_json('FromJSON') == 'FromJSON' | ||
|
||
|
||
def test_variable_of_string_nullable_to_json(variable_of_string_nullable): | ||
assert variable_of_string_nullable.to_json('ToJSON') == 'ToJSON' | ||
|
||
|
||
def test_variable_of_string_nullable_from_literal(variable_of_string_nullable): | ||
assert variable_of_string_nullable.from_literal("'FromLiteral'") == 'FromLiteral' | ||
|
||
|
||
def test_variable_of_string_nullable_to_literal(variable_of_string_nullable): | ||
assert variable_of_string_nullable.to_literal('ToLiteral') == "'ToLiteral'" | ||
|
||
|
||
def test_variable_of_string_from_json_none(variable_of_string): | ||
with pytest.raises(PyODataException) as e_info: | ||
variable_of_string.from_json(None) | ||
assert str(e_info.value).startswith('Cannot convert null JSON to value of VariableDeclaration(TestVariable)') | ||
|
||
|
||
def test_variable_of_string_to_json_none(variable_of_string): | ||
with pytest.raises(PyODataException) as e_info: | ||
variable_of_string.to_json(None) | ||
assert str(e_info.value).startswith('Cannot convert None to JSON of VariableDeclaration(TestVariable)') | ||
|
||
|
||
def test_variable_of_string_from_literal_none(variable_of_string): | ||
with pytest.raises(PyODataException) as e_info: | ||
variable_of_string.from_literal(None) | ||
assert str(e_info.value).startswith('Cannot convert null URL literal to value of VariableDeclaration(TestVariable)') | ||
|
||
|
||
def test_variable_of_string_to_literal_none(variable_of_string): | ||
with pytest.raises(PyODataException) as e_info: | ||
variable_of_string.to_literal(None) | ||
assert str(e_info.value).startswith('Cannot convert None to URL literal of VariableDeclaration(TestVariable)') |