From 4308dece83184a04dc836aca67f304f131843566 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 11 May 2016 09:16:45 +0100 Subject: [PATCH] adapt pyexcel v0.2.2 and code refactoring on tabulate and json handlers. much simpler code --- README.rst | 24 +++--- pyexcel_text/__init__.py | 4 - pyexcel_text/_json.py | 116 +++++++------------------- pyexcel_text/_text.py | 163 +++++-------------------------------- tests/fixtures.py | 66 +++++++-------- tests/test_io.py | 7 +- tests/test_presentation.py | 36 ++++---- 7 files changed, 114 insertions(+), 302 deletions(-) diff --git a/README.rst b/README.rst index 12e1096..5ae74b6 100644 --- a/README.rst +++ b/README.rst @@ -41,23 +41,21 @@ Simple ... ] >>> sheet = pe.Sheet(content) >>> print(sheet.simple) - Sheet Name: pyexcel + pyexcel sheet: -------- -------- -------- Column 1 Column 2 Column 3 1 2 3 4 5 6 7 8 9 -------- -------- -------- - >>> sheet.name_columns_by_row(0) >>> print(sheet.simple) - Sheet Name: pyexcel + pyexcel sheet: Column 1 Column 2 Column 3 ---------- ---------- ---------- 1 2 3 4 5 6 7 8 9 - Grid @@ -66,7 +64,7 @@ Grid .. code-block:: python >>> print(sheet.grid) - Sheet Name: pyexcel + pyexcel sheet: +------------+------------+------------+ | Column 1 | Column 2 | Column 3 | +============+============+============+ @@ -76,7 +74,7 @@ Grid +------------+------------+------------+ | 7 | 8 | 9 | +------------+------------+------------+ - + Mediawiki ------------- @@ -107,7 +105,7 @@ Mediawiki >>> book.save_as("myfile.mediawiki") >>> myfile = open("myfile.mediawiki") >>> print(myfile.read()) - Sheet Name: Sheet 1 + Sheet 1: {| class="wikitable" style="text-align: left;" |+ |- @@ -117,7 +115,7 @@ Mediawiki |- | align="right"| 7 || align="right"| 8 || align="right"| 9 |} - Sheet Name: Sheet 2 + Sheet 2: {| class="wikitable" style="text-align: left;" |+ |- @@ -127,7 +125,7 @@ Mediawiki |- | 4.0 || 5.0 || 6.0 |} - Sheet Name: Sheet 3 + Sheet 3: {| class="wikitable" style="text-align: left;" |+ |- @@ -137,7 +135,6 @@ Mediawiki |- | 4.0 || 3.0 || 2.0 |} - >>> myfile.close() Html @@ -148,25 +145,24 @@ Html >>> book.save_as("myfile.html") >>> myfile = open("myfile.html") >>> print(myfile.read()) - Sheet Name: Sheet 1 + Sheet 1:
123
456
789
- Sheet Name: Sheet 2 + Sheet 2:
X Y Z
1.02.03.0
4.05.06.0
- Sheet Name: Sheet 3 + Sheet 3:
O P Q
3.02.01.0
4.03.02.0
- .. testcode:: :hide: diff --git a/pyexcel_text/__init__.py b/pyexcel_text/__init__.py index 07c99a3..1a7f1b9 100644 --- a/pyexcel_text/__init__.py +++ b/pyexcel_text/__init__.py @@ -16,10 +16,6 @@ pyexcel.Sheet.save_as, pyexcel.Book.save_as. """ -sources = text.sources + json.sources -file_types = text.file_types + json.file_types - - def save_as(instance, filename): """ Legacy modular function. Now it is removed diff --git a/pyexcel_text/_json.py b/pyexcel_text/_json.py index 7dd0cef..3d3fb9b 100644 --- a/pyexcel_text/_json.py +++ b/pyexcel_text/_json.py @@ -9,95 +9,35 @@ """ import json -from pyexcel.sources import params - -from ._text import TextSource, WriteOnlyMemorySourceMixin - file_types = ('json',) -class JsonSheetSource(TextSource): - """ - Write a two dimensional array into json format - """ - text_file_formats = file_types - - def __init__(self, file_name=None, write_title=True, **keywords): - self.file_name = file_name - self.write_title = write_title - self.keywords = keywords - - def write_data(self, sheet): - data = self._transform_data(sheet) - with open(self.file_name, 'w') as jsonfile: - if self.write_title: - data = {sheet.name: data} - self._write_sheet(jsonfile, data) - - def _write_sheet(self, jsonfile, data): - jsonfile.write(json.dumps(data, sort_keys=True)) - - def _transform_data(self, sheet): - table = sheet.to_array() - if hasattr(sheet, 'colnames'): - colnames = sheet.colnames - rownames = sheet.rownames - # In the following, row[0] is the name of each row - if colnames and rownames: - table = dict((row[0], dict(zip(colnames, row[1:]))) - for row in table[1:]) - elif colnames: - table = [dict(zip(colnames, row)) for row in table[1:]] - elif rownames: - table = dict((row[0], row[1:]) for row in table) - else: - table = list(table) - return table - - -class JsonSheetSourceInMemory(JsonSheetSource, WriteOnlyMemorySourceMixin): - fields = [params.FILE_TYPE] - def __init__(self, file_type=None, file_stream=None, write_title=True, - **keywords): - WriteOnlyMemorySourceMixin.__init__( - self, - file_type=file_type, - file_stream=file_stream, - write_title=write_title, - **keywords) - - def write_data(self, sheet): - data = self._transform_data(sheet) - if self.write_title: - data = {sheet.name: data} - self._write_sheet(self.content, data) - - -def write_json_book(jsonfile, bookdict): - jsonfile.write(json.dumps(bookdict, sort_keys=True)) - - -class JsonBookSourceInMemory(JsonSheetSourceInMemory): - targets = (params.BOOK,) - actions = (params.WRITE_ACTION,) - - def write_data(self, book): - write_json_book(self.content, book.to_dict()) - - -class JsonBookSource(JsonSheetSource): - """ - Write a dictionary of two dimensional arrays into json format - """ - targets = (params.BOOK,) - actions = (params.WRITE_ACTION,) - - def write_data(self, book): - with open(self.file_name, 'w') as jsonfile: - write_json_book(jsonfile, book.to_dict()) - - -sources = (JsonSheetSource, JsonBookSource, - JsonSheetSourceInMemory, JsonBookSourceInMemory) - +def jsonify(sheet, file_type, write_title): + content = "" + table = sheet.to_array() + if hasattr(sheet, 'colnames'): + colnames = sheet.colnames + rownames = sheet.rownames + # In the following, row[0] is the name of each row + if colnames and rownames: + table = dict((row[0], dict(zip(colnames, row[1:]))) + for row in table[1:]) + elif colnames: + table = [dict(zip(colnames, row)) for row in table[1:]] + elif rownames: + table = dict((row[0], row[1:]) for row in table) + else: + table = list(table) + if write_title: + content = {sheet.name: table} + else: + content = table + return json.dumps(content, sort_keys=True) + + +def jsonify_book(book, file_type): + return json.dumps(book.to_dict(), sort_keys=True) + + +renderer = (jsonify, jsonify_book) diff --git a/pyexcel_text/_text.py b/pyexcel_text/_text.py index 36de255..e8dab8c 100644 --- a/pyexcel_text/_text.py +++ b/pyexcel_text/_text.py @@ -11,10 +11,6 @@ from pyexcel.sheets import NominableSheet, SheetStream from pyexcel.sheets.matrix import uniform -from pyexcel.sources.base import FileSource -from pyexcel.sources import params - -from ._compact import StringIO file_types = ( @@ -30,140 +26,25 @@ 'latex_booktabs' ) -class WriteOnlyMemorySourceMixin(object): - """ - Write up all memory source initialization once here - """ - def __init__(self, file_type=None, file_stream=None, write_title=True, - **keywords): - if file_stream: - self.content = file_stream - else: - self.content = StringIO() - self.file_type = file_type - self.keywords = keywords - self.write_title = write_title - - -class TextSource(FileSource): - """ - Base class for all sources in this module - """ - fields = [params.FILE_NAME] - targets = (params.SHEET,) - actions = (params.WRITE_ACTION,) - text_file_formats = file_types - - @classmethod - def can_i_handle(cls, action, file_type): - status = False - if action == params.WRITE_ACTION and file_type in cls.text_file_formats: - status = True - return status - - -class TextSheetSource(TextSource): - """ - A single sheet in text format - """ - def __init__(self, file_name=None, write_title=True, **keywords): - self.file_name = file_name - self.keywords = keywords - self.write_title = write_title - self.file_type = file_name.split(".")[-1] - - def write_data(self, sheet): - """ - Call by pyexcel to write out a sheet instance - """ - data = self._transform_data(sheet) - with open(self.file_name, 'w') as textfile: - self.write_sheet(textfile, data, sheet.name) - - def write_sheet(self, textfile, data, title): - """write out data to a file handle - - the file handle can be a stream - """ - if self.write_title: - textfile.write("Sheet Name: %s\n" % title) - textfile.write(tabulate.tabulate(data, - tablefmt=self.file_type, - **self.keywords)) - textfile.write("\n") - - def _transform_data(self, sheet): - table = [] - if isinstance(sheet, SheetStream): - table = list(sheet.to_array()) - width, table = uniform(table) - - if isinstance(sheet, NominableSheet): - if len(sheet.colnames) > 0: - self.keywords['headers'] = 'firstrow' - table = sheet.to_array() - return table - - -class TextSheetSourceInMemory(TextSheetSource, WriteOnlyMemorySourceMixin): - """ - Write to an io stream - """ - fields = [params.FILE_TYPE] - - def __init__(self, file_type=None, file_stream=None, - write_title=True, **keywords): - WriteOnlyMemorySourceMixin.__init__( - self, file_type=file_type, - file_stream=file_stream, write_title=write_title, **keywords) - - def write_data(self, sheet): - """no need to close file because it is a memory stream""" - data = self._transform_data(sheet) - self.write_sheet(self.content, data, sheet.name) - - -class TextBookSource(TextSheetSource): - """ - A excel book in text format - """ - targets = (params.BOOK,) - - def __init__(self, file_name=None, write_title=True, **keywords): - self.file_name = file_name - self.keywords = keywords - self.write_title = write_title - self.file_type = file_name.split(".")[-1] - - def write_data(self, book): - """Override TextSheetSource.write_data so as to write a book""" - with open(self.file_name, 'w') as textfile: - self.write_book(textfile, book) - - def write_book(self, textfile, book): - """but write_book in turn needs to write_sheet""" - for sheet in book: - data = self._transform_data(sheet) - self.write_sheet(textfile, data, sheet.name) - - -class TextBookSourceInMemory(TextBookSource, WriteOnlyMemorySourceMixin): - """ - Write book in text format to memory - """ - fields = [params.FILE_TYPE] - - def __init__(self, file_type=None, file_stream=None, - write_title=True, **keywords): - WriteOnlyMemorySourceMixin.__init__( - self, file_type=file_type, - file_stream=file_stream, write_title=write_title, **keywords) - - def write_data(self, book): - """Yet again, no need to close a memory stream""" - self.write_book(self.content, book) - - -# register sources -sources = (TextSheetSource, TextBookSource, - TextSheetSourceInMemory, TextBookSourceInMemory) +def tabulating(sheet, file_type, write_title): + content = "" + if write_title: + content += "%s:\n" % sheet.name + table = [] + keywords = {} + if isinstance(sheet, SheetStream): + table = list(sheet.to_array()) + width, table = uniform(table) + + if isinstance(sheet, NominableSheet): + if len(sheet.colnames) > 0: + keywords['headers'] = 'firstrow' + table = sheet.to_array() + content += tabulate.tabulate( + table, + tablefmt=file_type, + **keywords) + return content + + +renderer = (tabulating, None) \ No newline at end of file diff --git a/tests/fixtures.py b/tests/fixtures.py index 4b151a3..c8b86a5 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -7,12 +7,12 @@ EXPECTED_RESULTS = { 'simple': { 'dict': dedent(""" - Sheet Name: sheet 1 + sheet 1: - - 1 2 3 4 - - - Sheet Name: sheet 2 + sheet 2: - - 5 6 7 8 @@ -27,14 +27,14 @@ 7 8 - -""").strip('\n'), 'normal_usage': dedent(""" - Sheet Name: pyexcel + pyexcel sheet: - --- --- 1 2 3 4 588 6 7 8 999 - --- ---""").strip('\n'), 'new_normal_usage': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: - --- --- 1 2 3 4 588 6 @@ -47,21 +47,21 @@ 7 8 999 - --- ---""").strip('\n'), 'new_normal_usage_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: - --- - 1 2 3 4 588 6 7 8 - --- -""").strip('\n'), 'csvbook_irregular_columns': dedent(""" - Sheet Name: testfile.csv + testfile.csv: - --- - 1 2 3 4 588 6 7 8 - --- -""").strip('\n'), 'column_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: Column 1 Column 2 Column 3 ---------- ---------- ---------- 1 2 3 @@ -69,21 +69,21 @@ 7 8 9""").strip('\n'), # FIXME: numerical align lost when one cell is missing 'column_series_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: Column 1 Column 2 Column 3 ---------- ---------- ---------- 1 2 3 4 5 6 7 8""").strip('\n'), 'data_frame': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: Column 1 Column 2 Column 3 ----- ---------- ---------- ---------- Row 1 1 2 3 Row 2 4 5 6 Row 3 7 8 9""").strip('\n'), 'row_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ----- - - - Row 1 1 2 3 Row 2 4 5 6 @@ -92,12 +92,12 @@ }, "rst":{ 'dict': dedent(""" - Sheet Name: sheet 1 + sheet 1: = = 1 2 3 4 = = - Sheet Name: sheet 2 + sheet 2: = = 5 6 7 8 @@ -112,14 +112,14 @@ 7 8 = =""").strip('\n'), 'normal_usage': dedent(""" - Sheet Name: pyexcel + pyexcel sheet: = === === 1 2 3 4 588 6 7 8 999 = === ===""").strip('\n'), 'new_normal_usage': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: = === === 1 2 3 4 588 6 @@ -132,14 +132,14 @@ 7 8 999 = === ===""").strip('\n'), 'new_normal_usage_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: = === = 1 2 3 4 588 6 7 8 = === =""").strip('\n'), 'column_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ========== ========== ========== Column 1 Column 2 Column 3 ========== ========== ========== @@ -148,7 +148,7 @@ 7 8 9 ========== ========== ==========""").strip('\n'), 'column_series_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ========== ========== ========== Column 1 Column 2 Column 3 ========== ========== ========== @@ -157,14 +157,14 @@ 7 8 ========== ========== ==========""").strip('\n'), 'csvbook_irregular_columns': dedent(""" - Sheet Name: testfile.csv + testfile.csv: = === = 1 2 3 4 588 6 7 8 = === =""").strip('\n'), 'row_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ===== = = = Row 1 1 2 3 Row 2 4 5 6 @@ -173,12 +173,12 @@ }, 'html': { 'dict': dedent(""" - Sheet Name: sheet 1 + sheet 1:
12
34
- Sheet Name: sheet 2 + sheet 2: @@ -193,14 +193,14 @@
56
78
78
""").strip('\n'), 'normal_usage': dedent(""" - Sheet Name: pyexcel + pyexcel sheet:
1 2 3
4588 6
7 8999
""").strip('\n'), 'new_normal_usage': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: @@ -213,14 +213,14 @@
1 2 3
4588 6
7 8999
""").strip('\n'), 'new_normal_usage_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1:
1 23
45886
7 8
""").strip('\n'), 'column_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: @@ -228,7 +228,7 @@
Column 1 Column 2 Column 3
1 2 3
7 8 9
""").strip('\n'), 'column_series_irregular_columns': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: @@ -236,14 +236,14 @@
Column 1 Column 2Column 3
1 23
7 8
""").strip('\n'), 'csvbook_irregular_columns': dedent(""" - Sheet Name: testfile.csv + testfile.csv:
1 23
45886
7 8
""").strip('\n'), 'data_frame': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: @@ -251,7 +251,7 @@
Column 1 Column 2 Column 3
Row 1 1 2 3
Row 3 7 8 9
""").strip('\n'), 'row_series': dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: @@ -264,7 +264,7 @@ 'no_title_multiple_sheets': '{"sheet 1": [[1, 2], [3, 4]], "sheet 2": [[5, 6], [7, 8]]}', 'normal_usage': - '{"pyexcel": [[1, 2, 3], [4, 588, 6], [7, 8, 999]]}', + '{"pyexcel sheet": [[1, 2, 3], [4, 588, 6], [7, 8, 999]]}', 'new_normal_usage': '{"pyexcel_sheet1": [[1, 2, 3], [4, 588, 6], [7, 8, 999]]}', 'no_title_single_sheet': @@ -280,7 +280,7 @@ ' {"Column 1": 4, "Column 2": 5, "Column 3": 6},' ' {"Column 1": 7, "Column 2": 8, "Column 3": ""}]}', 'csvbook_irregular_columns': - '{"testfile.csv": [["1", "2", "3"], ["4", "588", "6"], ["7", "8"]]}', + '{"testfile.csv": [[1, 2, 3], [4, 588, 6], [7, 8]]}', 'data_frame': '{"pyexcel_sheet1": {"Row 1": {"Column 1": 1, "Column 2": 2, "Column 3": 3}, "Row 2": {"Column 1": 4, "Column 2": 5, "Column 3": 6}, "Row 3": {"Column 1": 7, "Column 2": 8, "Column 3": 9}}}', 'row_series': @@ -291,7 +291,7 @@ if (LooseVersion(tabulate.__version__) <= LooseVersion('0.7.5') or platform.python_implementation() == 'PyPy'): EXPECTED_RESULTS['rst']['data_frame'] = dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ===== ========== ========== ========== Column 1 Column 2 Column 3 ===== ========== ========== ========== @@ -301,7 +301,7 @@ ===== ========== ========== ==========""").strip('\n') else: EXPECTED_RESULTS['rst']['data_frame'] = dedent(""" - Sheet Name: pyexcel_sheet1 + pyexcel_sheet1: ===== ========== ========== ========== .. Column 1 Column 2 Column 3 ===== ========== ========== ========== diff --git a/tests/test_io.py b/tests/test_io.py index c932153..da1ed4b 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -197,14 +197,13 @@ def test_normal_usage(self): # note, plus the trailing '\n' # due to tabluate produces the extra new line content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: - --- --- 1 2 3 4 588 6 7 8 999 - - --- --- - """).strip('\n') + '\n' - self.assertEqual(s.simple,content) + - --- ---""").strip('\n') + self.assertEqual(s.simple, content) if __name__ == "__main__": unittest.main() diff --git a/tests/test_presentation.py b/tests/test_presentation.py index 74d1b6b..9741619 100644 --- a/tests/test_presentation.py +++ b/tests/test_presentation.py @@ -20,7 +20,7 @@ def _check_presentation(self, name, presentation): 'expected result missing: %s' % presentation) expected = self.expected_results[name] - self.assertEqual(presentation, expected+'\n') + self.assertEqual(presentation, expected) def test_no_title_multiple_sheets(self): adict = { @@ -185,7 +185,7 @@ class TestJson(TestSimple): def setUp(self): TestSimple.setUp(self) - self.expected_results['csvbook_irregular_columns'] = '{"testfile.csv": [["1", "2", "3"], ["4", "588", "6"], ["7", "8", ""]]}' + self.expected_results['csvbook_irregular_columns'] = '{"testfile.csv": [[1, 2, 3], [4, 588, 6], [7, 8, ""]]}' self.expected_results['new_normal_usage_irregular_columns'] = '{"pyexcel_sheet1": [[1, 2, 3], [4, 588, 6], [7, 8, ""]]}' def _check_presentation(self, name, presentation): @@ -206,7 +206,7 @@ def _check_presentation(self, name, presentation): 'expected result missing: %s' % presentation) expected = self.expected_results[name] - self.assertEqual(presentation, expected+'\n') + self.assertEqual(presentation, expected) class TestCustomJson(TestCase): @@ -218,7 +218,7 @@ def test_matrix(self): [7, 8, 999] ] s = pe.sheets.Sheet(content) - content = "{\"pyexcel\": [[1, 2, 3], [4, 588, 6], [7, 8, 999]]}" + content = "{\"pyexcel sheet\": [[1, 2, 3], [4, 588, 6], [7, 8, 999]]}" self.assertEqual(s.json, content) def test_sheet(self): @@ -266,12 +266,12 @@ def test_normal_usage(self): ] s = pe.Sheet(content) content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: - --- --- 1 2 3 4 588 6 7 8 999 - - --- ---""").strip('\n') + '\n' + - --- ---""").strip('\n') self.assertEqual(s.simple, content) def test_irregular_usage(self): @@ -283,12 +283,12 @@ def test_irregular_usage(self): ] s = pe.Sheet(content) content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: - --- - 1 2 3 4 588 6 7 8 - - --- -""").strip('\n') + '\n' + - --- -""").strip('\n') self.assertEqual(s.simple, content) @@ -301,12 +301,12 @@ def test_column_series(self): ] s = pe.Sheet(content, name_columns_by_row=0) content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: Column 1 Column 2 Column 3 ---------- ---------- ---------- 1 2 3 4 5 6 - 7 8 9""").strip('\n') + '\n' + 7 8 9""").strip('\n') self.assertEqual(s.simple, content) def test_data_frame(self): @@ -318,12 +318,12 @@ def test_data_frame(self): ] s = pe.Sheet(content, name_rows_by_column=0, name_columns_by_row=0) content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: Column 1 Column 2 Column 3 ----- ---------- ---------- ---------- Row 1 1 2 3 Row 2 4 5 6 - Row 3 7 8 9""").strip('\n') + '\n' + Row 3 7 8 9""").strip('\n') self.assertEqual(s.simple, content) def test_row_series(self): @@ -334,12 +334,12 @@ def test_row_series(self): ] s = pe.Sheet(content, name_rows_by_column=0) content = dedent(""" - Sheet Name: pyexcel + pyexcel sheet: ----- - - - Row 1 1 2 3 Row 2 4 5 6 Row 3 7 8 9 - ----- - - -""").strip('\n') + '\n' + ----- - - -""").strip('\n') self.assertEqual(s.simple, content) def test_book_presentation(self): @@ -365,22 +365,22 @@ def test_book_presentation(self): } book = pe.Book(data) content = dedent(""" - Sheet Name: Sheet 1 + Sheet 1: - - - 1 2 3 4 5 6 7 8 9 - - - - Sheet Name: Sheet 2 + Sheet 2: --- --- --- X Y Z 1.0 2.0 3.0 4.0 5.0 6.0 --- --- --- - Sheet Name: Sheet 3 + Sheet 3: --- --- --- O P Q 3.0 2.0 1.0 4.0 3.0 2.0 - --- --- ---""").strip("\n") + '\n' + --- --- ---""").strip("\n") self.assertEqual(book.simple, content)
Row 1123
Row 2456