mirror of
https://github.com/sprockets/sprockets.clients.dynamodb.git
synced 2024-11-23 11:19:54 +00:00
Marshalling and Unmarshalling Changes
- Remove the maybe_convert strings to UUIDs - Fix the binary data behavior
This commit is contained in:
parent
fc23a521b5
commit
9f4e81b3a8
4 changed files with 26 additions and 34 deletions
|
@ -4,7 +4,7 @@ except ImportError as error:
|
||||||
def DynamoDB(*args, **kwargs):
|
def DynamoDB(*args, **kwargs):
|
||||||
raise error
|
raise error
|
||||||
|
|
||||||
version_info = (0, 2, 3)
|
version_info = (0, 3, 0)
|
||||||
__version__ = '.'.join(str(v) for v in version_info)
|
__version__ = '.'.join(str(v) for v in version_info)
|
||||||
|
|
||||||
# Response constants
|
# Response constants
|
||||||
|
|
|
@ -14,6 +14,7 @@ the vast majority of types that we use.
|
||||||
APIReference/API_AttributeValue.html
|
APIReference/API_AttributeValue.html
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
import uuid
|
import uuid
|
||||||
import sys
|
import sys
|
||||||
|
@ -58,12 +59,12 @@ def _marshall_value(value):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if PYTHON3 and isinstance(value, bytes):
|
if PYTHON3 and isinstance(value, bytes):
|
||||||
return {'B': value}
|
return {'B': base64.b64encode(value).decode('ascii')}
|
||||||
elif PYTHON3 and isinstance(value, str):
|
elif PYTHON3 and isinstance(value, str):
|
||||||
return {'S': value}
|
return {'S': value}
|
||||||
elif not PYTHON3 and isinstance(value, str):
|
elif not PYTHON3 and isinstance(value, str):
|
||||||
if _is_binary(value):
|
if _is_binary(value):
|
||||||
return {'B': value}
|
return {'B': base64.b64encode(value).decode('ascii')}
|
||||||
return {'S': value}
|
return {'S': value}
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
return {'M': marshall(value)}
|
return {'M': marshall(value)}
|
||||||
|
@ -81,14 +82,14 @@ def _marshall_value(value):
|
||||||
return {'L': [_marshall_value(v) for v in value]}
|
return {'L': [_marshall_value(v) for v in value]}
|
||||||
elif isinstance(value, set):
|
elif isinstance(value, set):
|
||||||
if PYTHON3 and all([isinstance(v, bytes) for v in value]):
|
if PYTHON3 and all([isinstance(v, bytes) for v in value]):
|
||||||
return {'BS': sorted(list(value))}
|
return {'BS': _encode_binary_set(value)}
|
||||||
elif PYTHON3 and all([isinstance(v, str) for v in value]):
|
elif PYTHON3 and all([isinstance(v, str) for v in value]):
|
||||||
return {'SS': sorted(list(value))}
|
return {'SS': sorted(list(value))}
|
||||||
elif all([isinstance(v, (int, float)) for v in value]):
|
elif all([isinstance(v, (int, float)) for v in value]):
|
||||||
return {'NS': sorted([str(v) for v in value])}
|
return {'NS': sorted([str(v) for v in value])}
|
||||||
elif not PYTHON3 and all([isinstance(v, str) for v in value]) and \
|
elif not PYTHON3 and all([isinstance(v, str) for v in value]) and \
|
||||||
all([_is_binary(v) for v in value]):
|
all([_is_binary(v) for v in value]):
|
||||||
return {'BS': sorted(list(value))}
|
return {'BS': _encode_binary_set(value)}
|
||||||
elif not PYTHON3 and all([isinstance(v, str) for v in value]) and \
|
elif not PYTHON3 and all([isinstance(v, str) for v in value]) and \
|
||||||
all([_is_binary(v) is False for v in value]):
|
all([_is_binary(v) is False for v in value]):
|
||||||
return {'SS': sorted(list(value))}
|
return {'SS': sorted(list(value))}
|
||||||
|
@ -99,6 +100,11 @@ def _marshall_value(value):
|
||||||
raise ValueError('Unsupported type: %s' % type(value))
|
raise ValueError('Unsupported type: %s' % type(value))
|
||||||
|
|
||||||
|
|
||||||
|
def _encode_binary_set(value):
|
||||||
|
return sorted([base64.b64encode(v).decode('ascii') for v in value])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def unmarshall(values):
|
def unmarshall(values):
|
||||||
"""
|
"""
|
||||||
Transform a response payload from DynamoDB to a native dict
|
Transform a response payload from DynamoDB to a native dict
|
||||||
|
@ -125,9 +131,10 @@ def _unmarshall_dict(value):
|
||||||
"""
|
"""
|
||||||
key = list(value.keys()).pop()
|
key = list(value.keys()).pop()
|
||||||
if key == 'B':
|
if key == 'B':
|
||||||
return bytes(value[key])
|
return base64.b64decode(value[key].encode('ascii'))
|
||||||
elif key == 'BS':
|
elif key == 'BS':
|
||||||
return set([bytes(v) for v in value[key]])
|
return set([base64.b64decode(v.encode('ascii'))
|
||||||
|
for v in value[key]])
|
||||||
elif key == 'BOOL':
|
elif key == 'BOOL':
|
||||||
return value[key]
|
return value[key]
|
||||||
elif key == 'L':
|
elif key == 'L':
|
||||||
|
@ -141,9 +148,9 @@ def _unmarshall_dict(value):
|
||||||
elif key == 'NS':
|
elif key == 'NS':
|
||||||
return set([_to_number(v) for v in value[key]])
|
return set([_to_number(v) for v in value[key]])
|
||||||
elif key == 'S':
|
elif key == 'S':
|
||||||
return _maybe_convert(value[key])
|
return value[key]
|
||||||
elif key == 'SS':
|
elif key == 'SS':
|
||||||
return set([_maybe_convert(v) for v in value[key]])
|
return set([v for v in value[key]])
|
||||||
raise ValueError('Unsupported value type: %s' % key)
|
raise ValueError('Unsupported value type: %s' % key)
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,24 +165,6 @@ def _to_number(value):
|
||||||
return float(value) if '.' in value else int(value)
|
return float(value) if '.' in value else int(value)
|
||||||
|
|
||||||
|
|
||||||
def _maybe_convert(value):
|
|
||||||
"""
|
|
||||||
Try to convert a string into something useful.
|
|
||||||
|
|
||||||
:param str value: The value to convert
|
|
||||||
:rtype: uuid.UUID|datetime.datetime|str
|
|
||||||
|
|
||||||
Possibly convert the value to a :py:class:`uuid.UUID` or
|
|
||||||
:py:class:`datetime.datetime` if possible, otherwise just return
|
|
||||||
the value.
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return uuid.UUID(value)
|
|
||||||
except ValueError:
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
def _is_binary(value):
|
def _is_binary(value):
|
||||||
"""
|
"""
|
||||||
Check to see if a string contains binary data in Python2
|
Check to see if a string contains binary data in Python2
|
||||||
|
|
|
@ -247,4 +247,4 @@ class PutGetDeleteTests(AsyncTestCase):
|
||||||
|
|
||||||
response = yield self.client.get_item(definition['TableName'],
|
response = yield self.client.get_item(definition['TableName'],
|
||||||
{'id': row_id})
|
{'id': row_id})
|
||||||
self.assertEqual(response['id'], row_id)
|
self.assertEqual(response['id'], str(row_id))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
import unittest
|
import unittest
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -60,8 +61,9 @@ class MarshallTests(unittest.TestCase):
|
||||||
'key7': {'NS': ['1', '2', '3', '4']},
|
'key7': {'NS': ['1', '2', '3', '4']},
|
||||||
'key8': {'S': arrow_value.isoformat()},
|
'key8': {'S': arrow_value.isoformat()},
|
||||||
'key9': {'S': str(uuid_value)},
|
'key9': {'S': str(uuid_value)},
|
||||||
'key10': {'B': b'\0x01\0x02\0x03'},
|
'key10': {'B': base64.b64encode(b'\0x01\0x02\0x03').decode('ascii')},
|
||||||
'key11': {'BS': [b'\0x01\0x02\0x03', b'\0x04\0x05\0x06']},
|
'key11': {'BS': [base64.b64encode(b'\0x01\0x02\0x03').decode('ascii'),
|
||||||
|
base64.b64encode(b'\0x04\0x05\0x06').decode('ascii')]},
|
||||||
'key12': {'S': dt_value.isoformat()}
|
'key12': {'S': dt_value.isoformat()}
|
||||||
}
|
}
|
||||||
self.assertDictEqual(expectation, utils.marshall(value))
|
self.assertDictEqual(expectation, utils.marshall(value))
|
||||||
|
@ -77,7 +79,7 @@ class UnmarshallTests(unittest.TestCase):
|
||||||
maxDiff = None
|
maxDiff = None
|
||||||
|
|
||||||
def test_complex_document(self):
|
def test_complex_document(self):
|
||||||
uuid_value = uuid.uuid4()
|
uuid_value = str(uuid.uuid4())
|
||||||
dt_value = arrow.utcnow()
|
dt_value = arrow.utcnow()
|
||||||
value = {
|
value = {
|
||||||
'key1': {'S': 'str'},
|
'key1': {'S': 'str'},
|
||||||
|
@ -95,9 +97,10 @@ class UnmarshallTests(unittest.TestCase):
|
||||||
'key6': {'SS': ['a', 'b', 'c']},
|
'key6': {'SS': ['a', 'b', 'c']},
|
||||||
'key7': {'NS': ['1', '2', '3', '4']},
|
'key7': {'NS': ['1', '2', '3', '4']},
|
||||||
'key8': {'S': dt_value.isoformat()},
|
'key8': {'S': dt_value.isoformat()},
|
||||||
'key9': {'S': str(uuid_value)},
|
'key9': {'S': uuid_value},
|
||||||
'key10': {'B': b'\0x01\0x02\0x03'},
|
'key10': {'B': base64.b64encode(b'\0x01\0x02\0x03').decode('ascii')},
|
||||||
'key11': {'BS': [b'\0x01\0x02\0x03', b'\0x04\0x05\0x06']}
|
'key11': {'BS': [base64.b64encode(b'\0x01\0x02\0x03').decode('ascii'),
|
||||||
|
base64.b64encode(b'\0x04\0x05\0x06').decode('ascii')]}
|
||||||
}
|
}
|
||||||
expectation = {
|
expectation = {
|
||||||
'key1': 'str',
|
'key1': 'str',
|
||||||
|
|
Loading…
Reference in a new issue