Skip to content

Commit

Permalink
Update tests and code for easier reading
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgy8 committed Jan 18, 2025
1 parent eeca7e5 commit be9db5e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 36 deletions.
20 changes: 12 additions & 8 deletions src/tablib/formats/_xlsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from openpyxl.styles import Alignment, Font
from openpyxl.utils import get_column_letter
from openpyxl.workbook import Workbook
from openpyxl.writer.excel import ExcelWriter

import tablib

Expand Down Expand Up @@ -50,6 +49,11 @@ def export_set(cls, dataset, freeze_panes=True, invalid_char_subst="-", escape=F
If ``escape`` is True, formulae will have the leading '=' character removed.
This is a security measure to prevent formulae from executing by default
in exported XLSX files.
If ``column_width`` is set to "adaptive", the column width will be set to the maximum
width of the content in each column. If it is set to an integer, the column width will be
set to that integer value. If it is set to None, the column width will be set as the default openpyxl.Worksheet width value.
"""
wb = Workbook()
ws = wb.worksheets[0]
Expand All @@ -60,9 +64,6 @@ def export_set(cls, dataset, freeze_panes=True, invalid_char_subst="-", escape=F
)

cls.dset_sheet(dataset, ws, freeze_panes=freeze_panes, escape=escape)
if isinstance(column_width, str) and column_width != "adaptive":
raise ValueError(f"Unsupported value `{column_width}` passed to `column_width` "
"parameter. It supports 'adaptive' or integer values")

cls._adapt_column_width(ws, column_width)

Expand Down Expand Up @@ -175,21 +176,24 @@ def dset_sheet(cls, dataset, ws, freeze_panes=True, escape=False):
cell.value = cell.value.replace("=", "")

@classmethod
def _adapt_column_width(cls, worksheet,
width: str | int | None) -> None:
def _adapt_column_width(cls, worksheet, width):
if isinstance(width, str) and width != "adaptive":
raise ValueError(f"Unsupported value `{width}` passed to `column_width` "
"parameter. It supports 'adaptive' or integer values")

if width is None:
return

column_widths = []
if isinstance(width, str) and width == "adaptive":
if width == "adaptive":
for row in worksheet.values:
for i, cell in enumerate(row):
cell = str(cell)
if len(column_widths) > i:
if len(cell) > column_widths[i]:
column_widths[i] = len(cell)
else:
column_widths += [len(cell)]
column_widths.append(len(cell))
else:
column_widths = [width] * worksheet.max_column

Expand Down
56 changes: 28 additions & 28 deletions tests/test_tablib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,24 @@ def get_format_str(cell):


class XLSXTests(BaseTestCase):
def _helper_export_column_width(self, column_width):
"""check that column width adapts to value length"""
def _get_width(data, input_arg):
xlsx_content = data.export('xlsx', column_width=input_arg)
wb = load_workbook(filename=BytesIO(xlsx_content))
ws = wb.active
return ws.column_dimensions['A'].width

xls_source = Path(__file__).parent / 'files' / 'xlsx_cell_values.xlsx'
with xls_source.open('rb') as fh:
data = tablib.Dataset().load(fh)
width_before = _get_width(data, column_width)
data.append([
'verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue',
])
width_after = _get_width(data, width_before)
return width_before, width_after

def test_xlsx_format_detect(self):
"""Test the XLSX format detection."""
in_stream = self.founders.xlsx
Expand Down Expand Up @@ -1484,45 +1502,27 @@ def test_xlsx_raise_ValueError_on_cell_write_during_export(self):
_xlsx = data.export('xlsx')
wb = load_workbook(filename=BytesIO(_xlsx))
self.assertEqual('[1]', wb.active['A1'].value)

def _helper_export_column_width(self, input_arg):
"""check that column width adapts to value length"""
def _get_width(data, input_arg):
xlsx_content = data.export('xlsx', column_width=input_arg)
wb = load_workbook(filename=BytesIO(xlsx_content))
ws = wb.active
return ws.column_dimensions['A'].width

xls_source = Path(__file__).parent / 'files' / 'xlsx_cell_values.xlsx'
with xls_source.open('rb') as fh:
data = tablib.Dataset().load(fh)
width_before = _get_width(data, input_arg)
data.append([
'verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue-verylongvalue',
])
width_after = _get_width(data, width_before)
return width_before, width_after

def test_xlsx_column_width_none(self):
"""check column width with None"""
width_before, width_after = self._helper_export_column_width(None)
self.assertEqual(width_before, 13)
self.assertEqual(width_after, 13)


def test_xlsx_column_width_adaptive(self):
"""check column width with 'adaptive'"""
""" Test that column width adapts to value length"""
width_before, width_after = self._helper_export_column_width("adaptive")
self.assertEqual(width_before, 11)
self.assertEqual(width_after, 11)

def test_xlsx_column_width_integer(self):
"""check column width with an integer"""
"""Test that column width changes to integer length"""
width_before, width_after = self._helper_export_column_width(10)
self.assertEqual(width_before, 10)
self.assertEqual(width_after, 10)

def test_xlsx_column_width_none(self):
"""Test that column width does not change"""
width_before, width_after = self._helper_export_column_width(None)
self.assertEqual(width_before, 13)
self.assertEqual(width_after, 13)

def test_xlsx_column_width_value_error(self):
"""check column width with invalid input"""
"""Raise ValueError if column_width is not a valid input"""
with self.assertRaises(ValueError):
self._helper_export_column_width("invalid input")

Expand Down

0 comments on commit be9db5e

Please sign in to comment.