From d47633ce306b12044f023fa2e4732f53ea778ba3 Mon Sep 17 00:00:00 2001 From: Joao S O Bueno Date: Sat, 6 Apr 2019 12:13:49 -0300 Subject: [PATCH 1/3] Mark string containing '\copy' as raw, mitigates ambiguity in '\c' --- rows/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}' " From b983f8169c2cf50e52b8f17d39df3c7f3c4d46e3 Mon Sep 17 00:00:00 2001 From: Joao S O Bueno Date: Sat, 6 Apr 2019 12:33:44 -0300 Subject: [PATCH 2/3] Adds test for multi-line cell text output --- tests/data/line_break.csv | 5 +++++ tests/tests_plugin_txt.py | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/data/line_break.csv 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..49d0f8cc 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,27 @@ 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) From 9b73357daa37a5bac291c969363cff277ec05780 Mon Sep 17 00:00:00 2001 From: Joao S O Bueno Date: Sat, 6 Apr 2019 13:07:48 -0300 Subject: [PATCH 3/3] Implements correct text output for multiline cells. --- rows/plugins/txt.py | 22 ++++++++++++++-------- tests/tests_plugin_txt.py | 17 +++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) 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/tests/tests_plugin_txt.py b/tests/tests_plugin_txt.py index 49d0f8cc..66251acd 100644 --- a/tests/tests_plugin_txt.py +++ b/tests/tests_plugin_txt.py @@ -255,14 +255,15 @@ def test_data_with_line_breaks_correctly_formated(self): 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) | | - +-----------------------+----------------------------------+ + +---------------+------------------+ + | nome | endereco | + +---------------+------------------+ + | José da Silva | Rua dos Bobos, 0 | + | | Cidade Fantasma | + | | | + | José Maria | R. XPTO, 1 | + | (Zé Maria) | | + +---------------+------------------+ """) temp.seek(0)