diff --git a/sandbox/grist/imports/fixtures/test_boolean.xlsx b/sandbox/grist/imports/fixtures/test_boolean.xlsx new file mode 100644 index 00000000..c88acd99 Binary files /dev/null and b/sandbox/grist/imports/fixtures/test_boolean.xlsx differ diff --git a/sandbox/grist/imports/import_xls_test.py b/sandbox/grist/imports/import_xls_test.py index 935c7104..1c7134cb 100644 --- a/sandbox/grist/imports/import_xls_test.py +++ b/sandbox/grist/imports/import_xls_test.py @@ -33,9 +33,10 @@ class TestImportXLS(unittest.TestCase): self.assertEqual(parsed_file[1][0]["table_data"][1], ["a", "b", "c", "d", "e", "f", "g", "h"]) - # 0s and 1s become Numeric, not boolean like in the past - self.assertEqual(parsed_file[1][0]["column_metadata"][2], {"type": "Numeric", "id": "boolean"}) - self.assertEqual(parsed_file[1][0]["table_data"][2], [1, 0, 1, 0, 1, 0, 1, 0]) + # check that column type was correctly set to bool and values are properly parsed + self.assertEqual(parsed_file[1][0]["column_metadata"][2], {"type": "Bool", "id": "boolean"}) + self.assertEqual(parsed_file[1][0]["table_data"][2], + [True, False, True, False, True, False, True, False]) # check that column type was correctly set to text and values are properly parsed self.assertEqual(parsed_file[1][0]["column_metadata"][3], @@ -196,12 +197,29 @@ class TestImportXLS(unittest.TestCase): self.assertEqual(tables, [{ 'table_name': 'Sheet1', 'column_metadata': [ - {'id': u'A', 'type': 'Numeric'}, + {'id': u'A', 'type': 'Bool'}, {'id': u'B', 'type': 'Numeric'}, ], 'table_data': [ + [False, False], [0, 0], - [0, 0], + ], + }]) + + def test_boolean(self): + parsed_file = import_xls.parse_file(*_get_fixture('test_boolean.xlsx')) + tables = parsed_file[1] + self.assertEqual(tables, [{ + 'table_name': 'Sheet1', + 'column_metadata': [ + {'id': u'A', 'type': 'Bool'}, + {'id': u'B', 'type': 'Bool'}, + {'id': u'C', 'type': 'Any'}, + ], + 'table_data': [ + [True, False], + [False, False], + ['true', 'False'], ], }]) diff --git a/sandbox/grist/parse_data.py b/sandbox/grist/parse_data.py index 20ed9ea2..f0168623 100644 --- a/sandbox/grist/parse_data.py +++ b/sandbox/grist/parse_data.py @@ -76,6 +76,20 @@ class NumericConverter(BaseConverter): return ("Numeric", values) +class BooleanConverter(BaseConverter): + """Handles the Grist Bool type""" + + @classmethod + def convert(cls, value): + if value is False or value is True: + return value + raise ValueError() + + @classmethod + def get_grist_column(cls, values): + return ("Bool", values) + + class SimpleDateTimeConverter(BaseConverter): """Handles Date and DateTime values which are already instances of datetime.datetime.""" @@ -123,7 +137,7 @@ class ColumnDetector(object): """ # Converters are listed in the order of preference, which is only used if two converters succeed # on the same exact number of values. Text is always a fallback. - converters = [SimpleDateTimeConverter, NumericConverter] + converters = [SimpleDateTimeConverter, BooleanConverter, NumericConverter] # If this many non-junk values or more can't be converted, fall back to text. _text_threshold = 0.10