File: test_types.py

package info (click to toggle)
python-boto3 1.40.72-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 11,812 kB
  • sloc: python: 14,006; javascript: 192; makefile: 170
file content (208 lines) | stat: -rw-r--r-- 7,236 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the 'License'). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# https://aws.amazon.com/apache2.0/
#
# or in the 'license' file accompanying this file. This file is
# distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
from decimal import Decimal

import pytest

from boto3.dynamodb.types import Binary, TypeDeserializer, TypeSerializer
from tests import unittest


class TestBinary(unittest.TestCase):
    def test_bytes_input(self):
        data = Binary(b'\x01')
        assert b'\x01' == data
        assert b'\x01' == data.value

    def test_non_ascii_bytes_input(self):
        # Binary data that is out of ASCII range
        data = Binary(b'\x88')
        assert b'\x88' == data
        assert b'\x88' == data.value

    def test_bytearray_input(self):
        data = Binary(bytearray([1]))
        assert b'\x01' == data
        assert b'\x01' == data.value

    def test_unicode_throws_error(self):
        with pytest.raises(TypeError):
            Binary('\u00e9')

    def test_integer_throws_error(self):
        with pytest.raises(TypeError):
            Binary(1)

    def test_not_equal(self):
        assert Binary(b'\x01') != b'\x02'

    def test_str(self):
        assert Binary(b'\x01').__str__() == b'\x01'

    def test_bytes(self):
        self.assertEqual(bytes(Binary(b'\x01')), b'\x01')

    def test_repr(self):
        assert 'Binary' in repr(Binary(b'1'))


class TestSerializer(unittest.TestCase):
    def setUp(self):
        self.serializer = TypeSerializer()

    def test_serialize_unsupported_type(self):
        with pytest.raises(TypeError, match=r'Unsupported type'):
            self.serializer.serialize(object())

    def test_serialize_null(self):
        assert self.serializer.serialize(None) == {'NULL': True}

    def test_serialize_boolean(self):
        assert self.serializer.serialize(False) == {'BOOL': False}

    def test_serialize_integer(self):
        assert self.serializer.serialize(1) == {'N': '1'}

    def test_serialize_decimal(self):
        assert self.serializer.serialize(Decimal('1.25')) == {'N': '1.25'}

    def test_serialize_float_error(self):
        error_msg = r'Float types are not supported. Use Decimal types instead'
        with pytest.raises(TypeError, match=error_msg):
            self.serializer.serialize(1.25)

    def test_serialize_NaN_error(self):
        with pytest.raises(TypeError, match=r'Infinity and NaN not supported'):
            self.serializer.serialize(Decimal('NaN'))

    def test_serialize_string(self):
        assert self.serializer.serialize('foo') == {'S': 'foo'}

    def test_serialize_binary(self):
        assert self.serializer.serialize(Binary(b'\x01')) == {'B': b'\x01'}

    def test_serialize_bytearray(self):
        assert self.serializer.serialize(bytearray([1])) == {'B': b'\x01'}

    def test_serialize_bytes(self):
        assert self.serializer.serialize(b'\x01') == {'B': b'\x01'}

    def test_serialize_number_set(self):
        serialized_value = self.serializer.serialize({1, 2, 3})
        assert len(serialized_value) == 1
        assert 'NS' in serialized_value
        self.assertCountEqual(serialized_value['NS'], ['1', '2', '3'])

    def test_serialize_string_set(self):
        serialized_value = self.serializer.serialize({'foo', 'bar'})
        assert len(serialized_value) == 1
        assert 'SS' in serialized_value
        self.assertCountEqual(serialized_value['SS'], ['foo', 'bar'])

    def test_serialize_binary_set(self):
        serialized_value = self.serializer.serialize(
            {Binary(b'\x01'), Binary(b'\x02')}
        )
        assert len(serialized_value) == 1
        assert 'BS' in serialized_value
        self.assertCountEqual(serialized_value['BS'], [b'\x01', b'\x02'])

    def test_serialize_list(self):
        serialized_value = self.serializer.serialize(['foo', 1, [1]])
        assert len(serialized_value) == 1
        assert 'L' in serialized_value
        self.assertCountEqual(
            serialized_value['L'],
            [{'S': 'foo'}, {'N': '1'}, {'L': [{'N': '1'}]}],
        )

    def test_serialize_tuple(self):
        serialized_value = self.serializer.serialize(('foo', 1, (1,)))
        self.assertEqual(len(serialized_value), 1)
        self.assertIn('L', serialized_value)
        self.assertCountEqual(
            serialized_value['L'],
            [{'S': 'foo'}, {'N': '1'}, {'L': [{'N': '1'}]}],
        )

    def test_serialize_map(self):
        serialized_value = self.serializer.serialize(
            {'foo': 'bar', 'baz': {'biz': 1}}
        )
        assert serialized_value == {
            'M': {'foo': {'S': 'bar'}, 'baz': {'M': {'biz': {'N': '1'}}}}
        }


class TestDeserializer(unittest.TestCase):
    def setUp(self):
        self.deserializer = TypeDeserializer()

    def test_deserialize_invalid_type(self):
        with pytest.raises(TypeError, match=r'FOO is not supported'):
            self.deserializer.deserialize({'FOO': 'bar'})

    def test_deserialize_empty_structure(self):
        with pytest.raises(TypeError, match=r'Value must be a nonempty'):
            self.assertEqual(self.deserializer.deserialize({}), {})

    def test_deserialize_null(self):
        assert self.deserializer.deserialize({"NULL": True}) is None

    def test_deserialize_boolean(self):
        assert self.deserializer.deserialize({"BOOL": False}) is False

    def test_deserialize_integer(self):
        assert self.deserializer.deserialize({'N': '1'}) == Decimal('1')

    def test_deserialize_decimal(self):
        assert self.deserializer.deserialize({'N': '1.25'}) == Decimal('1.25')

    def test_deserialize_string(self):
        assert self.deserializer.deserialize({'S': 'foo'}) == 'foo'

    def test_deserialize_binary(self):
        assert self.deserializer.deserialize({'B': b'\x00'}) == Binary(b'\x00')

    def test_deserialize_number_set(self):
        assert self.deserializer.deserialize({'NS': ['1', '1.25']}) == {
            Decimal('1'),
            Decimal('1.25'),
        }

    def test_deserialize_string_set(self):
        assert self.deserializer.deserialize({'SS': ['foo', 'bar']}) == {
            'foo',
            'bar',
        }

    def test_deserialize_binary_set(self):
        assert self.deserializer.deserialize({'BS': [b'\x00', b'\x01']}) == {
            Binary(b'\x00'),
            Binary(b'\x01'),
        }

    def test_deserialize_list(self):
        assert self.deserializer.deserialize(
            {'L': [{'N': '1'}, {'S': 'foo'}, {'L': [{'N': '1.25'}]}]}
        ) == [Decimal('1'), 'foo', [Decimal('1.25')]]

    def test_deserialize_map(self):
        assert self.deserializer.deserialize(
            {
                'M': {
                    'foo': {'S': 'mystring'},
                    'bar': {'M': {'baz': {'N': '1'}}},
                }
            }
        ) == {'foo': 'mystring', 'bar': {'baz': Decimal('1')}}