diff --git a/conservancy_beancount/pdfforms/fields.py b/conservancy_beancount/pdfforms/fields.py index 8a49567a6492c5078066ef4d840a3a217f81673c..23ebd6eff7fc997433e6c944ea4152a29801107f 100644 --- a/conservancy_beancount/pdfforms/fields.py +++ b/conservancy_beancount/pdfforms/fields.py @@ -8,6 +8,10 @@ import enum import functools +from decimal import Decimal + +import babel.numbers # type:ignore[import] + from pdfminer.pdftypes import resolve1 # type:ignore[import] from pdfminer import psparser # type:ignore[import] from . import utils as pdfutils @@ -22,6 +26,7 @@ from typing import ( Sequence, Tuple, Union, + cast, ) FieldSource = MutableMapping[str, Any] @@ -238,7 +243,9 @@ class TextField(FormField): def value(self) -> Optional[str]: return self._decode(super().value()) - def set_value(self, value: Optional[str]) -> None: + def set_value(self, value: Union[str, Decimal, float, int, None]) -> None: + if isinstance(value, (Decimal, float, int)): + value = cast(str, babel.numbers.format_decimal(value)) super().set_value(None if value is None else pdfutils.encode_text(value)) def fill_value(self) -> Optional[str]: diff --git a/tests/test_pdfforms_fields.py b/tests/test_pdfforms_fields.py index 13521259c3774bf39c3181280ca710dde873b75b..8f54120d94b07eaa17621eb04227bc375fd6cf37 100644 --- a/tests/test_pdfforms_fields.py +++ b/tests/test_pdfforms_fields.py @@ -10,6 +10,8 @@ import itertools import pytest +from decimal import Decimal + from pdfminer.psparser import PSLiteral from conservancy_beancount.pdfforms import fields as fieldsmod @@ -249,6 +251,24 @@ def test_text_set_value(text, bprefix): actual = fieldsmod.FormField.value(field) assert actual == bprefix + text.encode('utf-16be' if bprefix else 'ascii') +@pytest.mark.parametrize('expected', [ + '0', + '32', + '32.45', + '32,768', + '32,768.95', +]) +def test_text_set_value_numeric(expected): + num_s = expected.replace(',', '') + field = fieldsmod.TextField({}) + num_types = [Decimal, float] + if '.' not in expected: + num_types.append(int) + for num_type in num_types: + field.set_value(num_type(num_s)) + assert field.value() == expected + field.set_value(None) + def test_text_set_value_none(): source = field_source('t', b'set None test', 'Tx') field = fieldsmod.TextField(source)