Added fixed decimal type - revisions re: scottbelden
MODIFY
.gitignore
.gitignore
@@ -13,3 +13,4 @@ venv
.tox
.idea
*.pyc
+.cache/

MODIFY
fastavro/reader.py
fastavro/reader.py
@@ -181,47 +181,21 @@ def read_time_micros(data, writer_schema=None, reader_schema=None):
def read_bytes_decimal(data, writer_schema=None, reader_schema=None):
- """
- Decimal is encoded as bytes.
- based on https://github.com/apache/avro/pull/82/
- """
- scale = writer_schema['scale']
- precision = writer_schema['precision']
-
size = len(data)
+ return _read_decimal(data, size, writer_schema)
- datum_byte = str2ints(data)
-
- unscaled_datum = 0
- msb = fstint(data)
- leftmost_bit = (msb >> 7) & 1
- if leftmost_bit == 1:
- modified_first_byte = datum_byte[0] ^ (1 << 7)
- datum_byte = [modified_first_byte] + datum_byte[1:]
- for offset in xrange(size):
- unscaled_datum <<= 8
- unscaled_datum += datum_byte[offset]
- unscaled_datum += pow(-2, (size * 8) - 1)
- else:
- for offset in xrange(size):
- unscaled_datum <<= 8
- unscaled_datum += (datum_byte[offset])
- with localcontext() as ctx:
- ctx.prec = precision
- scaled_datum = Decimal(unscaled_datum).scaleb(-scale)
- return scaled_datum
+def read_fixed_decimal(data, writer_schema=None, reader_schema=None):
+ size = writer_schema['size']
+ return _read_decimal(data, size, writer_schema)
-def read_fixed_decimal(data, writer_schema=None, reader_schema=None):
+def _read_decimal(data, size, writer_schema):
"""
- Decimal is encoded as fixed. Fixed instances are encoded using the
- number of bytes declared in the schema.
based on https://github.com/apache/avro/pull/82/
"""
scale = writer_schema['scale']
precision = writer_schema['precision']
- size = writer_schema['size']
datum_byte = str2ints(data)

MODIFY
fastavro/writer.py
fastavro/writer.py
@@ -105,7 +105,7 @@ def prepare_bytes_decimal(data, schema):
sign, digits, exp = data.as_tuple()
if -exp > scale:
- raise AssertionError(
+ raise ValueError(
'Scale provided in schema does not match the decimal')
delta = exp + scale
if delta > 0:
@@ -150,7 +150,7 @@ def prepare_fixed_decimal(data, schema):
sign, digits, exp = data.as_tuple()
if -exp > scale:
- raise AssertionError(
+ raise ValueError(
'Scale provided in schema does not match the decimal')
delta = exp + scale
if delta > 0:

MODIFY
tests/test_logical_types.py
tests/test_logical_types.py
@@ -115,7 +115,7 @@ def test_null():
# test bytes decimal
-schema_top = {
+schema_bytes_decimal = {
"name": "n",
"namespace": "namespace",
"type": "bytes",
@@ -125,39 +125,31 @@ schema_top = {
}
-def test_top():
- data1 = Decimal("123.456")
- binary = serialize(schema_top, data1)
-
- data2 = deserialize(schema_top, binary)
- assert (data1 == data2)
-
-
def test_bytes_decimal_negative():
data1 = Decimal("-2.90")
- binary = serialize(schema_top, data1)
- data2 = deserialize(schema_top, binary)
+ binary = serialize(schema_bytes_decimal, data1)
+ data2 = deserialize(schema_bytes_decimal, binary)
assert (data1 == data2)
def test_bytes_decimal_zero():
data1 = Decimal("0.0")
- binary = serialize(schema_top, data1)
- data2 = deserialize(schema_top, binary)
+ binary = serialize(schema_bytes_decimal, data1)
+ data2 = deserialize(schema_bytes_decimal, binary)
assert (data1 == data2)
def test_bytes_decimal_positive():
data1 = Decimal("123.456")
- binary = serialize(schema_top, data1)
- data2 = deserialize(schema_top, binary)
+ binary = serialize(schema_bytes_decimal, data1)
+ data2 = deserialize(schema_bytes_decimal, binary)
assert (data1 == data2)
def test_bytes_decimal_scale():
data1 = Decimal("123.456678") # does not fit scale
- with pytest.raises(AssertionError):
- serialize(schema_top, data1)
+ with pytest.raises(ValueError):
+ serialize(schema_bytes_decimal, data1)
schema_bytes_decimal_leftmost = {
@@ -214,7 +206,7 @@ def test_fixed_decimal_positive():
def test_fixed_decimal_scale():
data1 = Decimal("123.456678") # does not fit scale
- with pytest.raises(AssertionError):
+ with pytest.raises(ValueError):
serialize(schema_fixed_decimal, data1)

Added fixed decimal type (#105) - revisions re: scottbelden