Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Round Decimal to 9 places to support DynamoDB constraints #5092

Merged
merged 9 commits into from
Jan 22, 2020
Merged
1 change: 1 addition & 0 deletions changelog/5092.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DynamoDB tracker store decimal values will now be rounded on save. Previously values exceeding 38 digits caused an unhandled error.
4 changes: 2 additions & 2 deletions rasa/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ def replace_floats_with_decimals(obj: Union[List, Dict]) -> Any:
Args:
obj: A `List` or `Dict` object.

Returns: An object with all matching values and `float` type replaced by `Decimal`.
Returns: An object with all matching values and `float` type replaced by `Decimal` rounded to 9 decimal places.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Returns: An object with all matching values and `float` type replaced by `Decimal` rounded to 9 decimal places.
Returns: An object with all matching values and `float` type replaced by `Decimal` rounded to 9 decimal places.
Suggested change
Returns: An object with all matching values and `float` type replaced by `Decimal` rounded to 9 decimal places.
Returns: An object with all matching values and `float` types replaced by `Decimal`s rounded to 9 decimal places.


"""
if isinstance(obj, list):
Expand All @@ -477,7 +477,7 @@ def replace_floats_with_decimals(obj: Union[List, Dict]) -> Any:
obj[j] = replace_floats_with_decimals(obj[j])
return obj
elif isinstance(obj, float):
return Decimal(obj)
return round(Decimal(obj), 9)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 should even be enough (I just checked how many decimals time.time() returns

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function will also consume confidence scores, hence the slightly higher value:

{'event': 'user', 'timestamp': Decimal('1579507733.1107571125030517578125'), 'text': 'hi', 'parse_data': {'intent': {'name': 'greet', 'confidence': Decimal('0.918040672051180450807805755175650119781494140625')}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make the number of decimals a parameter of the function? 9 could be the default value

else:
return obj

Expand Down
2 changes: 2 additions & 0 deletions tests/core/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def test_float_conversion_to_decimal():
d = {
"int": -1,
"float": 2.1,
"float_round": 0.918040672051180450807805755175650119781494140625,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please to the test with an output of time.time(). I think that's the more realistic setting for the tracker store.

"list": ["one", "two"],
"list_of_floats": [1.0, -2.1, 3.2],
"nested_dict_with_floats": {"list_with_floats": [4.5, -5.6], "float": 6.7},
Expand All @@ -106,6 +107,7 @@ def test_float_conversion_to_decimal():

assert isinstance(d_replaced["int"], int)
assert isinstance(d_replaced["float"], Decimal)
assert d_replaced["float_round"] == Decimal('0.918040672')
for t in d_replaced["list"]:
assert isinstance(t, str)
for f in d_replaced["list_of_floats"]:
Expand Down