DynamoDB - error when sending an integer as string (#5108)
This commit is contained in:
parent
4a5c72d5ed
commit
ff767d0743
@ -310,3 +310,9 @@ class StreamAlreadyEnabledException(JsonRESTError):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException"
|
er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException"
|
||||||
super().__init__(er, "Cannot enable stream")
|
super().__init__(er, "Cannot enable stream")
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidConversion(JsonRESTError):
|
||||||
|
def __init__(self):
|
||||||
|
er = "SerializationException"
|
||||||
|
super().__init__(er, "NUMBER_VALUE cannot be converted to String")
|
||||||
|
@ -33,6 +33,7 @@ from moto.dynamodb.exceptions import (
|
|||||||
ResourceInUseException,
|
ResourceInUseException,
|
||||||
StreamAlreadyEnabledException,
|
StreamAlreadyEnabledException,
|
||||||
MockValidationException,
|
MockValidationException,
|
||||||
|
InvalidConversion,
|
||||||
)
|
)
|
||||||
from moto.dynamodb.models.utilities import bytesize
|
from moto.dynamodb.models.utilities import bytesize
|
||||||
from moto.dynamodb.models.dynamo_type import DynamoType
|
from moto.dynamodb.models.dynamo_type import DynamoType
|
||||||
@ -646,6 +647,13 @@ class Table(CloudFormationModel):
|
|||||||
if DynamoType(range_value).size() > RANGE_KEY_MAX_LENGTH:
|
if DynamoType(range_value).size() > RANGE_KEY_MAX_LENGTH:
|
||||||
raise RangeKeyTooLong
|
raise RangeKeyTooLong
|
||||||
|
|
||||||
|
def _validate_item_types(self, item_attrs):
|
||||||
|
for key, value in item_attrs.items():
|
||||||
|
if type(value) == dict:
|
||||||
|
self._validate_item_types(value)
|
||||||
|
elif type(value) == int and key == "N":
|
||||||
|
raise InvalidConversion
|
||||||
|
|
||||||
def put_item(
|
def put_item(
|
||||||
self,
|
self,
|
||||||
item_attrs,
|
item_attrs,
|
||||||
@ -688,6 +696,8 @@ class Table(CloudFormationModel):
|
|||||||
|
|
||||||
self._validate_key_sizes(item_attrs)
|
self._validate_key_sizes(item_attrs)
|
||||||
|
|
||||||
|
self._validate_item_types(item_attrs)
|
||||||
|
|
||||||
if expected is None:
|
if expected is None:
|
||||||
expected = {}
|
expected = {}
|
||||||
lookup_range_value = range_value
|
lookup_range_value = range_value
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import boto3
|
import boto3
|
||||||
|
import botocore
|
||||||
import pytest
|
import pytest
|
||||||
import sure # noqa # pylint: disable=unused-import
|
import sure # noqa # pylint: disable=unused-import
|
||||||
from boto3.dynamodb.conditions import Key
|
from boto3.dynamodb.conditions import Key
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
from moto import mock_dynamodb
|
from unittest import SkipTest
|
||||||
|
from moto import mock_dynamodb, settings
|
||||||
|
|
||||||
table_schema = {
|
table_schema = {
|
||||||
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
|
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
|
||||||
@ -547,3 +549,33 @@ def test_update_item_non_existent_table():
|
|||||||
err = exc.value.response["Error"]
|
err = exc.value.response["Error"]
|
||||||
assert err["Code"].should.equal("ResourceNotFoundException")
|
assert err["Code"].should.equal("ResourceNotFoundException")
|
||||||
assert err["Message"].should.equal("Requested resource not found")
|
assert err["Message"].should.equal("Requested resource not found")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_dynamodb
|
||||||
|
def test_put_item_wrong_datatype():
|
||||||
|
if settings.TEST_SERVER_MODE:
|
||||||
|
raise SkipTest("Unable to mock a session with Config in ServerMode")
|
||||||
|
session = botocore.session.Session()
|
||||||
|
config = botocore.client.Config(parameter_validation=False)
|
||||||
|
client = session.create_client("dynamodb", region_name="us-east-1", config=config)
|
||||||
|
client.create_table(
|
||||||
|
TableName="test2",
|
||||||
|
KeySchema=[{"AttributeName": "mykey", "KeyType": "HASH"}],
|
||||||
|
AttributeDefinitions=[{"AttributeName": "mykey", "AttributeType": "N"}],
|
||||||
|
BillingMode="PAY_PER_REQUEST",
|
||||||
|
)
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
client.put_item(TableName="test2", Item={"mykey": {"N": 123}})
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("SerializationException")
|
||||||
|
err["Message"].should.equal("NUMBER_VALUE cannot be converted to String")
|
||||||
|
|
||||||
|
# Same thing - but with a non-key, and nested
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
client.put_item(
|
||||||
|
TableName="test2",
|
||||||
|
Item={"mykey": {"N": "123"}, "nested": {"M": {"sth": {"N": 5}}}},
|
||||||
|
)
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("SerializationException")
|
||||||
|
err["Message"].should.equal("NUMBER_VALUE cannot be converted to String")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user