From 3205584df9a31a86063a5ef0d2c6c72944fccf5c Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 14:09:58 +0100 Subject: [PATCH 01/12] Extract fixture for more reusability --- tests/conftest.py | 13 +++++++++++++ tests/test_utilities.py | 4 +--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..e641348 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,13 @@ +import pytest +from openpyxl.workbook import Workbook +from openpyxl.worksheet.worksheet import Worksheet + + +@pytest.fixture +def workbook() -> Workbook: + return Workbook() + + +@pytest.fixture +def worksheet(workbook: Workbook) -> Worksheet: + return Worksheet(workbook) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 01a2abc..6cc2f94 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -5,7 +5,6 @@ from openpyxl.cell import Cell from openpyxl.styles import Font, PatternFill, Alignment, Border, Color, Side -from openpyxl.workbook import Workbook from openpyxl.worksheet.worksheet import Worksheet from drf_excel.utilities import ( @@ -166,8 +165,7 @@ def test_sanitize_value(value, expected_output): class TestSetCellStyle: @pytest.fixture - def cell(self): - worksheet = Worksheet(Workbook()) + def cell(self, worksheet: Worksheet): return Cell(worksheet) def test_no_style(self, cell): From b955ce9232f7ebf7aaf56046dd4c71cea0684d41 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 14:10:19 +0100 Subject: [PATCH 02/12] Add TestXLSXField --- tests/test_fields.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/test_fields.py diff --git a/tests/test_fields.py b/tests/test_fields.py new file mode 100644 index 0000000..a0f17e0 --- /dev/null +++ b/tests/test_fields.py @@ -0,0 +1,26 @@ +import pytest +from openpyxl.cell import Cell +from openpyxl.worksheet.worksheet import Worksheet +from rest_framework.fields import CharField + +from drf_excel.fields import XLSXField +from drf_excel.utilities import XLSXStyle + + +@pytest.fixture +def style(): + return XLSXStyle() + + +class TestXLSXField: + def test_init(self, style: XLSXStyle): + f = XLSXField("foo", "bar", CharField(), style, None, style) + assert f.key == "foo" + assert f.original_value == "bar" + assert f.value == "bar" + + def test_cell(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXField("foo", "bar", CharField(), style, None, style) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "bar" From 07359abdaa082c6f6b863926ece985b062ca53bf Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 14:27:43 +0100 Subject: [PATCH 03/12] Add TestXLSXNumberField --- tests/test_fields.py | 124 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index a0f17e0..d79e93c 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,9 +1,11 @@ +from decimal import Decimal + import pytest from openpyxl.cell import Cell from openpyxl.worksheet.worksheet import Worksheet -from rest_framework.fields import CharField +from rest_framework.fields import CharField, IntegerField, FloatField, DecimalField -from drf_excel.fields import XLSXField +from drf_excel.fields import XLSXField, XLSXNumberField from drf_excel.utilities import XLSXStyle @@ -24,3 +26,121 @@ def test_cell(self, style: XLSXStyle, worksheet: Worksheet): cell = f.cell(worksheet, 1, 1) assert isinstance(cell, Cell) assert cell.value == "bar" + + +class TestXLSXNumberField: + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Conversion worked + (42, 42), + ("42", 42), + (42.1, 42), + (True, 1), + (False, 0), + # Conversion fails + ("42.0", "42.0"), + ("foo", "foo"), + (None, None), + ], + ) + def test_init_integer_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXNumberField( + key="age", + value=original_value, + field=IntegerField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.key == "age" + assert f.original_value == original_value + assert f.value == cleaned_value + + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Conversion worked + (49, 49), + ("36", 36), + (11.4, 11.4), + ("42.0", 42.0), + (True, 1), + (False, 0), + # Conversion fails + ("foo", "foo"), + (None, None), + ], + ) + def test_init_float_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXNumberField( + key="temperature", + value=original_value, + field=FloatField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.key == "temperature" + assert f.original_value == original_value + assert f.value == cleaned_value + + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Conversion worked + (49, Decimal(49)), + ("36", Decimal(36)), + (11.4, Decimal(11.4)), + ("42.20", Decimal("42.20")), + (True, Decimal(1)), + (False, Decimal(0)), + (Decimal(5), Decimal(5)), + (Decimal("35.00"), Decimal("35.00")), + (Decimal("55.9"), Decimal("55.9")), + (Decimal("123.9999"), Decimal("123.9999")), + # Conversion fails + ("foo", "foo"), + (None, None), + ], + ) + def test_init_decimal_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXNumberField( + key="price", + value=original_value, + field=DecimalField(max_digits=10, decimal_places=2), + style=style, + mapping=None, + cell_style=style, + ) + assert f.key == "price" + assert f.original_value == original_value + assert f.value == cleaned_value + + def test_cell_integer(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXNumberField( + key="age", + value=42, + field=IntegerField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == 42 + assert cell.number_format == "0" + + def test_cell_float(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXNumberField( + key="weight", + value=35.5, + field=FloatField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == 35.5 + assert cell.number_format == "0.00" From 3c333ecdabb74afa59e49f6f1c66147f456d97af Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 15:29:41 +0100 Subject: [PATCH 04/12] Add TestXLSXDateField --- tests/test_fields.py | 164 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index d79e93c..b19ec6d 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,11 +1,20 @@ from decimal import Decimal +import datetime as dt import pytest from openpyxl.cell import Cell from openpyxl.worksheet.worksheet import Worksheet -from rest_framework.fields import CharField, IntegerField, FloatField, DecimalField +from rest_framework.fields import ( + CharField, + IntegerField, + FloatField, + DecimalField, + DateTimeField, + DateField, + TimeField, +) -from drf_excel.fields import XLSXField, XLSXNumberField +from drf_excel.fields import XLSXField, XLSXNumberField, XLSXDateField from drf_excel.utilities import XLSXStyle @@ -144,3 +153,154 @@ def test_cell_float(self, style: XLSXStyle, worksheet: Worksheet): assert isinstance(cell, Cell) assert cell.value == 35.5 assert cell.number_format == "0.00" + + +class TestXLSXDateField: + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Successful parsing + ("2020-01-01", dt.datetime(2020, 1, 1, 0, 0)), + ("2020-02-03T13:01", dt.datetime(2020, 2, 3, 13, 1)), + ("2020-03-04T13:15:30", dt.datetime(2020, 3, 4, 13, 15, 30)), + ("2020-10-08T15:18:23.1234Z", dt.datetime(2020, 10, 8, 15, 18, 23, 123400)), + # Failed parsing + ("foo", "foo"), + (None, None), + (True, True), + (300, 300), + (99.99, 99.99), + ], + ) + def test_init_datetime_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXDateField( + key="dt", + value=original_value, + field=DateTimeField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == original_value + assert f.value == cleaned_value + + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Successful parsing + ("2020-01-01", dt.date(2020, 1, 1)), + # Failed parsing + ("2020-02-03T13:01", None), + ("2020-03-04T13:15:30", None), + ("2020-10-08T15:18:23.1234Z", None), + ("foo", None), + (None, None), + (True, True), + (300, 300), + (99.99, 99.99), + ], + ) + def test_init_date_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXDateField( + key="d", + value=original_value, + field=DateField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == original_value + assert f.value == cleaned_value + + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + # Successful parsing + ("13:01", dt.time(13, 1)), + ("13:15:30", dt.time(13, 15, 30)), + ("14:15:16.1234Z", dt.time(14, 15, 16, 123400)), + # Failed parsing + ("2020-01-01", "2020-01-01"), + ("2020-02-03T13:01", "2020-02-03T13:01"), + ("2020-03-04T13:15:30", "2020-03-04T13:15:30"), + ("2020-10-08T15:18:23.1234Z", "2020-10-08T15:18:23.1234Z"), + ("foo", "foo"), + (None, None), + (True, True), + (300, 300), + (99.99, 99.99), + ], + ) + def test_init_time_field(self, style: XLSXStyle, original_value, cleaned_value): + f = XLSXDateField( + key="t", + value=original_value, + field=TimeField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == original_value + assert f.value == cleaned_value + + def test_cell_datetime_default_format(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXDateField( + key="dt", + value="2019-03-04T13:15:30", + field=DateTimeField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.datetime(2019, 3, 4, 13, 15, 30) + assert cell.number_format == "yyyy-mm-dd h:mm:ss" + + def test_cell_datetime_custom_format( + self, style: XLSXStyle, worksheet: Worksheet, settings + ): + settings.DRF_EXCEL_DATETIME_FORMAT = "dd/mm/yyyy h:mm:ss" + f = XLSXDateField( + key="dt", + value="01-04-2015 05:16:09", + field=DateTimeField(format="%d-%m-%Y %H:%M:%S"), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.datetime(2015, 4, 1, 5, 16, 9) + assert cell.number_format == "dd/mm/yyyy h:mm:ss" + + def test_cell_date_default_format(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXDateField( + key="dt", + value="2018-09-10", + field=DateField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.date(2018, 9, 10) + assert cell.number_format == "yyyy-mm-dd" + + def test_cell_date_custom_format( + self, style: XLSXStyle, worksheet: Worksheet, settings + ): + settings.DRF_EXCEL_DATE_FORMAT = "dd/mm/yyyy" + f = XLSXDateField( + key="dt", + value="25/10/2017", + field=DateField(format="%d/%m/%Y"), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.date(2017, 10, 25) + assert cell.number_format == "dd/mm/yyyy" From 3d06c2024c9ca3a5a1b40306d0b197185cc7fb5b Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 15:44:49 +0100 Subject: [PATCH 05/12] Add TestXLSXListField --- tests/test_fields.py | 50 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index b19ec6d..1ae284d 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -12,9 +12,10 @@ DateTimeField, DateField, TimeField, + ListField, ) -from drf_excel.fields import XLSXField, XLSXNumberField, XLSXDateField +from drf_excel.fields import XLSXField, XLSXNumberField, XLSXDateField, XLSXListField from drf_excel.utilities import XLSXStyle @@ -304,3 +305,50 @@ def test_cell_date_custom_format( assert isinstance(cell, Cell) assert cell.value == dt.date(2017, 10, 25) assert cell.number_format == "dd/mm/yyyy" + + +class TestXLSXListField: + def test_cell_default_separator(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXListField( + list_sep=None, + key="things", + value=["foo", "bar", "baz"], + field=ListField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == f.value == ["foo", "bar", "baz"] + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "foo, bar, baz" + + def test_cell_custom_separator(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXListField( + list_sep=";", + key="things", + value=["john", "doe", "john.doe@example.com"], + field=ListField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == f.value == ["john", "doe", "john.doe@example.com"] + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "john;doe;john.doe@example.com" + + def test_cell_complex_types(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXListField( + list_sep=None, + key="objs", + value=[{"a": 1}, {"b": 2}], + field=ListField(), + style=style, + mapping=None, + cell_style=style, + ) + assert f.original_value == f.value == [{"a": 1}, {"b": 2}] + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == '[{"a": 1}, {"b": 2}]' From 487f652fce9474eaf58bc3d7627fb14d37aed3ca Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 15:48:56 +0100 Subject: [PATCH 06/12] Add TestXLSXBooleanField --- tests/test_fields.py | 55 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 1ae284d..9c63871 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -13,9 +13,16 @@ DateField, TimeField, ListField, + BooleanField, ) -from drf_excel.fields import XLSXField, XLSXNumberField, XLSXDateField, XLSXListField +from drf_excel.fields import ( + XLSXField, + XLSXNumberField, + XLSXDateField, + XLSXListField, + XLSXBooleanField, +) from drf_excel.utilities import XLSXStyle @@ -352,3 +359,49 @@ def test_cell_complex_types(self, style: XLSXStyle, worksheet: Worksheet): cell = f.cell(worksheet, 1, 1) assert isinstance(cell, Cell) assert cell.value == '[{"a": 1}, {"b": 2}]' + + +class TestXLSXBooleanField: + @pytest.mark.parametrize("value", [True, False]) + def test_cell_default_display( + self, style: XLSXStyle, worksheet: Worksheet, value: bool + ): + f = XLSXBooleanField( + boolean_display={}, + key="is_active", + value=value, + field=BooleanField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == value + + @pytest.mark.parametrize( + ("original_value", "cleaned_value"), + [ + (True, "yes"), + (False, "no"), + ], + ) + def test_cell_custom_display( + self, + style: XLSXStyle, + worksheet: Worksheet, + original_value: bool, + cleaned_value: str, + ): + f = XLSXBooleanField( + boolean_display={True: "yes", False: "no"}, + key="is_active", + value=original_value, + field=BooleanField(), + style=style, + mapping=None, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == cleaned_value From d34474b66d8ba8f5b24320a47de42b6ae7764ce8 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 15:57:07 +0100 Subject: [PATCH 07/12] Test custom mapping --- tests/test_fields.py | 45 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 9c63871..448603e 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,5 +1,6 @@ from decimal import Decimal import datetime as dt +from types import SimpleNamespace import pytest from openpyxl.cell import Cell @@ -33,13 +34,53 @@ def style(): class TestXLSXField: def test_init(self, style: XLSXStyle): - f = XLSXField("foo", "bar", CharField(), style, None, style) + f = XLSXField( + key="foo", + value="bar", + field=CharField(), + style=style, + mapping="", + cell_style=style, + ) assert f.key == "foo" assert f.original_value == "bar" assert f.value == "bar" def test_cell(self, style: XLSXStyle, worksheet: Worksheet): - f = XLSXField("foo", "bar", CharField(), style, None, style) + f = XLSXField( + key="foo", + value="bar", + field=CharField(), + style=style, + mapping="", + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "bar" + + def test_cell_with_mapping_str(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXField( + key="foo", + value={"custom": "bar"}, + field=CharField(), + style=style, + mapping="custom", + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "bar" + + def test_cell_with_mapping_callable(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXField( + key="foo", + value=SimpleNamespace(custom="bar"), + field=CharField(), + style=style, + mapping=lambda v: v.custom, + cell_style=style, + ) cell = f.cell(worksheet, 1, 1) assert isinstance(cell, Cell) assert cell.value == "bar" From 9b8be8e877c1dc495f68fa3aedd42fae598c6adc Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 15:57:34 +0100 Subject: [PATCH 08/12] Fix type for empty mapping --- tests/test_fields.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 448603e..9e95014 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -108,7 +108,7 @@ def test_init_integer_field(self, style: XLSXStyle, original_value, cleaned_valu value=original_value, field=IntegerField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.key == "age" @@ -136,7 +136,7 @@ def test_init_float_field(self, style: XLSXStyle, original_value, cleaned_value) value=original_value, field=FloatField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.key == "temperature" @@ -168,7 +168,7 @@ def test_init_decimal_field(self, style: XLSXStyle, original_value, cleaned_valu value=original_value, field=DecimalField(max_digits=10, decimal_places=2), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.key == "price" @@ -181,7 +181,7 @@ def test_cell_integer(self, style: XLSXStyle, worksheet: Worksheet): value=42, field=IntegerField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -195,7 +195,7 @@ def test_cell_float(self, style: XLSXStyle, worksheet: Worksheet): value=35.5, field=FloatField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -227,7 +227,7 @@ def test_init_datetime_field(self, style: XLSXStyle, original_value, cleaned_val value=original_value, field=DateTimeField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == original_value @@ -255,7 +255,7 @@ def test_init_date_field(self, style: XLSXStyle, original_value, cleaned_value): value=original_value, field=DateField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == original_value @@ -286,7 +286,7 @@ def test_init_time_field(self, style: XLSXStyle, original_value, cleaned_value): value=original_value, field=TimeField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == original_value @@ -298,7 +298,7 @@ def test_cell_datetime_default_format(self, style: XLSXStyle, worksheet: Workshe value="2019-03-04T13:15:30", field=DateTimeField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -315,7 +315,7 @@ def test_cell_datetime_custom_format( value="01-04-2015 05:16:09", field=DateTimeField(format="%d-%m-%Y %H:%M:%S"), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -329,7 +329,7 @@ def test_cell_date_default_format(self, style: XLSXStyle, worksheet: Worksheet): value="2018-09-10", field=DateField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -346,7 +346,7 @@ def test_cell_date_custom_format( value="25/10/2017", field=DateField(format="%d/%m/%Y"), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -363,7 +363,7 @@ def test_cell_default_separator(self, style: XLSXStyle, worksheet: Worksheet): value=["foo", "bar", "baz"], field=ListField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == f.value == ["foo", "bar", "baz"] @@ -378,7 +378,7 @@ def test_cell_custom_separator(self, style: XLSXStyle, worksheet: Worksheet): value=["john", "doe", "john.doe@example.com"], field=ListField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == f.value == ["john", "doe", "john.doe@example.com"] @@ -393,7 +393,7 @@ def test_cell_complex_types(self, style: XLSXStyle, worksheet: Worksheet): value=[{"a": 1}, {"b": 2}], field=ListField(), style=style, - mapping=None, + mapping="", cell_style=style, ) assert f.original_value == f.value == [{"a": 1}, {"b": 2}] @@ -413,7 +413,7 @@ def test_cell_default_display( value=value, field=BooleanField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) @@ -440,7 +440,7 @@ def test_cell_custom_display( value=original_value, field=BooleanField(), style=style, - mapping=None, + mapping="", cell_style=style, ) cell = f.cell(worksheet, 1, 1) From e07fc75e6869fbf11a446e4e924b829d63f457fe Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 16:04:05 +0100 Subject: [PATCH 09/12] Simplify test case to avoid discrepancies between Python versions --- tests/test_fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 9e95014..0572056 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -212,7 +212,7 @@ class TestXLSXDateField: ("2020-01-01", dt.datetime(2020, 1, 1, 0, 0)), ("2020-02-03T13:01", dt.datetime(2020, 2, 3, 13, 1)), ("2020-03-04T13:15:30", dt.datetime(2020, 3, 4, 13, 15, 30)), - ("2020-10-08T15:18:23.1234Z", dt.datetime(2020, 10, 8, 15, 18, 23, 123400)), + ("2020-10-08T15:18:23Z", dt.datetime(2020, 10, 8, 15, 18, 23)), # Failed parsing ("foo", "foo"), (None, None), From 5f8cb1ab637df8213b0ad840b6ead5079fe11766 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 16:08:40 +0100 Subject: [PATCH 10/12] Test XLSXDateField celle rendering with TimeField --- tests/test_fields.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_fields.py b/tests/test_fields.py index 0572056..4e8b1ac 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -354,6 +354,37 @@ def test_cell_date_custom_format( assert cell.value == dt.date(2017, 10, 25) assert cell.number_format == "dd/mm/yyyy" + def test_cell_time_default_format(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXDateField( + key="dt", + value="09:10:11", + field=TimeField(), + style=style, + mapping="", + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.time(9, 10, 11) + assert cell.number_format == "h:mm:ss" + + def test_cell_time_custom_format( + self, style: XLSXStyle, worksheet: Worksheet, settings + ): + settings.DRF_EXCEL_TIME_FORMAT = "hh - mm - ss" + f = XLSXDateField( + key="dt", + value="09h 10m 11s", + field=TimeField(format="%Hh %Mm %Ss"), + style=style, + mapping="", + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == dt.time(9, 10, 11) + assert cell.number_format == "hh - mm - ss" + class TestXLSXListField: def test_cell_default_separator(self, style: XLSXStyle, worksheet: Worksheet): From b53eeeaaef05f66d8760c89ce52d2653189a5b6f Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 16:10:06 +0100 Subject: [PATCH 11/12] Test when mapping is neither a string nor callable --- tests/test_fields.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_fields.py b/tests/test_fields.py index 4e8b1ac..613c795 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -85,6 +85,19 @@ def test_cell_with_mapping_callable(self, style: XLSXStyle, worksheet: Worksheet assert isinstance(cell, Cell) assert cell.value == "bar" + def test_cell_with_invalid_mapping(self, style: XLSXStyle, worksheet: Worksheet): + f = XLSXField( + key="foo", + value="bar", + field=CharField(), + style=style, + mapping=55, + cell_style=style, + ) + cell = f.cell(worksheet, 1, 1) + assert isinstance(cell, Cell) + assert cell.value == "bar" + class TestXLSXNumberField: @pytest.mark.parametrize( From c2e5d8a3ebda0f6e2138c098cb95d089873f9be9 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Thu, 10 Oct 2024 16:12:01 +0100 Subject: [PATCH 12/12] Remove test case to avoid discrepancies between Python versions --- tests/test_fields.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 613c795..0789d00 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -280,7 +280,6 @@ def test_init_date_field(self, style: XLSXStyle, original_value, cleaned_value): # Successful parsing ("13:01", dt.time(13, 1)), ("13:15:30", dt.time(13, 15, 30)), - ("14:15:16.1234Z", dt.time(14, 15, 16, 123400)), # Failed parsing ("2020-01-01", "2020-01-01"), ("2020-02-03T13:01", "2020-02-03T13:01"),