From 4023903eac7c1bb76287b20133913a6d786b7c0d Mon Sep 17 00:00:00 2001 From: Elena ``of Valhalla'' Grandi Date: Thu, 23 Dec 2021 17:20:11 +0100 Subject: New property ``precision`` for ``decimal`` fields. --- CHANGELOG.rst | 2 ++ docs/source/user/settings.rst | 11 +++++++++++ lesana/types.py | 9 ++++++++- .../items/5084bc6e94f24dc6976629282ef30419.yaml | 1 + .../items/8e9fa1ed3c1b4a30a6be7a98eda0cfa7.yaml | 1 + .../items/a4265cc5dfa94c3d8030d7df4a0ab747.yaml | 17 +++++++++++++++++ tests/data/complex/settings.yaml | 3 +++ tests/test_collection.py | 19 ++++++++++++------- 8 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/data/complex/items/a4265cc5dfa94c3d8030d7df4a0ab747.yaml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4f51190..48486ff 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -22,6 +22,8 @@ Unreleased * Add support for bash autocompletion via argcomplete, if installed. * Add support for the ``values`` property in the settings, to limit the contents of a field. +* New property ``precision`` for ``decimal`` fields, to force rounding + values to that number of decimal digits. Bugfixes -------- diff --git a/docs/source/user/settings.rst b/docs/source/user/settings.rst index 565ae73..2d3a3fa 100644 --- a/docs/source/user/settings.rst +++ b/docs/source/user/settings.rst @@ -86,6 +86,17 @@ Some field types may add other custom properties. the amount by which an ``auto: increment`` field is incremented (negative values are of course allowed). Default is 1. +``decimal`` properties +---------------------- + +``precision``: + if this property is set, every value in this field will get rounded + to the given number of decimals. + + With this property it is possible to store decimal values as YAML + floats instead of strings. + + ``date`` and ``datetime`` properties ------------------------------------ diff --git a/lesana/types.py b/lesana/types.py index 77f790d..349208f 100644 --- a/lesana/types.py +++ b/lesana/types.py @@ -204,6 +204,9 @@ class LesanaDecimal(LesanaType): Because of a limitation of the yaml format, these should be stored quoted as a string, to avoid being loaded back as floats. + + Alternatively, the property ``precision`` can be used to force all + values to be rounded to that number of decimals. """ name = "decimal" @@ -211,11 +214,15 @@ class LesanaDecimal(LesanaType): if not data: return data try: - return self.allowed_value(decimal.Decimal(data)) + value = decimal.Decimal(data) except decimal.InvalidOperation: raise LesanaValueError( "Invalid value for decimal field: {}".format(data) ) + precision = self.field.get('precision') + if precision: + value = round(value, precision) + return self.allowed_value(value) def empty(self): return decimal.Decimal(0) diff --git a/tests/data/complex/items/5084bc6e94f24dc6976629282ef30419.yaml b/tests/data/complex/items/5084bc6e94f24dc6976629282ef30419.yaml index c0d6e90..df239bb 100644 --- a/tests/data/complex/items/5084bc6e94f24dc6976629282ef30419.yaml +++ b/tests/data/complex/items/5084bc6e94f24dc6976629282ef30419.yaml @@ -18,4 +18,5 @@ updated: epoch: version: 0 category: first +price: '3.50' # and a comment at the end diff --git a/tests/data/complex/items/8e9fa1ed3c1b4a30a6be7a98eda0cfa7.yaml b/tests/data/complex/items/8e9fa1ed3c1b4a30a6be7a98eda0cfa7.yaml index 0580675..28dc551 100644 --- a/tests/data/complex/items/8e9fa1ed3c1b4a30a6be7a98eda0cfa7.yaml +++ b/tests/data/complex/items/8e9fa1ed3c1b4a30a6be7a98eda0cfa7.yaml @@ -16,3 +16,4 @@ updated: epoch: version: 2 category: first +price: '1.00' diff --git a/tests/data/complex/items/a4265cc5dfa94c3d8030d7df4a0ab747.yaml b/tests/data/complex/items/a4265cc5dfa94c3d8030d7df4a0ab747.yaml new file mode 100644 index 0000000..0c040b3 --- /dev/null +++ b/tests/data/complex/items/a4265cc5dfa94c3d8030d7df4a0ab747.yaml @@ -0,0 +1,17 @@ +name: 'Floaty price' +description: | + An entry with the price stored as a float. +position: '' +something: +tags: [] +keywords: [] +exists: +with_default: 'default value' +amount: 0 +order: '' +created: 2021-12-23 15:32:22.100470+00:00 +updated: 2021-12-23 15:32:22.100486+00:00 +epoch: +version: 0 +category: '' +price: 1.90 diff --git a/tests/data/complex/settings.yaml b/tests/data/complex/settings.yaml index b85e2a2..f4ad574 100644 --- a/tests/data/complex/settings.yaml +++ b/tests/data/complex/settings.yaml @@ -60,3 +60,6 @@ fields: - second - third index: field + - name: price + type: decimal + precision: 2 diff --git a/tests/test_collection.py b/tests/test_collection.py index 659671d..de349ed 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -381,13 +381,13 @@ class testComplexCollection(unittest.TestCase): self.collection.settings['name'], "Fully featured lesana collection", ) - self.assertEqual(len(self.collection.settings['fields']), 15) + self.assertEqual(len(self.collection.settings['fields']), 16) self.assertIsNotNone(self.collection.stemmer) self.assertEqual(len(self.collection.indexed_fields), 9) def test_index(self): indexed = self.collection.update_cache() - self.assertEqual(indexed, 9) + self.assertEqual(indexed, 10) def test_indexing_list(self): self.collection.update_cache(['73097121f1874a6ea2f927db7dc4f11e.yaml']) @@ -504,13 +504,13 @@ class testComplexCollection(unittest.TestCase): self.collection.start_search('*') res = self.collection.get_search_results() matches = list(res) - self.assertEqual(len(matches), 9) + self.assertEqual(len(matches), 10) for i in range(5): self.assertEqual(matches[i].data['order'], None) - self.assertEqual(matches[5].data['order'], 'alpha') - self.assertEqual(matches[6].data['order'], 'charlie') - self.assertEqual(matches[7].data['order'], 'delta') - self.assertEqual(matches[8].data['order'], 'zucchini') + self.assertEqual(matches[6].data['order'], 'alpha') + self.assertEqual(matches[7].data['order'], 'charlie') + self.assertEqual(matches[8].data['order'], 'delta') + self.assertEqual(matches[9].data['order'], 'zucchini') def test_update_entry(self): eid = '5084bc6e94f24dc6976629282ef30419' @@ -545,6 +545,11 @@ class testComplexCollection(unittest.TestCase): {'value': b'there', 'frequency': 1}, ]) + def test_decimal_as_float(self): + eid = 'a4265cc5dfa94c3d8030d7df4a0ab747' + entry = self.collection.entry_from_eid(eid) + self.assertEqual(entry.data['price'], "1.90") + class testCollectionWithErrors(unittest.TestCase): def setUp(self): -- cgit v1.2.3