The gist of this change is to refactor the
serialization/deserialization of python types to the format
that the dynamodb expects into a single "Dynamizer" interface.
This interface is then plumbed into Layer2 and can be passed in
via the __init__. This also allows users to entirely override
this process if they need.
I implemented two types of Dynamizers:
* Dynamizer - Uses Decimals to handle numeric types.
* LossyFloatDynamizer - Uses int/float to handle numeric types.
I made the default dynamizer the LossyFloatDynamizer which will
maintain backwards compatibility (all of the dynamodb tests pass).
If a user wants to use decimals, they can either pass in the
dynamodb = boto.connect_dynamodb(dynamizer=Dynamizer)
or use the `use_decimals` convenience method::
dynamodb = boto.connect_dynamodb()
If a user wants to customize this process, they can subclass
Dynamizer and either override `encode` or `decode`, or they
can override a specific conversion. For example:
def decode_s(self, attr):
dynamodb = boto.connect_dynamodb(dynamizer=UnicodeDynamizer)
I've added unittests/integration tests for the new functionality.
* Don't catch Exception, catch more specific exceptions
when converting to Decimal.
* Mark the encode_X/decode_X methods as internal (client should
use encode/decode which will delegate to the proper