Skip to content

Commit

Permalink
Add docs for dynamodb decimal changes
Browse files Browse the repository at this point in the history
* Added docstrings
* Updated tutorial with section on using decimals
* Added boto.dynamodb.types to the list of modules
  for which to generate API docs.
  • Loading branch information
jamesls committed Dec 21, 2012
1 parent 6f9ff24 commit 7972dda
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 1 deletion.
9 changes: 9 additions & 0 deletions boto/dynamodb/layer2.py
Expand Up @@ -107,6 +107,15 @@ def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
self.dynamizer = dynamizer()

def use_decimals(self):
"""
Use the ``decimal.Decimal`` type for encoding/decoding numeric types.
By default, ints/floats are used to represent numeric types
('N', 'NS') received from DynamoDB. Using the ``Decimal``
type is recommended to prevent loss of precision.
"""
# Eventually this should be made the default dynamizer.
self.dynamizer = Dynamizer()

def dynamize_attribute_updates(self, pending_updates):
Expand Down
52 changes: 52 additions & 0 deletions boto/dynamodb/types.py
Expand Up @@ -184,10 +184,47 @@ def item_object_hook(dct):


class Dynamizer(object):
"""Control serialization/deserialization of types.
This class controls the encoding of python types to the
format that is expected by the DynamoDB API, as well as
taking DynamoDB types and constructing the appropriate
python types.
If you want to customize this process, you can subclass
this class and override the encoding/decoding of
specific types. For example::
'foo' (Python type)
|
v
encode('foo')
|
v
_encode_s('foo')
|
v
{'S': 'foo'} (Encoding sent to/received from DynamoDB)
|
V
decode({'S': 'foo'})
|
v
_decode_s({'S': 'foo'})
|
v
'foo' (Python type)
"""
def _get_dynamodb_type(self, attr):
return get_dynamodb_type(attr)

def encode(self, attr):
"""
Encodes a python type to the format expected
by DynamoDB.
"""
dynamodb_type = self._get_dynamodb_type(attr)
try:
encoder = getattr(self, '_encode_%s' % dynamodb_type.lower())
Expand Down Expand Up @@ -228,6 +265,11 @@ def _encode_bs(self, attr):
return [self._encode_b(n) for n in attr]

def decode(self, attr):
"""
Takes the format returned by DynamoDB and constructs
the appropriate python type.
"""
if len(attr) > 1 or not attr:
return attr
dynamodb_type = attr.keys()[0]
Expand Down Expand Up @@ -257,6 +299,16 @@ def _decode_bs(self, attr):


class LossyFloatDynamizer(Dynamizer):
"""Use float/int instead of Decimal for numeric types.
This class is provided for backwards compatibility. Instead of
using Decimals for the 'N', 'NS' types it uses ints/floats.
This class is deprecated and its usage is not encouraged,
as doing so may result in loss of precision. Use the
`Dynamizer` class instead.
"""
def _encode_n(self, attr):
return serialize_num(attr)

Expand Down
30 changes: 30 additions & 0 deletions docs/source/dynamodb_tut.rst
Expand Up @@ -205,6 +205,36 @@ To update an item's attributes, simply retrieve it, modify the value, then
>>> item['SentBy'] = 'User B'
>>> item.put()

Working with Decimals
---------------------

To avoid the loss of precision, you can stipulate that the
``decimal.Decimal`` type be used for numeric values::

>>> import decimal
>>> conn.use_decimals()
>>> table = conn.get_table('messages')
>>> item = table.new_item(
hash_key='LOLCat Forum',
range_key='Check this out!'
)
>>> item['decimal_type'] = decimal.Decimal('1.12345678912345')
>>> item.put()
>>> print table.get_item('LOLCat Forum', 'Check this out!')
{u'forum_name': 'LOLCat Forum', u'decimal_type': Decimal('1.12345678912345'),
u'subject': 'Check this out!'}

You can enable the usage of ``decimal.Decimal`` by using either the ``use_decimals``
method, or by passing in the
:py:class:`Dynamizer <boto.dynamodb.types.Dynamizer>` class for
the ``dynamizer`` param::

>>> from boto.dynamodb.types import Dynamizer
>>> conn = boto.connect_dynamodb(dynamizer=Dynamizer)

This mechanism can also be used if you want to customize the encoding/decoding
process of DynamoDB types.

Deleting Items
--------------

Expand Down
7 changes: 6 additions & 1 deletion docs/source/ref/dynamodb.rst
Expand Up @@ -8,7 +8,7 @@ boto.dynamodb
-------------

.. automodule:: boto.dynamodb
:members:
:members:
:undoc-members:

boto.dynamodb.layer1
Expand Down Expand Up @@ -53,4 +53,9 @@ boto.dynamodb.batch
:members:
:undoc-members:

boto.dynamodb.types
-------------------

.. automodule:: boto.dynamodb.types
:members:
:undoc-members:

0 comments on commit 7972dda

Please sign in to comment.