diff --git a/packages/aws-durable-execution-sdk-python-telemetry-exporter/README.md b/packages/aws-durable-execution-sdk-python-telemetry-exporter/README.md index 056708be9..f7a108a95 100644 --- a/packages/aws-durable-execution-sdk-python-telemetry-exporter/README.md +++ b/packages/aws-durable-execution-sdk-python-telemetry-exporter/README.md @@ -331,8 +331,8 @@ and converted to plain JSON: `2**53 - 1`. Otherwise a float when the float round-trips exactly and is within DynamoDB's number range (magnitude 1E-130 to 9.99...E+125). Otherwise `str(value)`, for example `"9007199254740993"`, `"12345678901234567.89"` or `"1E+299"`. NaN and Infinity become `null`. - Negative zero (`Decimal("-0")`, `Decimal("-0.0")`) is integral, so it becomes - `0` and loses its sign. + Every zero, of any sign or exponent (`Decimal("-0")`, `Decimal("-0E+20")`), + becomes `0` and loses its sign. - `datetime` and `date`: `isoformat()`. `UUID`: string. `bytes`: base64. `tuple`: list. `BatchResult`: `to_dict()`. diff --git a/packages/aws-durable-execution-sdk-python-telemetry-exporter/src/aws_durable_execution_sdk_python_telemetry_exporter/plugin.py b/packages/aws-durable-execution-sdk-python-telemetry-exporter/src/aws_durable_execution_sdk_python_telemetry_exporter/plugin.py index 7313ea68c..24eadc26d 100644 --- a/packages/aws-durable-execution-sdk-python-telemetry-exporter/src/aws_durable_execution_sdk_python_telemetry_exporter/plugin.py +++ b/packages/aws-durable-execution-sdk-python-telemetry-exporter/src/aws_durable_execution_sdk_python_telemetry_exporter/plugin.py @@ -276,7 +276,7 @@ def _to_json_compatible(value: Any) -> Any: ``Decimal``: an int when integral and ``abs(n) <= 2**53 - 1``, else a float when it round-trips exactly and is within DynamoDB's number range (magnitude 1E-130 to 9.99...E+125), else ``str(value)``; NaN and Infinity - become ``None``. Negative zero becomes ``0``. ``datetime`` / ``date`` -> ``isoformat()``, ``UUID`` -> string, + become ``None``. Every zero, of any sign or exponent, becomes ``0``. ``datetime`` / ``date`` -> ``isoformat()``, ``UUID`` -> string, ``bytes`` -> base64, ``tuple`` -> list, ``BatchResult`` -> ``to_dict()``. Non-finite floats become ``None``. """ @@ -315,6 +315,10 @@ def _scalar_to_json_compatible(value: Any) -> Any: if isinstance(value, decimal.Decimal): if not value.is_finite(): return None + # A zero of any sign or exponent ("-0E+20", "0E+16") is integer 0. + # Its adjusted() can be large, so the integer check below would miss it. + if value.is_zero(): + return 0 # adjusted() is checked first so Decimal("1E+1000000") never builds a # million-digit int. if ( @@ -324,9 +328,7 @@ def _scalar_to_json_compatible(value: Any) -> Any: as_int = int(value) if abs(as_int) <= _MAX_SAFE_INTEGER: return as_int - if value and not ( - _MIN_NUMBER_ADJUSTED <= value.adjusted() <= _MAX_NUMBER_ADJUSTED - ): + if not (_MIN_NUMBER_ADJUSTED <= value.adjusted() <= _MAX_NUMBER_ADJUSTED): return str(value) as_float = float(value) written = decimal.Decimal(repr(as_float)) diff --git a/packages/aws-durable-execution-sdk-python-telemetry-exporter/tests/test_error_and_result_format.py b/packages/aws-durable-execution-sdk-python-telemetry-exporter/tests/test_error_and_result_format.py index f2b7d4fee..b22b8aef6 100644 --- a/packages/aws-durable-execution-sdk-python-telemetry-exporter/tests/test_error_and_result_format.py +++ b/packages/aws-durable-execution-sdk-python-telemetry-exporter/tests/test_error_and_result_format.py @@ -243,6 +243,9 @@ def test_batch_result_becomes_to_dict(): ("12", 12), ("-0", 0), ("-0.0", 0), + ("-0E+20", 0), + ("0E+16", 0), + ("0E-200", 0), ("1.10", 1.1), ("0.1", 0.1), ("9007199254740991", 9007199254740991),