diff --git a/rows/plugins/txt.py b/rows/plugins/txt.py index 65eec200..26a7429a 100644 --- a/rows/plugins/txt.py +++ b/rows/plugins/txt.py @@ -122,7 +122,7 @@ def _parse_col_positions(frame_style, header_line): def _max_column_sizes(field_names, table_rows): columns = zip(*([field_names] + table_rows)) return { - field_name: max(len(value) for value in column) + field_name: max(max(len(line) for line in value.split("\n")) for value in column) for field_name, column in zip(field_names, columns) } @@ -256,13 +256,19 @@ def export_to_txt( result += [top_split_line] result += [header, body_split_line] - for row in table_rows: - values = [ - value.rjust(max_sizes[field_name]) - for field_name, value in zip(field_names, row) - ] - row_data = " {} ".format(frame["VERTICAL"]).join(values) - result.append("{0} {1} {0}".format(frame["VERTICAL"], row_data)) + for row_number, row in enumerate(table_rows): + row_height = max(cell.count("\n") for cell in row) + 1 + if row_height > 1 and row_number < len(table_rows) - 1: + row_height += 1 + + split_row = [cell.split("\n") for cell in row] + for cell_line in range(row_height): + values = [ + (value[cell_line] if cell_line < len(value) else "").rjust(max_sizes[field_name]) + for field_name, value in zip(field_names, split_row) + ] + row_data = " {} ".format(frame["VERTICAL"]).join(values) + result.append("{0} {1} {0}".format(frame["VERTICAL"], row_data)) if frame_style != "None": result.append(botton_split_line) diff --git a/rows/utils.py b/rows/utils.py index 471e36e5..aea437ed 100644 --- a/rows/utils.py +++ b/rows/utils.py @@ -763,7 +763,7 @@ def get_psql_copy_command( header = ", ".join(slug(field_name) for field_name in header) header = "({header}) ".format(header=header) copy = ( - "\copy {table_name} {header}{direction} STDIN " + r"\copy {table_name} {header}{direction} STDIN " "DELIMITER '{delimiter}' " "QUOTE '{quote}' " "ENCODING '{encoding}' " diff --git a/tests/data/line_break.csv b/tests/data/line_break.csv new file mode 100644 index 00000000..d59830a1 --- /dev/null +++ b/tests/data/line_break.csv @@ -0,0 +1,5 @@ +nome,endereco +José da Silva,"Rua dos Bobos, 0 +Cidade Fantasma" +"José Maria +(Zé Maria)","R. XPTO, 1" \ No newline at end of file diff --git a/tests/tests_plugin_txt.py b/tests/tests_plugin_txt.py index 965419f6..66251acd 100644 --- a/tests/tests_plugin_txt.py +++ b/tests/tests_plugin_txt.py @@ -21,6 +21,7 @@ import tempfile import unittest from collections import OrderedDict +from textwrap import dedent import mock import six @@ -244,3 +245,28 @@ def test__parse_col_positions(self): self.assertEqual(result1, [0, 5, 10]) result2 = rows.plugins.txt._parse_col_positions("None", " col1 col2 ") self.assertEqual(result2, [0, 7, 14]) + + + def test_data_with_line_breaks_correctly_formated(self): + temp = tempfile.NamedTemporaryFile(delete=False) + + original_data = rows.import_from_csv("tests/data/line_break.csv") + rows.export_to_txt( + original_data, temp.file, encoding="utf-8", frame_style="ASCII", + ) + expected_output = dedent("""\ + +---------------+------------------+ + | nome | endereco | + +---------------+------------------+ + | José da Silva | Rua dos Bobos, 0 | + | | Cidade Fantasma | + | | | + | José Maria | R. XPTO, 1 | + | (Zé Maria) | | + +---------------+------------------+ + """) + + temp.seek(0) + text_data = temp.read().decode("utf-8") + + self.assertEqual(text_data, expected_output)