# encoding: utf-8 """ Test suite for the docx.table module """ from __future__ import absolute_import, print_function, unicode_literals import pytest from docx.enum.style import WD_STYLE_TYPE from docx.enum.table import WD_TABLE_ALIGNMENT, WD_TABLE_DIRECTION from docx.oxml import parse_xml from docx.oxml.table import CT_Tc from docx.parts.document import DocumentPart from docx.shared import Inches from docx.table import _Cell, _Column, _Columns, _Row, _Rows, Table from docx.text.paragraph import Paragraph from .oxml.unitdata.table import a_gridCol, a_tbl, a_tblGrid, a_tc, a_tr from .oxml.unitdata.text import a_p from .unitutil.cxml import element, xml from .unitutil.file import snippet_seq from .unitutil.mock import instance_mock, property_mock class DescribeTable(object): def it_can_add_a_row(self, add_row_fixture): table, expected_xml = add_row_fixture row = table.add_row() assert table._tbl.xml == expected_xml assert isinstance(row, _Row) assert row._tr is table._tbl.tr_lst[-1] assert row._parent is table def it_can_add_a_column(self, add_column_fixture): table, width, expected_xml = add_column_fixture column = table.add_column(width) assert table._tbl.xml == expected_xml assert isinstance(column, _Column) assert column._gridCol is table._tbl.tblGrid.gridCol_lst[-1] assert column._parent is table def it_provides_access_to_a_cell_by_row_and_col_indices(self, table): for row_idx in range(2): for col_idx in range(2): cell = table.cell(row_idx, col_idx) assert isinstance(cell, _Cell) tr = table._tbl.tr_lst[row_idx] tc = tr.tc_lst[col_idx] assert tc is cell._tc def it_provides_access_to_the_table_rows(self, table): rows = table.rows assert isinstance(rows, _Rows) def it_provides_access_to_the_table_columns(self, table): columns = table.columns assert isinstance(columns, _Columns) def it_provides_access_to_the_cells_in_a_column(self, col_cells_fixture): table, column_idx, expected_cells = col_cells_fixture column_cells = table.column_cells(column_idx) assert column_cells == expected_cells def it_provides_access_to_the_cells_in_a_row(self, row_cells_fixture): table, row_idx, expected_cells = row_cells_fixture row_cells = table.row_cells(row_idx) assert row_cells == expected_cells def it_knows_its_alignment_setting(self, alignment_get_fixture): table, expected_value = alignment_get_fixture assert table.alignment == expected_value def it_can_change_its_alignment_setting(self, alignment_set_fixture): table, new_value, expected_xml = alignment_set_fixture table.alignment = new_value assert table._tbl.xml == expected_xml def it_knows_whether_it_should_autofit(self, autofit_get_fixture): table, expected_value = autofit_get_fixture assert table.autofit is expected_value def it_can_change_its_autofit_setting(self, autofit_set_fixture): table, new_value, expected_xml = autofit_set_fixture table.autofit = new_value assert table._tbl.xml == expected_xml def it_knows_it_is_the_table_its_children_belong_to(self, table_fixture): table = table_fixture assert table.table is table def it_knows_its_direction(self, direction_get_fixture): table, expected_value = direction_get_fixture assert table.table_direction == expected_value def it_can_change_its_direction(self, direction_set_fixture): table, new_value, expected_xml = direction_set_fixture table.table_direction = new_value assert table._element.xml == expected_xml def it_knows_its_table_style(self, style_get_fixture): table, style_id_, style_ = style_get_fixture style = table.style table.part.get_style.assert_called_once_with( style_id_, WD_STYLE_TYPE.TABLE ) assert style is style_ def it_can_change_its_table_style(self, style_set_fixture): table, value, expected_xml = style_set_fixture table.style = value table.part.get_style_id.assert_called_once_with( value, WD_STYLE_TYPE.TABLE ) assert table._tbl.xml == expected_xml def it_provides_access_to_its_cells_to_help(self, cells_fixture): table, cell_count, unique_count, matches = cells_fixture cells = table._cells assert len(cells) == cell_count assert len(set(cells)) == unique_count for matching_idxs in matches: comparator_idx = matching_idxs[0] for idx in matching_idxs[1:]: assert cells[idx] is cells[comparator_idx] def it_knows_its_column_count_to_help(self, column_count_fixture): table, expected_value = column_count_fixture column_count = table._column_count assert column_count == expected_value # fixtures ------------------------------------------------------- @pytest.fixture def add_column_fixture(self): snippets = snippet_seq('add-row-col') tbl = parse_xml(snippets[0]) table = Table(tbl, None) width = Inches(1.5) expected_xml = snippets[2] return table, width, expected_xml @pytest.fixture def add_row_fixture(self): snippets = snippet_seq('add-row-col') tbl = parse_xml(snippets[0]) table = Table(tbl, None) expected_xml = snippets[1] return table, expected_xml @pytest.fixture(params=[ ('w:tbl/w:tblPr', None), ('w:tbl/w:tblPr/w:jc{w:val=center}', WD_TABLE_ALIGNMENT.CENTER), ('w:tbl/w:tblPr/w:jc{w:val=right}', WD_TABLE_ALIGNMENT.RIGHT), ('w:tbl/w:tblPr/w:jc{w:val=left}', WD_TABLE_ALIGNMENT.LEFT), ]) def alignment_get_fixture(self, request): tbl_cxml, expected_value = request.param table = Table(element(tbl_cxml), None) return table, expected_value @pytest.fixture(params=[ ('w:tbl/w:tblPr', WD_TABLE_ALIGNMENT.LEFT, 'w:tbl/w:tblPr/w:jc{w:val=left}'), ('w:tbl/w:tblPr/w:jc{w:val=left}', WD_TABLE_ALIGNMENT.RIGHT, 'w:tbl/w:tblPr/w:jc{w:val=right}'), ('w:tbl/w:tblPr/w:jc{w:val=right}', None, 'w:tbl/w:tblPr'), ]) def alignment_set_fixture(self, request): tbl_cxml, new_value, expected_tbl_cxml = request.param table = Table(element(tbl_cxml), None) expected_xml = xml(expected_tbl_cxml) return table, new_value, expected_xml @pytest.fixture(params=[ ('w:tbl/w:tblPr', True), ('w:tbl/w:tblPr/w:tblLayout', True), ('w:tbl/w:tblPr/w:tblLayout{w:type=autofit}', True), ('w:tbl/w:tblPr/w:tblLayout{w:type=fixed}', False), ]) def autofit_get_fixture(self, request): tbl_cxml, expected_autofit = request.param table = Table(element(tbl_cxml), None) return table, expected_autofit @pytest.fixture(params=[ ('w:tbl/w:tblPr', True, 'w:tbl/w:tblPr/w:tblLayout{w:type=autofit}'), ('w:tbl/w:tblPr', False, 'w:tbl/w:tblPr/w:tblLayout{w:type=fixed}'), ('w:tbl/w:tblPr', None, 'w:tbl/w:tblPr/w:tblLayout{w:type=fixed}'), ('w:tbl/w:tblPr/w:tblLayout{w:type=fixed}', True, 'w:tbl/w:tblPr/w:tblLayout{w:type=autofit}'), ('w:tbl/w:tblPr/w:tblLayout{w:type=autofit}', False, 'w:tbl/w:tblPr/w:tblLayout{w:type=fixed}'), ]) def autofit_set_fixture(self, request): tbl_cxml, new_value, expected_tbl_cxml = request.param table = Table(element(tbl_cxml), None) expected_xml = xml(expected_tbl_cxml) return table, new_value, expected_xml @pytest.fixture(params=[ (0, 9, 9, ()), (1, 9, 8, ((0, 1),)), (2, 9, 8, ((1, 4),)), (3, 9, 6, ((0, 1, 3, 4),)), (4, 9, 4, ((0, 1), (3, 6), (4, 5, 7, 8))), ]) def cells_fixture(self, request): snippet_idx, cell_count, unique_count, matches = request.param tbl_xml = snippet_seq('tbl-cells')[snippet_idx] table = Table(parse_xml(tbl_xml), None) return table, cell_count, unique_count, matches @pytest.fixture def col_cells_fixture(self, _cells_, _column_count_): table = Table(None, None) _cells_.return_value = [0, 1, 2, 3, 4, 5, 6, 7, 8] _column_count_.return_value = 3 column_idx = 1 expected_cells = [1, 4, 7] return table, column_idx, expected_cells @pytest.fixture def column_count_fixture(self): tbl_cxml = 'w:tbl/w:tblGrid/(w:gridCol,w:gridCol,w:gridCol)' expected_value = 3 table = Table(element(tbl_cxml), None) return table, expected_value @pytest.fixture(params=[ ('w:tbl/w:tblPr', None), ('w:tbl/w:tblPr/w:bidiVisual', WD_TABLE_DIRECTION.RTL), ('w:tbl/w:tblPr/w:bidiVisual{w:val=0}', WD_TABLE_DIRECTION.LTR), ('w:tbl/w:tblPr/w:bidiVisual{w:val=on}', WD_TABLE_DIRECTION.RTL), ]) def direction_get_fixture(self, request): tbl_cxml, expected_value = request.param table = Table(element(tbl_cxml), None) return table, expected_value @pytest.fixture(params=[ ('w:tbl/w:tblPr', WD_TABLE_DIRECTION.RTL, 'w:tbl/w:tblPr/w:bidiVisual'), ('w:tbl/w:tblPr/w:bidiVisual', WD_TABLE_DIRECTION.LTR, 'w:tbl/w:tblPr/w:bidiVisual{w:val=0}'), ('w:tbl/w:tblPr/w:bidiVisual{w:val=0}', WD_TABLE_DIRECTION.RTL, 'w:tbl/w:tblPr/w:bidiVisual'), ('w:tbl/w:tblPr/w:bidiVisual{w:val=1}', None, 'w:tbl/w:tblPr'), ]) def direction_set_fixture(self, request): tbl_cxml, new_value, expected_cxml = request.param table = Table(element(tbl_cxml), None) expected_xml = xml(expected_cxml) return table, new_value, expected_xml @pytest.fixture def row_cells_fixture(self, _cells_, _column_count_): table = Table(None, None) _cells_.return_value = [0, 1, 2, 3, 4, 5, 6, 7, 8] _column_count_.return_value = 3 row_idx = 1 expected_cells = [3, 4, 5] return table, row_idx, expected_cells @pytest.fixture def style_get_fixture(self, part_prop_): style_id = 'Barbaz' tbl_cxml = 'w:tbl/w:tblPr/w:tblStyle{w:val=%s}' % style_id table = Table(element(tbl_cxml), None) style_ = part_prop_.return_value.get_style.return_value return table, style_id, style_ @pytest.fixture(params=[ ('w:tbl/w:tblPr', 'Tbl A', 'TblA', 'w:tbl/w:tblPr/w:tblStyle{w:val=TblA}'), ('w:tbl/w:tblPr/w:tblStyle{w:val=TblA}', 'Tbl B', 'TblB', 'w:tbl/w:tblPr/w:tblStyle{w:val=TblB}'), ('w:tbl/w:tblPr/w:tblStyle{w:val=TblB}', None, None, 'w:tbl/w:tblPr'), ]) def style_set_fixture(self, request, part_prop_): tbl_cxml, value, style_id, expected_cxml = request.param table = Table(element(tbl_cxml), None) part_prop_.return_value.get_style_id.return_value = style_id expected_xml = xml(expected_cxml) return table, value, expected_xml @pytest.fixture def table_fixture(self): table = Table(None, None) return table # fixture components --------------------------------------------- @pytest.fixture def _cells_(self, request): return property_mock(request, Table, '_cells') @pytest.fixture def _column_count_(self, request): return property_mock(request, Table, '_column_count') @pytest.fixture def document_part_(self, request): return instance_mock(request, DocumentPart) @pytest.fixture def part_prop_(self, request, document_part_): return property_mock( request, Table, 'part', return_value=document_part_ ) @pytest.fixture def table(self): tbl = _tbl_bldr(rows=2, cols=2).element table = Table(tbl, None) return table class Describe_Cell(object): def it_knows_what_text_it_contains(self, text_get_fixture): cell, expected_text = text_get_fixture text = cell.text assert text == expected_text def it_can_replace_its_content_with_a_string_of_text( self, text_set_fixture): cell, text, expected_xml = text_set_fixture cell.text = text assert cell._tc.xml == expected_xml def it_knows_its_width_in_EMU(self, width_get_fixture): cell, expected_width = width_get_fixture assert cell.width == expected_width def it_can_change_its_width(self, width_set_fixture): cell, value, expected_xml = width_set_fixture cell.width = value assert cell.width == value assert cell._tc.xml == expected_xml def it_provides_access_to_the_paragraphs_it_contains( self, paragraphs_fixture): cell = paragraphs_fixture paragraphs = cell.paragraphs assert len(paragraphs) == 2 count = 0 for idx, paragraph in enumerate(paragraphs): assert isinstance(paragraph, Paragraph) assert paragraph is paragraphs[idx] count += 1 assert count == 2 def it_provides_access_to_the_tables_it_contains(self, tables_fixture): # test len(), iterable, and indexed access cell, expected_count = tables_fixture tables = cell.tables assert len(tables) == expected_count count = 0 for idx, table in enumerate(tables): assert isinstance(table, Table) assert tables[idx] is table count += 1 assert count == expected_count def it_can_add_a_paragraph(self, add_paragraph_fixture): cell, expected_xml = add_paragraph_fixture p = cell.add_paragraph() assert cell._tc.xml == expected_xml assert isinstance(p, Paragraph) def it_can_add_a_table(self, add_table_fixture): cell, expected_xml = add_table_fixture table = cell.add_table(rows=2, cols=2) assert cell._element.xml == expected_xml assert isinstance(table, Table) def it_can_merge_itself_with_other_cells(self, merge_fixture): cell, other_cell, merged_tc_ = merge_fixture merged_cell = cell.merge(other_cell) cell._tc.merge.assert_called_once_with(other_cell._tc) assert isinstance(merged_cell, _Cell) assert merged_cell._tc is merged_tc_ assert merged_cell._parent is cell._parent # fixtures ------------------------------------------------------- @pytest.fixture(params=[ ('w:tc', 'w:tc/w:p'), ('w:tc/w:p', 'w:tc/(w:p, w:p)'), ('w:tc/w:tbl', 'w:tc/(w:tbl, w:p)'), ]) def add_paragraph_fixture(self, request): tc_cxml, after_tc_cxml = request.param cell = _Cell(element(tc_cxml), None) expected_xml = xml(after_tc_cxml) return cell, expected_xml @pytest.fixture def add_table_fixture(self, request): cell = _Cell(element('w:tc/w:p'), None) expected_xml = snippet_seq('new-tbl')[1] return cell, expected_xml @pytest.fixture def merge_fixture(self, tc_, tc_2_, parent_, merged_tc_): cell, other_cell = _Cell(tc_, parent_), _Cell(tc_2_, parent_) tc_.merge.return_value = merged_tc_ return cell, other_cell, merged_tc_ @pytest.fixture def paragraphs_fixture(self): return _Cell(element('w:tc/(w:p, w:p)'), None) @pytest.fixture(params=[ ('w:tc', 0), ('w:tc/w:tbl', 1), ('w:tc/(w:tbl,w:tbl)', 2), ('w:tc/(w:p,w:tbl)', 1), ('w:tc/(w:tbl,w:tbl,w:p)', 2), ]) def tables_fixture(self, request): cell_cxml, expected_count = request.param cell = _Cell(element(cell_cxml), None) return cell, expected_count @pytest.fixture(params=[ ('w:tc', ''), ('w:tc/w:p/w:r/w:t"foobar"', 'foobar'), ('w:tc/(w:p/w:r/w:t"foo",w:p/w:r/w:t"bar")', 'foo\nbar'), ('w:tc/(w:tcPr,w:p/w:r/w:t"foobar")', 'foobar'), ('w:tc/w:p/w:r/(w:t"fo",w:tab,w:t"ob",w:br,w:t"ar",w:br)', 'fo\tob\nar\n'), ]) def text_get_fixture(self, request): tc_cxml, expected_text = request.param cell = _Cell(element(tc_cxml), None) return cell, expected_text @pytest.fixture(params=[ ('w:tc/w:p', 'foobar', 'w:tc/w:p/w:r/w:t"foobar"'), ('w:tc/w:p', 'fo\tob\rar\n', 'w:tc/w:p/w:r/(w:t"fo",w:tab,w:t"ob",w:br,w:t"ar",w:br)'), ('w:tc/(w:tcPr, w:p, w:tbl, w:p)', 'foobar', 'w:tc/(w:tcPr, w:p/w:r/w:t"foobar")'), ]) def text_set_fixture(self, request): tc_cxml, new_text, expected_cxml = request.param cell = _Cell(element(tc_cxml), None) expected_xml = xml(expected_cxml) return cell, new_text, expected_xml @pytest.fixture(params=[ ('w:tc', None), ('w:tc/w:tcPr', None), ('w:tc/w:tcPr/w:tcW{w:w=25%,w:type=pct}', None), ('w:tc/w:tcPr/w:tcW{w:w=1440,w:type=dxa}', 914400), ]) def width_get_fixture(self, request): tc_cxml, expected_width = request.param cell = _Cell(element(tc_cxml), None) return cell, expected_width @pytest.fixture(params=[ ('w:tc', Inches(1), 'w:tc/w:tcPr/w:tcW{w:w=1440,w:type=dxa}'), ('w:tc/w:tcPr/w:tcW{w:w=25%,w:type=pct}', Inches(2), 'w:tc/w:tcPr/w:tcW{w:w=2880,w:type=dxa}'), ]) def width_set_fixture(self, request): tc_cxml, new_value, expected_cxml = request.param cell = _Cell(element(tc_cxml), None) expected_xml = xml(expected_cxml) return cell, new_value, expected_xml # fixture components --------------------------------------------- @pytest.fixture def merged_tc_(self, request): return instance_mock(request, CT_Tc) @pytest.fixture def parent_(self, request): return instance_mock(request, Table) @pytest.fixture def tc_(self, request): return instance_mock(request, CT_Tc) @pytest.fixture def tc_2_(self, request): return instance_mock(request, CT_Tc) class Describe_Column(object): def it_provides_access_to_its_cells(self, cells_fixture): column, column_idx, expected_cells = cells_fixture cells = column.cells column.table.column_cells.assert_called_once_with(column_idx) assert cells == expected_cells def it_provides_access_to_the_table_it_belongs_to(self, table_fixture): column, table_ = table_fixture assert column.table is table_ def it_knows_its_width_in_EMU(self, width_get_fixture): column, expected_width = width_get_fixture assert column.width == expected_width def it_can_change_its_width(self, width_set_fixture): column, value, expected_xml = width_set_fixture column.width = value assert column.width == value assert column._gridCol.xml == expected_xml def it_knows_its_index_in_table_to_help(self, index_fixture): column, expected_idx = index_fixture assert column._index == expected_idx # fixtures ------------------------------------------------------- @pytest.fixture def cells_fixture(self, _index_, table_prop_, table_): column = _Column(None, None) _index_.return_value = column_idx = 4 expected_cells = (3, 2, 1) table_.column_cells.return_value = list(expected_cells) return column, column_idx, expected_cells @pytest.fixture def index_fixture(self): tbl = element('w:tbl/w:tblGrid/(w:gridCol,w:gridCol,w:gridCol)') gridCol, expected_idx = tbl.tblGrid[1], 1 column = _Column(gridCol, None) return column, expected_idx @pytest.fixture def table_fixture(self, parent_, table_): column = _Column(None, parent_) parent_.table = table_ return column, table_ @pytest.fixture(params=[ ('w:gridCol{w:w=4242}', 2693670), ('w:gridCol{w:w=1440}', 914400), ('w:gridCol{w:w=2.54cm}', 914400), ('w:gridCol{w:w=54mm}', 1944000), ('w:gridCol{w:w=12.5pt}', 158750), ('w:gridCol', None), ]) def width_get_fixture(self, request): gridCol_cxml, expected_width = request.param column = _Column(element(gridCol_cxml), None) return column, expected_width @pytest.fixture(params=[ ('w:gridCol', 914400, 'w:gridCol{w:w=1440}'), ('w:gridCol{w:w=4242}', 457200, 'w:gridCol{w:w=720}'), ('w:gridCol{w:w=4242}', None, 'w:gridCol'), ('w:gridCol', None, 'w:gridCol'), ]) def width_set_fixture(self, request): gridCol_cxml, new_value, expected_cxml = request.param column = _Column(element(gridCol_cxml), None) expected_xml = xml(expected_cxml) return column, new_value, expected_xml # fixture components --------------------------------------------- @pytest.fixture def _index_(self, request): return property_mock(request, _Column, '_index') @pytest.fixture def parent_(self, request): return instance_mock(request, Table) @pytest.fixture def table_(self, request): return instance_mock(request, Table) @pytest.fixture def table_prop_(self, request, table_): return property_mock(request, _Column, 'table', return_value=table_) class Describe_Columns(object): def it_knows_how_many_columns_it_contains(self, columns_fixture): columns, column_count = columns_fixture assert len(columns) == column_count def it_can_interate_over_its__Column_instances(self, columns_fixture): columns, column_count = columns_fixture actual_count = 0 for column in columns: assert isinstance(column, _Column) actual_count += 1 assert actual_count == column_count def it_provides_indexed_access_to_columns(self, columns_fixture): columns, column_count = columns_fixture for idx in range(-column_count, column_count): column = columns[idx] assert isinstance(column, _Column) def it_raises_on_indexed_access_out_of_range(self, columns_fixture): columns, column_count = columns_fixture too_low = -1 - column_count too_high = column_count with pytest.raises(IndexError): columns[too_low] with pytest.raises(IndexError): columns[too_high] def it_provides_access_to_the_table_it_belongs_to(self, table_fixture): columns, table_ = table_fixture assert columns.table is table_ # fixtures ------------------------------------------------------- @pytest.fixture def columns_fixture(self): column_count = 2 tbl = _tbl_bldr(rows=2, cols=column_count).element columns = _Columns(tbl, None) return columns, column_count @pytest.fixture def table_fixture(self, table_): columns = _Columns(None, table_) table_.table = table_ return columns, table_ # fixture components --------------------------------------------- @pytest.fixture def table_(self, request): return instance_mock(request, Table) class Describe_Row(object): def it_provides_access_to_its_cells(self, cells_fixture): row, row_idx, expected_cells = cells_fixture cells = row.cells row.table.row_cells.assert_called_once_with(row_idx) assert cells == expected_cells def it_provides_access_to_the_table_it_belongs_to(self, table_fixture): row, table_ = table_fixture assert row.table is table_ def it_knows_its_index_in_table_to_help(self, idx_fixture): row, expected_idx = idx_fixture assert row._index == expected_idx # fixtures ------------------------------------------------------- @pytest.fixture def cells_fixture(self, _index_, table_prop_, table_): row = _Row(None, None) _index_.return_value = row_idx = 6 expected_cells = (1, 2, 3) table_.row_cells.return_value = list(expected_cells) return row, row_idx, expected_cells @pytest.fixture def idx_fixture(self): tbl = element('w:tbl/(w:tr,w:tr,w:tr)') tr, expected_idx = tbl[1], 1 row = _Row(tr, None) return row, expected_idx @pytest.fixture def table_fixture(self, parent_, table_): row = _Row(None, parent_) parent_.table = table_ return row, table_ # fixture components --------------------------------------------- @pytest.fixture def _index_(self, request): return property_mock(request, _Row, '_index') @pytest.fixture def parent_(self, request): return instance_mock(request, Table) @pytest.fixture def table_(self, request): return instance_mock(request, Table) @pytest.fixture def table_prop_(self, request, table_): return property_mock(request, _Row, 'table', return_value=table_) class Describe_Rows(object): def it_knows_how_many_rows_it_contains(self, rows_fixture): rows, row_count = rows_fixture assert len(rows) == row_count def it_can_iterate_over_its__Row_instances(self, rows_fixture): rows, row_count = rows_fixture actual_count = 0 for row in rows: assert isinstance(row, _Row) actual_count += 1 assert actual_count == row_count def it_provides_indexed_access_to_rows(self, rows_fixture): rows, row_count = rows_fixture for idx in range(-row_count, row_count): row = rows[idx] assert isinstance(row, _Row) def it_provides_sliced_access_to_rows(self, slice_fixture): rows, start, end, expected_count = slice_fixture slice_of_rows = rows[start:end] assert len(slice_of_rows) == expected_count tr_lst = rows._tbl.tr_lst for idx, row in enumerate(slice_of_rows): assert tr_lst.index(row._tr) == start + idx assert isinstance(row, _Row) def it_raises_on_indexed_access_out_of_range(self, rows_fixture): rows, row_count = rows_fixture with pytest.raises(IndexError): too_low = -1 - row_count rows[too_low] with pytest.raises(IndexError): too_high = row_count rows[too_high] def it_provides_access_to_the_table_it_belongs_to(self, table_fixture): rows, table_ = table_fixture assert rows.table is table_ # fixtures ------------------------------------------------------- @pytest.fixture def rows_fixture(self): row_count = 2 tbl = _tbl_bldr(rows=row_count, cols=2).element rows = _Rows(tbl, None) return rows, row_count @pytest.fixture(params=[ (3, 1, 3, 2), (3, 0, -1, 2), ]) def slice_fixture(self, request): row_count, start, end, expected_count = request.param tbl = _tbl_bldr(rows=row_count, cols=2).element rows = _Rows(tbl, None) return rows, start, end, expected_count @pytest.fixture def table_fixture(self, table_): rows = _Rows(None, table_) table_.table = table_ return rows, table_ # fixture components --------------------------------------------- @pytest.fixture def table_(self, request): return instance_mock(request, Table) # fixtures ----------------------------------------------------------- def _tbl_bldr(rows, cols): tblGrid_bldr = a_tblGrid() for i in range(cols): tblGrid_bldr.with_child(a_gridCol()) tbl_bldr = a_tbl().with_nsdecls().with_child(tblGrid_bldr) for i in range(rows): tr_bldr = _tr_bldr(cols) tbl_bldr.with_child(tr_bldr) return tbl_bldr def _tc_bldr(): return a_tc().with_child(a_p()) def _tr_bldr(cols): tr_bldr = a_tr() for i in range(cols): tc_bldr = _tc_bldr() tr_bldr.with_child(tc_bldr) return tr_bldr