# encoding: utf-8

"""Unit-test suite for `pptx.table` module."""

import pytest

from pptx.dml.fill import FillFormat
from pptx.dml.border import BorderFormat
from pptx.enum.text import MSO_ANCHOR
from pptx.oxml.ns import qn
from pptx.oxml.table import CT_Table, CT_TableCell, TcRange
from pptx.shapes.graphfrm import GraphicFrame
from pptx.table import (
    _Cell,
    _CellCollection,
    _Column,
    _ColumnCollection,
    _Row,
    _RowCollection,
    Table,
)
from pptx.text.text import TextFrame
from pptx.util import Inches, Length, Pt

from .unitutil.cxml import element, xml
from .unitutil.mock import call, class_mock, instance_mock, property_mock


class DescribeTable(object):
    """Unit-test suite for `pptx.table.Table` objects."""

    def it_provides_access_to_its_cells(self, tbl_, tc_, _Cell_, cell_):
        row_idx, col_idx = 4, 2
        tbl_.tc.return_value = tc_
        _Cell_.return_value = cell_
        table = Table(tbl_, None)

        cell = table.cell(row_idx, col_idx)

        tbl_.tc.assert_called_once_with(row_idx, col_idx)
        _Cell_.assert_called_once_with(tc_, table)
        assert cell is cell_

    def it_provides_access_to_its_columns(self, request):
        columns_ = instance_mock(request, _ColumnCollection)
        _ColumnCollection_ = class_mock(
            request, "pptx.table._ColumnCollection", return_value=columns_
        )
        tbl = element("a:tbl")
        table = Table(tbl, None)

        columns = table.columns

        _ColumnCollection_.assert_called_once_with(tbl, table)
        assert columns is columns_

    def it_can_iterate_its_grid_cells(self, request, _Cell_):
        tbl = element("a:tbl/(a:tr/(a:tc,a:tc),a:tr/(a:tc,a:tc))")
        expected_tcs = tbl.xpath(".//a:tc")
        expected_cells = _Cell_.side_effect = [
            instance_mock(request, _Cell, name="cell%d" % idx) for idx in range(4)
        ]
        table = Table(tbl, None)

        cells = list(table.iter_cells())

        assert cells == expected_cells
        assert _Cell_.call_args_list == [call(tc, table) for tc in expected_tcs]

    def it_provides_access_to_its_rows(self, request):
        rows_ = instance_mock(request, _RowCollection)
        _RowCollection_ = class_mock(
            request, "pptx.table._RowCollection", return_value=rows_
        )
        tbl = element("a:tbl")
        table = Table(tbl, None)

        rows = table.rows

        _RowCollection_.assert_called_once_with(tbl, table)
        assert rows is rows_

    def it_updates_graphic_frame_width_on_width_change(self, dx_fixture):
        table, expected_width = dx_fixture
        table.notify_width_changed()
        assert table._graphic_frame.width == expected_width

    def it_updates_graphic_frame_height_on_height_change(self, dy_fixture):
        table, expected_height = dy_fixture
        table.notify_height_changed()
        assert table._graphic_frame.height == expected_height

    # fixtures -------------------------------------------------------

    @pytest.fixture
    def dx_fixture(self, graphic_frame_):
        tbl_cxml = "a:tbl/a:tblGrid/(a:gridCol{w=111},a:gridCol{w=222})"
        table = Table(element(tbl_cxml), graphic_frame_)
        expected_width = 333
        return table, expected_width

    @pytest.fixture
    def dy_fixture(self, graphic_frame_):
        tbl_cxml = "a:tbl/(a:tr{h=100},a:tr{h=200})"
        table = Table(element(tbl_cxml), graphic_frame_)
        expected_height = 300
        return table, expected_height

    # fixture components ---------------------------------------------

    @pytest.fixture
    def _Cell_(self, request):
        return class_mock(request, "pptx.table._Cell")

    @pytest.fixture
    def cell_(self, request):
        return instance_mock(request, _Cell)

    @pytest.fixture
    def graphic_frame_(self, request):
        return instance_mock(request, GraphicFrame)

    @pytest.fixture
    def tbl_(self, request):
        return instance_mock(request, CT_Table)

    @pytest.fixture
    def tc_(self, request):
        return instance_mock(request, CT_TableCell)


class DescribeTableBooleanProperties(object):
    def it_knows_its_boolean_property_settings(self, boolprop_get_fixture):
        table, boolprop_name, expected_value = boolprop_get_fixture
        boolprop_value = getattr(table, boolprop_name)
        assert boolprop_value is expected_value

    def it_can_change_its_boolean_property_settings(self, boolprop_set_fixture):
        table, boolprop_name, new_value, expected_xml = boolprop_set_fixture
        setattr(table, boolprop_name, new_value)
        assert table._tbl.xml == expected_xml

    # fixtures -------------------------------------------------------

    @pytest.fixture(
        params=[
            ("a:tbl", "first_row", False),
            ("a:tbl/a:tblPr", "first_row", False),
            ("a:tbl/a:tblPr{firstRow=1}", "first_row", True),
            ("a:tbl/a:tblPr{firstRow=0}", "first_row", False),
            ("a:tbl/a:tblPr{firstRow=true}", "first_row", True),
            ("a:tbl/a:tblPr{firstRow=false}", "first_row", False),
            ("a:tbl/a:tblPr{firstCol=1}", "first_col", True),
            ("a:tbl/a:tblPr{lastRow=0}", "last_row", False),
            ("a:tbl/a:tblPr{lastCol=true}", "last_col", True),
            ("a:tbl/a:tblPr{bandRow=false}", "horz_banding", False),
            ("a:tbl/a:tblPr", "vert_banding", False),
        ]
    )
    def boolprop_get_fixture(self, request):
        tbl_cxml, boolprop_name, expected_value = request.param
        table = Table(element(tbl_cxml), None)
        return table, boolprop_name, expected_value

    @pytest.fixture(
        params=[
            ("a:tbl", "first_row", True, "a:tbl/a:tblPr{firstRow=1}"),
            ("a:tbl", "first_row", False, "a:tbl/a:tblPr"),
            ("a:tbl/a:tblPr", "first_row", True, "a:tbl/a:tblPr{firstRow=1}"),
            ("a:tbl/a:tblPr", "first_row", False, "a:tbl/a:tblPr"),
            (
                "a:tbl/a:tblPr{firstRow=true}",
                "first_row",
                True,
                "a:tbl/a:tblPr{firstRow=1}",
            ),
            ("a:tbl/a:tblPr{firstRow=false}", "first_row", False, "a:tbl/a:tblPr"),
            (
                "a:tbl/a:tblPr{bandRow=1}",
                "first_row",
                True,
                "a:tbl/a:tblPr{bandRow=1,firstRow=1}",
            ),
            ("a:tbl", "first_col", True, "a:tbl/a:tblPr{firstCol=1}"),
            ("a:tbl", "last_row", True, "a:tbl/a:tblPr{lastRow=1}"),
            ("a:tbl", "last_col", True, "a:tbl/a:tblPr{lastCol=1}"),
            ("a:tbl", "horz_banding", True, "a:tbl/a:tblPr{bandRow=1}"),
            ("a:tbl", "vert_banding", True, "a:tbl/a:tblPr{bandCol=1}"),
        ]
    )
    def boolprop_set_fixture(self, request):
        tbl_cxml, boolprop_name, new_value, expected_tbl_cxml = request.param
        table = Table(element(tbl_cxml), None)
        expected_xml = xml(expected_tbl_cxml)
        return table, boolprop_name, new_value, expected_xml


class Describe_Cell(object):
    """Unit-test suite for `pptx.table._Cell` object."""

    def it_is_equal_to_other_instance_having_same_tc(self):
        tc = element("a:tc")
        other_tc = element("a:tc")
        cell = _Cell(tc, None)
        cell_with_same_tc = _Cell(tc, None)
        cell_with_other_tc = _Cell(other_tc, None)

        assert cell == cell_with_same_tc
        assert cell != cell_with_other_tc

    def it_has_a_fill(self, fill_fixture):
        cell = fill_fixture
        assert isinstance(cell.fill, FillFormat)

    def it_knows_whether_it_is_merge_origin_cell(self, origin_fixture):
        tc, expected_value = origin_fixture
        cell = _Cell(tc, None)

        is_merge_origin = cell.is_merge_origin

        assert is_merge_origin is expected_value

    def it_knows_whether_it_is_spanned(self, spanned_fixture):
        tc, expected_value = spanned_fixture
        cell = _Cell(tc, None)

        is_spanned = cell.is_spanned

        assert is_spanned is expected_value

    def it_knows_its_margin_settings(self, margin_get_fixture):
        cell, margin_prop_name, expected_value = margin_get_fixture
        margin_value = getattr(cell, margin_prop_name)
        assert margin_value == expected_value

    def it_can_change_its_margin_settings(self, margin_set_fixture):
        cell, margin_prop_name, new_value, expected_xml = margin_set_fixture
        setattr(cell, margin_prop_name, new_value)
        assert cell._tc.xml == expected_xml

    def it_raises_on_margin_assigned_other_than_int_or_None(
        self, margin_raises_fixture
    ):
        cell, margin_attr_name, val_of_invalid_type = margin_raises_fixture
        with pytest.raises(TypeError):
            setattr(cell, margin_attr_name, val_of_invalid_type)

    def it_can_merge_a_range_of_cells(self, TcRange_, tc_range_):
        tbl = element("a:tbl/(a:tr/(a:tc,a:tc),a:tr/(a:tc,a:tc))")
        tc, other_tc = tbl.tc(0, 0), tbl.tc(1, 1)
        TcRange_.return_value = tc_range_
        tc_range_.contains_merged_cell = False
        tc_range_.dimensions = 2, 2

        def tcs(*rowcols):
            return (tbl.tc(*rowcol) for rowcol in rowcols)

        tc_range_.iter_top_row_tcs.return_value = tcs((0, 0), (0, 1))
        tc_range_.iter_left_col_tcs.return_value = tcs((0, 0), (1, 0))
        tc_range_.iter_except_left_col_tcs.return_value = tcs((0, 1), (1, 1))
        tc_range_.iter_except_top_row_tcs.return_value = tcs((1, 0), (1, 1))
        expected_xml = xml(
            "a:tbl/(a:tr/(a:tc{gridSpan=2,rowSpan=2},a:tc{rowSpan=2,hMerge=1"
            "}),a:tr/(a:tc{gridSpan=2,vMerge=1},a:tc{hMerge=1,vMerge=1}))"
        )
        cell, other_cell = _Cell(tc, None), _Cell(other_tc, None)

        cell.merge(other_cell)

        TcRange_.assert_called_once_with(tc, other_tc)
        tc_range_.move_content_to_origin.assert_called_once_with()
        assert tbl.xml == expected_xml

    def but_it_raises_when_cells_are_from_different_tables(self, TcRange_, tc_range_):
        TcRange_.return_value = tc_range_
        tc_range_.in_same_table = False
        cell, other_cell = _Cell(None, None), _Cell(None, None)

        with pytest.raises(ValueError) as e:
            cell.merge(other_cell)
        assert "different table" in str(e.value)

    def and_it_raises_when_range_contains_merged_cell(self, TcRange_, tc_range_):
        TcRange_.return_value = tc_range_
        tc_range_.contains_merged_cell = True
        cell, other_cell = _Cell(None, None), _Cell(None, None)

        with pytest.raises(ValueError) as e:
            cell.merge(other_cell)
        assert "contains one or more merged cells" in str(e.value)

    def it_knows_how_many_rows_the_merge_spans(self, height_fixture):
        tc, expected_value = height_fixture
        cell = _Cell(tc, None)
        span_height = cell.span_height
        assert span_height == expected_value

    def it_knows_how_many_columns_the_merge_spans(self, width_fixture):
        tc, expected_value = width_fixture
        cell = _Cell(tc, None)
        span_width = cell.span_width
        assert span_width == expected_value

    def it_can_split_a_merged_cell(self, split_fixture):
        origin_tc, range_tcs = split_fixture
        cell = _Cell(origin_tc, None)

        cell.split()

        assert all(tc.gridSpan == 1 for tc in range_tcs)
        assert all(tc.rowSpan == 1 for tc in range_tcs)
        assert all(not tc.hMerge for tc in range_tcs)
        assert all(not tc.vMerge for tc in range_tcs)

    def but_it_raises_when_cell_to_be_split_is_not_merge_origin(self):
        tc = element("a:tbl/a:tr/a:tc").xpath("//a:tc")[0]
        cell = _Cell(tc, None)

        with pytest.raises(ValueError) as e:
            cell.split()
        assert "not a merge-origin cell" in str(e.value)

    def it_knows_what_text_it_contains(self, text_frame_prop_, text_frame_):
        text_frame_prop_.return_value = text_frame_
        text_frame_.text = "foobar"
        cell = _Cell(None, None)

        text = cell.text

        assert text == "foobar"

    def it_can_change_its_text(self, text_frame_prop_, text_frame_):
        text_frame_prop_.return_value = text_frame_
        cell = _Cell(None, None)

        cell.text = "føøbår"

        assert text_frame_.text == "føøbår"

    def it_knows_its_vertical_anchor_setting(self, anchor_get_fixture):
        cell, expected_value = anchor_get_fixture
        assert cell.vertical_anchor == expected_value

    def it_can_change_its_vertical_anchor(self, anchor_set_fixture):
        cell, new_value, expected_xml = anchor_set_fixture
        cell.vertical_anchor = new_value
        assert cell._tc.xml == expected_xml

    def it_knows_it_has_border_settings(self, border_fixture):
        cell = border_fixture
        assert isinstance(cell.border_left, BorderFormat)
        assert isinstance(cell.border_right, BorderFormat)
        assert isinstance(cell.border_top, BorderFormat)
        assert isinstance(cell.border_bottom, BorderFormat)
        assert isinstance(cell.border_tl_br, BorderFormat)
        assert isinstance(cell.border_bl_tr, BorderFormat)
        
    # fixtures -------------------------------------------------------

    @pytest.fixture(
        params=[
            ("a:tc", None),
            ("a:tc/a:tcPr", None),
            ("a:tc/a:tcPr{anchor=t}", MSO_ANCHOR.TOP),
            ("a:tc/a:tcPr{anchor=ctr}", MSO_ANCHOR.MIDDLE),
            ("a:tc/a:tcPr{anchor=b}", MSO_ANCHOR.BOTTOM),
        ]
    )
    def anchor_get_fixture(self, request):
        tc_cxml, expected_value = request.param
        cell = _Cell(element(tc_cxml), None)
        return cell, expected_value

    @pytest.fixture(
        params=[
            ("a:tc", None, "a:tc"),
            ("a:tc", MSO_ANCHOR.TOP, "a:tc/a:tcPr{anchor=t}"),
            ("a:tc", MSO_ANCHOR.MIDDLE, "a:tc/a:tcPr{anchor=ctr}"),
            ("a:tc", MSO_ANCHOR.BOTTOM, "a:tc/a:tcPr{anchor=b}"),
            ("a:tc/a:tcPr{anchor=t}", MSO_ANCHOR.MIDDLE, "a:tc/a:tcPr{anchor=ctr}"),
            ("a:tc/a:tcPr{anchor=ctr}", None, "a:tc/a:tcPr"),
        ]
    )
    def anchor_set_fixture(self, request):
        tc_cxml, new_value, expected_tc_cxml = request.param
        cell = _Cell(element(tc_cxml), None)
        expected_xml = xml(expected_tc_cxml)
        return cell, new_value, expected_xml

    @pytest.fixture
    def fill_fixture(self, cell):
        return cell

    @pytest.fixture
    def border_fixture(self, cell):
        return cell

    @pytest.fixture(
        params=[("a:tc", 1), ("a:tc{gridSpan=2}", 1), ("a:tc{rowSpan=42}", 42)]
    )
    def height_fixture(self, request):
        tc_cxml, expected_value = request.param
        tc = element(tc_cxml)
        return tc, expected_value

    @pytest.fixture(
        params=[
            ("a:tc/a:tcPr{marL=82296}", "margin_left", Inches(0.09)),
            ("a:tc/a:tcPr{marR=73152}", "margin_right", Inches(0.08)),
            ("a:tc/a:tcPr{marT=64008}", "margin_top", Inches(0.07)),
            ("a:tc/a:tcPr{marB=54864}", "margin_bottom", Inches(0.06)),
            ("a:tc", "margin_left", Inches(0.1)),
            ("a:tc/a:tcPr", "margin_right", Inches(0.1)),
            ("a:tc", "margin_top", Inches(0.05)),
            ("a:tc/a:tcPr", "margin_bottom", Inches(0.05)),
        ]
    )
    def margin_get_fixture(self, request):
        tc_cxml, margin_prop_name, expected_value = request.param
        cell = _Cell(element(tc_cxml), None)
        return cell, margin_prop_name, expected_value

    @pytest.fixture(
        params=[
            ("a:tc", "margin_left", Inches(0.08), "a:tc/a:tcPr{marL=73152}"),
            ("a:tc", "margin_right", Inches(0.08), "a:tc/a:tcPr{marR=73152}"),
            ("a:tc", "margin_top", Inches(0.08), "a:tc/a:tcPr{marT=73152}"),
            ("a:tc", "margin_bottom", Inches(0.08), "a:tc/a:tcPr{marB=73152}"),
            ("a:tc", "margin_left", None, "a:tc"),
            ("a:tc/a:tcPr{marL=42}", "margin_left", None, "a:tc/a:tcPr"),
        ]
    )
    def margin_set_fixture(self, request):
        tc_cxml, margin_prop_name, new_value, expected_tc_cxml = request.param
        cell = _Cell(element(tc_cxml), None)
        expected_xml = xml(expected_tc_cxml)
        return cell, margin_prop_name, new_value, expected_xml

    @pytest.fixture(
        params=["margin_left", "margin_right", "margin_top", "margin_bottom"]
    )
    def margin_raises_fixture(self, request):
        margin_prop_name = request.param
        cell = _Cell(element("a:tc"), None)
        val_of_invalid_type = "foobar"
        return cell, margin_prop_name, val_of_invalid_type

    @pytest.fixture(
        params=[
            ("a:tc", False),
            ("a:tc{gridSpan=1}", False),
            ("a:tc{hMerge=1}", False),
            ("a:tc{gridSpan=2,vMerge=1}", False),
            ("a:tc{gridSpan=2}", True),
            ("a:tc{rowSpan=2}", True),
            ("a:tc{gridSpan=2,rowSpan=3}", True),
        ]
    )
    def origin_fixture(self, request):
        tc_cxml, expected_value = request.param
        tc = element(tc_cxml)
        return tc, expected_value

    @pytest.fixture(
        params=[
            ("a:tc", False),
            ("a:tc{gridSpan=2}", False),
            ("a:tc{hMerge=1}", True),
            ("a:tc{gridSpan=2,vMerge=1}", True),
            ("a:tc{rowSpan=2,hMerge=true}", True),
            ("a:tc{gridSpan=2,rowSpan=3}", False),
        ]
    )
    def spanned_fixture(self, request):
        tc_cxml, expected_value = request.param
        tc = element(tc_cxml)
        return tc, expected_value

    @pytest.fixture(
        params=[
            (
                "a:tbl/(a:tr/(a:tc{gridSpan=2},a:tc{hMerge=1}),a:tr/(a:tc,a:tc))",
                0,
                [0, 1],
            ),
            (
                "a:tbl/(a:tr/(a:tc{rowSpan=2},a:tc),a:tr/(a:tc{vMerge=1},a:tc))",
                0,
                [0, 2],
            ),
            (
                "a:tbl/(a:tr/(a:tc{gridSpan=2,rowSpan=2},a:tc{hMerge=1,rowSpan=2}),"
                "a:tr/(a:tc{gridSpan=2,vMerge=1},a:tc{hMerge=1,vMerge=1}))",
                0,
                [0, 1, 2, 3],
            ),
        ]
    )
    def split_fixture(self, request):
        tbl_cxml, origin_tc_idx, range_tc_idxs = request.param
        tcs = element(tbl_cxml).xpath("//a:tc")
        origin_tc = tcs[origin_tc_idx]
        range_tcs = tuple(tcs[idx] for idx in range_tc_idxs)
        return origin_tc, range_tcs

    @pytest.fixture(
        params=[("a:tc", 1), ("a:tc{rowSpan=2}", 1), ("a:tc{gridSpan=24}", 24)]
    )
    def width_fixture(self, request):
        tc_cxml, expected_value = request.param
        tc = element(tc_cxml)
        return tc, expected_value

    # fixture components ---------------------------------------------

    @pytest.fixture
    def cell(self):
        return _Cell(element("a:tc"), None)

    @pytest.fixture
    def TcRange_(self, request):
        return class_mock(request, "pptx.table.TcRange")

    @pytest.fixture
    def tc_range_(self, request):
        return instance_mock(request, TcRange)

    @pytest.fixture
    def text_frame_(self, request):
        return instance_mock(request, TextFrame)

    @pytest.fixture
    def text_frame_prop_(self, request):
        return property_mock(request, _Cell, "text_frame")


class Describe_CellCollection(object):
    def it_knows_how_many_cells_it_contains(self, len_fixture):
        cells, expected_count = len_fixture
        assert len(cells) == expected_count

    def it_can_iterate_over_the_cells_it_contains(self, iter_fixture):
        cell_collection, _Cell_, calls, expected_cells = iter_fixture

        cells = list(cell_collection)

        assert _Cell_.call_args_list == calls
        assert cells == expected_cells

    def it_supports_indexed_access(self, _Cell_, cell_):
        tr = element("a:tr/(a:tc, a:tc, a:tc)")
        tcs = tr.xpath("//a:tc")
        _Cell_.return_value = cell_
        cell_collection = _CellCollection(tr, None)

        cell = cell_collection[1]

        _Cell_.assert_called_once_with(tcs[1], cell_collection)
        assert cell is cell_

    def it_raises_on_indexed_access_out_of_range(self):
        cells = _CellCollection(element("a:tr/a:tc"), None)
        with pytest.raises(IndexError):
            cells[-1]
        with pytest.raises(IndexError):
            cells[9]

    # fixtures -------------------------------------------------------

    @pytest.fixture(params=["a:tr", "a:tr/a:tc", "a:tr/(a:tc, a:tc, a:tc)"])
    def iter_fixture(self, request, _Cell_):
        tr_cxml = request.param
        tr = element(tr_cxml)
        tcs = tr.xpath("//a:tc")
        cell_collection = _CellCollection(tr, None)

        expected_cells = [
            instance_mock(request, _Cell, name="cell%d" % idx)
            for idx in range(len(tcs))
        ]
        _Cell_.side_effect = expected_cells
        calls = [call(tc, cell_collection) for tc in tcs]

        return cell_collection, _Cell_, calls, expected_cells

    @pytest.fixture(params=[("a:tr", 0), ("a:tr/a:tc", 1), ("a:tr/(a:tc, a:tc)", 2)])
    def len_fixture(self, request):
        tr_cxml, expected_len = request.param
        cells = _CellCollection(element(tr_cxml), None)
        return cells, expected_len

    # fixture components ---------------------------------------------

    @pytest.fixture
    def _Cell_(self, request):
        return class_mock(request, "pptx.table._Cell")

    @pytest.fixture
    def cell_(self, request):
        return instance_mock(request, _Cell)


class Describe_Column(object):
    def it_knows_its_width(self, width_get_fixture):
        column, expected_value = width_get_fixture
        width = column.width
        assert width == expected_value
        assert isinstance(width, Length)

    def it_can_change_its_width(self, width_set_fixture):
        column, new_width, expected_xml, parent_ = width_set_fixture
        column.width = new_width
        assert column._gridCol.xml == expected_xml
        parent_.notify_width_changed.assert_called_once_with()

    # fixtures -------------------------------------------------------

    @pytest.fixture(
        params=[("a:gridCol{w=914400}", Inches(1)), ("a:gridCol{w=10pt}", Pt(10))]
    )
    def width_get_fixture(self, request):
        gridCol_cxml, expected_value = request.param
        column = _Column(element(gridCol_cxml), None)
        return column, expected_value

    @pytest.fixture(
        params=[
            ("a:gridCol{w=12pt}", Inches(1), "a:gridCol{w=914400}"),
            ("a:gridCol{w=1234}", Inches(1), "a:gridCol{w=914400}"),
        ]
    )
    def width_set_fixture(self, request, parent_):
        gridCol_cxml, new_width, expected_gridCol_cxml = request.param
        column = _Column(element(gridCol_cxml), parent_)
        expected_xml = xml(expected_gridCol_cxml)
        return column, new_width, expected_xml, parent_

    # fixture components ---------------------------------------------

    @pytest.fixture
    def parent_(self, request):
        return instance_mock(request, _ColumnCollection)


class Describe_ColumnCollection(object):
    def it_knows_how_many_columns_it_contains(self, len_fixture):
        columns, expected_count = len_fixture
        assert len(columns) == expected_count

    def it_can_iterate_over_the_columns_it_contains(self, iter_fixture):
        columns, expected_gridCol_lst = iter_fixture
        count = 0
        for idx, column in enumerate(columns):
            assert isinstance(column, _Column)
            assert column._gridCol is expected_gridCol_lst[idx]
            count += 1
        assert count == len(expected_gridCol_lst)

    def it_supports_indexed_access(self, getitem_fixture):
        columns, expected_gridCol_lst = getitem_fixture
        for idx, gridCol in enumerate(expected_gridCol_lst):
            column = columns[idx]
            assert isinstance(column, _Column)
            assert column._gridCol is gridCol

    def it_raises_on_indexed_access_out_of_range(self):
        columns = _ColumnCollection(element("a:tbl/a:tblGrid/a:gridCol"), None)
        with pytest.raises(IndexError):
            columns[-1]
        with pytest.raises(IndexError):
            columns[9]

    # fixtures -------------------------------------------------------

    @pytest.fixture(
        params=[
            "a:tbl/a:tblGrid",
            "a:tbl/a:tblGrid/a:gridCol",
            "a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)",
        ]
    )
    def getitem_fixture(self, request):
        tbl_cxml = request.param
        tbl = element(tbl_cxml)
        columns = _ColumnCollection(tbl, None)
        expected_column_lst = tbl.xpath("//a:gridCol")
        return columns, expected_column_lst

    @pytest.fixture(
        params=[
            "a:tbl/a:tblGrid",
            "a:tbl/a:tblGrid/a:gridCol",
            "a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)",
        ]
    )
    def iter_fixture(self, request):
        tbl_cxml = request.param
        tbl = element(tbl_cxml)
        columns = _ColumnCollection(tbl, None)
        expected_column_lst = tbl.xpath("//a:gridCol")
        return columns, expected_column_lst

    @pytest.fixture(
        params=[
            ("a:tbl/a:tblGrid", 0),
            ("a:tbl/a:tblGrid/a:gridCol", 1),
            ("a:tbl/a:tblGrid/(a:gridCol,a:gridCol)", 2),
        ]
    )
    def len_fixture(self, request):
        tbl_cxml, expected_len = request.param
        columns = _ColumnCollection(element(tbl_cxml), None)
        return columns, expected_len


class Describe_Row(object):
    def it_knows_its_height(self, height_get_fixture):
        row, expected_value = height_get_fixture
        height = row.height
        assert height == expected_value
        assert isinstance(height, Length)

    def it_can_change_its_height(self, height_set_fixture):
        row, new_height, expected_xml, parent_ = height_set_fixture
        row.height = new_height
        assert row._tr.xml == expected_xml
        parent_.notify_height_changed.assert_called_once_with()

    def it_provides_access_to_its_cells(self, cells_fixture):
        row, _CellCollection_, cells_ = cells_fixture
        cells = row.cells
        _CellCollection_.assert_called_once_with(row._tr, row)
        assert cells is cells_

    # fixtures -------------------------------------------------------

    @pytest.fixture
    def cells_fixture(self, _CellCollection_, cells_):
        row = _Row(element("a:tr"), None)
        return row, _CellCollection_, cells_

    @pytest.fixture(params=[("a:tr{h=914400}", Inches(1)), ("a:tr{h=10pt}", Pt(10))])
    def height_get_fixture(self, request):
        tr_cxml, expected_value = request.param
        row = _Row(element(tr_cxml), None)
        return row, expected_value

    @pytest.fixture(
        params=[
            ("a:tr{h=12pt}", Inches(1), "a:tr{h=914400}"),
            ("a:tr{h=1234}", Inches(1), "a:tr{h=914400}"),
        ]
    )
    def height_set_fixture(self, request, parent_):
        tr_cxml, new_height, expected_tr_cxml = request.param
        row = _Row(element(tr_cxml), parent_)
        expected_xml = xml(expected_tr_cxml)
        return row, new_height, expected_xml, parent_

    # fixture components ---------------------------------------------

    @pytest.fixture
    def _CellCollection_(self, request, cells_):
        return class_mock(request, "pptx.table._CellCollection", return_value=cells_)

    @pytest.fixture
    def cells_(self, request):
        return instance_mock(request, _CellCollection)

    @pytest.fixture
    def parent_(self, request):
        return instance_mock(request, _RowCollection)


class Describe_RowCollection(object):
    def it_knows_how_many_rows_it_contains(self, len_fixture):
        rows, expected_count = len_fixture
        assert len(rows) == expected_count

    def it_can_iterate_over_the_rows_it_contains(self, iter_fixture):
        rows, expected_tr_lst = iter_fixture
        count = 0
        for idx, row in enumerate(rows):
            assert isinstance(row, _Row)
            assert row._tr is expected_tr_lst[idx]
            count += 1
        assert count == len(expected_tr_lst)

    def it_supports_indexed_access(self, getitem_fixture):
        rows, expected_tr_lst = getitem_fixture
        for idx, tr in enumerate(expected_tr_lst):
            row = rows[idx]
            assert isinstance(row, _Row)
            assert row._tr is tr

    def it_raises_on_indexed_access_out_of_range(self):
        rows = _RowCollection(element("a:tbl/a:tr"), None)
        with pytest.raises(IndexError):
            rows[-1]
        with pytest.raises(IndexError):
            rows[9]

    # fixtures -------------------------------------------------------

    @pytest.fixture(params=["a:tbl", "a:tbl/a:tr", "a:tbl/(a:tr, a:tr, a:tr)"])
    def getitem_fixture(self, request):
        tbl_cxml = request.param
        tbl = element(tbl_cxml)
        rows = _RowCollection(tbl, None)
        expected_row_lst = tbl.findall(qn("a:tr"))
        return rows, expected_row_lst

    @pytest.fixture(params=["a:tbl", "a:tbl/a:tr", "a:tbl/(a:tr, a:tr, a:tr)"])
    def iter_fixture(self, request):
        tbl_cxml = request.param
        tbl = element(tbl_cxml)
        rows = _RowCollection(tbl, None)
        expected_row_lst = tbl.findall(qn("a:tr"))
        return rows, expected_row_lst

    @pytest.fixture(params=[("a:tbl", 0), ("a:tbl/a:tr", 1), ("a:tbl/(a:tr, a:tr)", 2)])
    def len_fixture(self, request):
        tbl_cxml, expected_len = request.param
        rows = _RowCollection(element(tbl_cxml), None)
        return rows, expected_len

[((4728, 5322), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tbl', 'first_row', False), ('a:tbl/a:tblPr', 'first_row', False), (\n    'a:tbl/a:tblPr{firstRow=1}', 'first_row', True), (\n    'a:tbl/a:tblPr{firstRow=0}', 'first_row', False), (\n    'a:tbl/a:tblPr{firstRow=true}', 'first_row', True), (\n    'a:tbl/a:tblPr{firstRow=false}', 'first_row', False), (\n    'a:tbl/a:tblPr{firstCol=1}', 'first_col', True), (\n    'a:tbl/a:tblPr{lastRow=0}', 'last_row', False), (\n    'a:tbl/a:tblPr{lastCol=true}', 'last_col', True), (\n    'a:tbl/a:tblPr{bandRow=false}', 'horz_banding', False), (\n    'a:tbl/a:tblPr', 'vert_banding', False)]"}), "(params=[('a:tbl', 'first_row', False), ('a:tbl/a:tblPr',\n    'first_row', False), ('a:tbl/a:tblPr{firstRow=1}', 'first_row', True),\n    ('a:tbl/a:tblPr{firstRow=0}', 'first_row', False), (\n    'a:tbl/a:tblPr{firstRow=true}', 'first_row', True), (\n    'a:tbl/a:tblPr{firstRow=false}', 'first_row', False), (\n    'a:tbl/a:tblPr{firstCol=1}', 'first_col', True), (\n    'a:tbl/a:tblPr{lastRow=0}', 'last_row', False), (\n    'a:tbl/a:tblPr{lastCol=true}', 'last_col', True), (\n    'a:tbl/a:tblPr{bandRow=false}', 'horz_banding', False), (\n    'a:tbl/a:tblPr', 'vert_banding', False)])\n", (4742, 5322), False, 'import pytest\n'), ((5651, 6490), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tbl', 'first_row', True, 'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl',\n    'first_row', False, 'a:tbl/a:tblPr'), ('a:tbl/a:tblPr', 'first_row', \n    True, 'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl/a:tblPr', 'first_row', \n    False, 'a:tbl/a:tblPr'), ('a:tbl/a:tblPr{firstRow=true}', 'first_row', \n    True, 'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl/a:tblPr{firstRow=false}',\n    'first_row', False, 'a:tbl/a:tblPr'), ('a:tbl/a:tblPr{bandRow=1}',\n    'first_row', True, 'a:tbl/a:tblPr{bandRow=1,firstRow=1}'), ('a:tbl',\n    'first_col', True, 'a:tbl/a:tblPr{firstCol=1}'), ('a:tbl', 'last_row', \n    True, 'a:tbl/a:tblPr{lastRow=1}'), ('a:tbl', 'last_col', True,\n    'a:tbl/a:tblPr{lastCol=1}'), ('a:tbl', 'horz_banding', True,\n    'a:tbl/a:tblPr{bandRow=1}'), ('a:tbl', 'vert_banding', True,\n    'a:tbl/a:tblPr{bandCol=1}')]"}), "(params=[('a:tbl', 'first_row', True,\n    'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl', 'first_row', False,\n    'a:tbl/a:tblPr'), ('a:tbl/a:tblPr', 'first_row', True,\n    'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl/a:tblPr', 'first_row', False,\n    'a:tbl/a:tblPr'), ('a:tbl/a:tblPr{firstRow=true}', 'first_row', True,\n    'a:tbl/a:tblPr{firstRow=1}'), ('a:tbl/a:tblPr{firstRow=false}',\n    'first_row', False, 'a:tbl/a:tblPr'), ('a:tbl/a:tblPr{bandRow=1}',\n    'first_row', True, 'a:tbl/a:tblPr{bandRow=1,firstRow=1}'), ('a:tbl',\n    'first_col', True, 'a:tbl/a:tblPr{firstCol=1}'), ('a:tbl', 'last_row', \n    True, 'a:tbl/a:tblPr{lastRow=1}'), ('a:tbl', 'last_col', True,\n    'a:tbl/a:tblPr{lastCol=1}'), ('a:tbl', 'horz_banding', True,\n    'a:tbl/a:tblPr{bandRow=1}'), ('a:tbl', 'vert_banding', True,\n    'a:tbl/a:tblPr{bandCol=1}')])\n", (5665, 6490), False, 'import pytest\n'), ((13255, 13463), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', None), ('a:tc/a:tcPr', None), ('a:tc/a:tcPr{anchor=t}',\n    MSO_ANCHOR.TOP), ('a:tc/a:tcPr{anchor=ctr}', MSO_ANCHOR.MIDDLE), (\n    'a:tc/a:tcPr{anchor=b}', MSO_ANCHOR.BOTTOM)]"}), "(params=[('a:tc', None), ('a:tc/a:tcPr', None), (\n    'a:tc/a:tcPr{anchor=t}', MSO_ANCHOR.TOP), ('a:tc/a:tcPr{anchor=ctr}',\n    MSO_ANCHOR.MIDDLE), ('a:tc/a:tcPr{anchor=b}', MSO_ANCHOR.BOTTOM)])\n", (13269, 13463), False, 'import pytest\n'), ((13718, 14069), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', None, 'a:tc'), ('a:tc', MSO_ANCHOR.TOP, 'a:tc/a:tcPr{anchor=t}'),\n    ('a:tc', MSO_ANCHOR.MIDDLE, 'a:tc/a:tcPr{anchor=ctr}'), ('a:tc',\n    MSO_ANCHOR.BOTTOM, 'a:tc/a:tcPr{anchor=b}'), ('a:tc/a:tcPr{anchor=t}',\n    MSO_ANCHOR.MIDDLE, 'a:tc/a:tcPr{anchor=ctr}'), (\n    'a:tc/a:tcPr{anchor=ctr}', None, 'a:tc/a:tcPr')]"}), "(params=[('a:tc', None, 'a:tc'), ('a:tc', MSO_ANCHOR.TOP,\n    'a:tc/a:tcPr{anchor=t}'), ('a:tc', MSO_ANCHOR.MIDDLE,\n    'a:tc/a:tcPr{anchor=ctr}'), ('a:tc', MSO_ANCHOR.BOTTOM,\n    'a:tc/a:tcPr{anchor=b}'), ('a:tc/a:tcPr{anchor=t}', MSO_ANCHOR.MIDDLE,\n    'a:tc/a:tcPr{anchor=ctr}'), ('a:tc/a:tcPr{anchor=ctr}', None,\n    'a:tc/a:tcPr')])\n", (13732, 14069), False, 'import pytest\n'), ((14544, 14636), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', 1), ('a:tc{gridSpan=2}', 1), ('a:tc{rowSpan=42}', 42)]"}), "(params=[('a:tc', 1), ('a:tc{gridSpan=2}', 1), (\n    'a:tc{rowSpan=42}', 42)])\n", (14558, 14636), False, 'import pytest\n'), ((16335, 16424), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['margin_left', 'margin_right', 'margin_top', 'margin_bottom']"}), "(params=['margin_left', 'margin_right', 'margin_top',\n    'margin_bottom'])\n", (16349, 16424), False, 'import pytest\n'), ((16670, 16912), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', False), ('a:tc{gridSpan=1}', False), ('a:tc{hMerge=1}', False), (\n    'a:tc{gridSpan=2,vMerge=1}', False), ('a:tc{gridSpan=2}', True), (\n    'a:tc{rowSpan=2}', True), ('a:tc{gridSpan=2,rowSpan=3}', True)]"}), "(params=[('a:tc', False), ('a:tc{gridSpan=1}', False), (\n    'a:tc{hMerge=1}', False), ('a:tc{gridSpan=2,vMerge=1}', False), (\n    'a:tc{gridSpan=2}', True), ('a:tc{rowSpan=2}', True), (\n    'a:tc{gridSpan=2,rowSpan=3}', True)])\n", (16684, 16912), False, 'import pytest\n'), ((17164, 17389), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', False), ('a:tc{gridSpan=2}', False), ('a:tc{hMerge=1}', True), (\n    'a:tc{gridSpan=2,vMerge=1}', True), ('a:tc{rowSpan=2,hMerge=true}', \n    True), ('a:tc{gridSpan=2,rowSpan=3}', False)]"}), "(params=[('a:tc', False), ('a:tc{gridSpan=2}', False), (\n    'a:tc{hMerge=1}', True), ('a:tc{gridSpan=2,vMerge=1}', True), (\n    'a:tc{rowSpan=2,hMerge=true}', True), ('a:tc{gridSpan=2,rowSpan=3}', \n    False)])\n", (17178, 17389), False, 'import pytest\n'), ((17630, 17987), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tbl/(a:tr/(a:tc{gridSpan=2},a:tc{hMerge=1}),a:tr/(a:tc,a:tc))', 0, [0,\n    1]), ('a:tbl/(a:tr/(a:tc{rowSpan=2},a:tc),a:tr/(a:tc{vMerge=1},a:tc))',\n    0, [0, 2]), (\n    'a:tbl/(a:tr/(a:tc{gridSpan=2,rowSpan=2},a:tc{hMerge=1,rowSpan=2}),a:tr/(a:tc{gridSpan=2,vMerge=1},a:tc{hMerge=1,vMerge=1}))'\n    , 0, [0, 1, 2, 3])]"}), "(params=[(\n    'a:tbl/(a:tr/(a:tc{gridSpan=2},a:tc{hMerge=1}),a:tr/(a:tc,a:tc))', 0, [\n    0, 1]), (\n    'a:tbl/(a:tr/(a:tc{rowSpan=2},a:tc),a:tr/(a:tc{vMerge=1},a:tc))', 0, [0,\n    2]), (\n    'a:tbl/(a:tr/(a:tc{gridSpan=2,rowSpan=2},a:tc{hMerge=1,rowSpan=2}),a:tr/(a:tc{gridSpan=2,vMerge=1},a:tc{hMerge=1,vMerge=1}))'\n    , 0, [0, 1, 2, 3])])\n", (17644, 17987), False, 'import pytest\n'), ((18519, 18611), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tc', 1), ('a:tc{rowSpan=2}', 1), ('a:tc{gridSpan=24}', 24)]"}), "(params=[('a:tc', 1), ('a:tc{rowSpan=2}', 1), (\n    'a:tc{gridSpan=24}', 24)])\n", (18533, 18611), False, 'import pytest\n'), ((20502, 20573), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['a:tr', 'a:tr/a:tc', 'a:tr/(a:tc, a:tc, a:tc)']"}), "(params=['a:tr', 'a:tr/a:tc', 'a:tr/(a:tc, a:tc, a:tc)'])\n", (20516, 20573), False, 'import pytest\n'), ((21077, 21162), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tr', 0), ('a:tr/a:tc', 1), ('a:tr/(a:tc, a:tc)', 2)]"}), "(params=[('a:tr', 0), ('a:tr/a:tc', 1), ('a:tr/(a:tc, a:tc)', 2)]\n    )\n", (21091, 21162), False, 'import pytest\n'), ((24380, 24508), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['a:tbl/a:tblGrid', 'a:tbl/a:tblGrid/a:gridCol',\n    'a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)']"}), "(params=['a:tbl/a:tblGrid', 'a:tbl/a:tblGrid/a:gridCol',\n    'a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)'])\n", (24394, 24508), False, 'import pytest\n'), ((24823, 24951), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['a:tbl/a:tblGrid', 'a:tbl/a:tblGrid/a:gridCol',\n    'a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)']"}), "(params=['a:tbl/a:tblGrid', 'a:tbl/a:tblGrid/a:gridCol',\n    'a:tbl/a:tblGrid/(a:gridCol, a:gridCol, a:gridCol)'])\n", (24837, 24951), False, 'import pytest\n'), ((25263, 25394), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tbl/a:tblGrid', 0), ('a:tbl/a:tblGrid/a:gridCol', 1), (\n    'a:tbl/a:tblGrid/(a:gridCol,a:gridCol)', 2)]"}), "(params=[('a:tbl/a:tblGrid', 0), ('a:tbl/a:tblGrid/a:gridCol',\n    1), ('a:tbl/a:tblGrid/(a:gridCol,a:gridCol)', 2)])\n", (25277, 25394), False, 'import pytest\n'), ((28847, 28921), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['a:tbl', 'a:tbl/a:tr', 'a:tbl/(a:tr, a:tr, a:tr)']"}), "(params=['a:tbl', 'a:tbl/a:tr', 'a:tbl/(a:tr, a:tr, a:tr)'])\n", (28861, 28921), False, 'import pytest\n'), ((29163, 29237), 'pytest.fixture', 'pytest.fixture', ([], {'params': "['a:tbl', 'a:tbl/a:tr', 'a:tbl/(a:tr, a:tr, a:tr)']"}), "(params=['a:tbl', 'a:tbl/a:tr', 'a:tbl/(a:tr, a:tr, a:tr)'])\n", (29177, 29237), False, 'import pytest\n'), ((29476, 29564), 'pytest.fixture', 'pytest.fixture', ([], {'params': "[('a:tbl', 0), ('a:tbl/a:tr', 1), ('a:tbl/(a:tr, a:tr)', 2)]"}), "(params=[('a:tbl', 0), ('a:tbl/a:tr', 1), (\n    'a:tbl/(a:tr, a:tr)', 2)])\n", (29490, 29564), False, 'import pytest\n'), ((943, 960), 'pptx.table.Table', 'Table', (['tbl_', 'None'], {}), '(tbl_, None)\n', (948, 960), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((1438, 1454), 'pptx.table.Table', 'Table', (['tbl', 'None'], {}), '(tbl, None)\n', (1443, 1454), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((1918, 1934), 'pptx.table.Table', 'Table', (['tbl', 'None'], {}), '(tbl, None)\n', (1923, 1934), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((2373, 2389), 'pptx.table.Table', 'Table', (['tbl', 'None'], {}), '(tbl, None)\n', (2378, 2389), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((7274, 7289), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (7279, 7289), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((7318, 7333), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (7323, 7333), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((7363, 7384), 'pptx.table._Cell', '_Cell', (['other_tc', 'None'], {}), '(other_tc, None)\n', (7368, 7384), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((7722, 7737), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (7727, 7737), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((7960, 7975), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (7965, 7975), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10841, 10856), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (10846, 10856), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((11072, 11087), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (11077, 11087), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((11287, 11309), 'pptx.table._Cell', '_Cell', (['origin_tc', 'None'], {}), '(origin_tc, None)\n', (11292, 11309), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((11700, 11715), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (11705, 11715), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((12025, 12042), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (12030, 12042), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((12239, 12256), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (12244, 12256), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((20029, 20054), 'pptx.table._CellCollection', '_CellCollection', (['tr', 'None'], {}), '(tr, None)\n', (20044, 20054), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((20740, 20765), 'pptx.table._CellCollection', '_CellCollection', (['tr', 'None'], {}), '(tr, None)\n', (20755, 20765), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((24689, 24717), 'pptx.table._ColumnCollection', '_ColumnCollection', (['tbl', 'None'], {}), '(tbl, None)\n', (24706, 24717), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((25129, 25157), 'pptx.table._ColumnCollection', '_ColumnCollection', (['tbl', 'None'], {}), '(tbl, None)\n', (25146, 25157), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((29042, 29067), 'pptx.table._RowCollection', '_RowCollection', (['tbl', 'None'], {}), '(tbl, None)\n', (29056, 29067), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((29355, 29380), 'pptx.table._RowCollection', '_RowCollection', (['tbl', 'None'], {}), '(tbl, None)\n', (29369, 29380), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((8729, 8753), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (8742, 8753), False, 'import pytest\n'), ((9731, 9746), 'pptx.table._Cell', '_Cell', (['tc', 'None'], {}), '(tc, None)\n', (9736, 9746), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((9748, 9769), 'pptx.table._Cell', '_Cell', (['other_tc', 'None'], {}), '(other_tc, None)\n', (9753, 9769), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10161, 10178), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (10166, 10178), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10180, 10197), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (10185, 10197), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10212, 10237), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (10225, 10237), False, 'import pytest\n'), ((10526, 10543), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (10531, 10543), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10545, 10562), 'pptx.table._Cell', '_Cell', (['None', 'None'], {}), '(None, None)\n', (10550, 10562), False, 'from pptx.table import _Cell, _CellCollection, _Column, _ColumnCollection, _Row, _RowCollection, Table\n'), ((10577, 10602), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (10590, 10602), False, 'import pytest\n'), ((11730, 11755), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (11743, 11755), False, 'import pytest\n'), ((20314, 20339), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (20327, 20339), False, 'import pytest\n'), ((20376, 20401), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (20389, 20401), False, 'import pytest\n'), ((24188, 24213), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (24201, 24213), False, 'import pytest\n'), ((24252, 24277), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (24265, 24277), False, 'import pytest\n'), ((28661, 28686), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (28674, 28686), False, 'import pytest\n'), ((28722, 28747), 'pytest.raises', 'pytest.raises', (['IndexError'], {}), '(IndexError)\n', (28735, 28747), False, 'import pytest\n'), ((29107, 29117), 'pptx.oxml.ns.qn', 'qn', (['"""a:tr"""'], {}), "('a:tr')\n", (29109, 29117), False, 'from pptx.oxml.ns import qn\n'), ((29420, 29430), 'pptx.oxml.ns.qn', 'qn', (['"""a:tr"""'], {}), "('a:tr')\n", (29422, 29430), False, 'from pptx.oxml.ns import qn\n'), ((14891, 14903), 'pptx.util.Inches', 'Inches', (['(0.09)'], {}), '(0.09)\n', (14897, 14903), False, 'from pptx.util import Inches, Length, Pt\n'), ((14962, 14974), 'pptx.util.Inches', 'Inches', (['(0.08)'], {}), '(0.08)\n', (14968, 14974), False, 'from pptx.util import Inches, Length, Pt\n'), ((15031, 15043), 'pptx.util.Inches', 'Inches', (['(0.07)'], {}), '(0.07)\n', (15037, 15043), False, 'from pptx.util import Inches, Length, Pt\n'), ((15103, 15115), 'pptx.util.Inches', 'Inches', (['(0.06)'], {}), '(0.06)\n', (15109, 15115), False, 'from pptx.util import Inches, Length, Pt\n'), ((15154, 15165), 'pptx.util.Inches', 'Inches', (['(0.1)'], {}), '(0.1)\n', (15160, 15165), False, 'from pptx.util import Inches, Length, Pt\n'), ((15212, 15223), 'pptx.util.Inches', 'Inches', (['(0.1)'], {}), '(0.1)\n', (15218, 15223), False, 'from pptx.util import Inches, Length, Pt\n'), ((15261, 15273), 'pptx.util.Inches', 'Inches', (['(0.05)'], {}), '(0.05)\n', (15267, 15273), False, 'from pptx.util import Inches, Length, Pt\n'), ((15321, 15333), 'pptx.util.Inches', 'Inches', (['(0.05)'], {}), '(0.05)\n', (15327, 15333), False, 'from pptx.util import Inches, Length, Pt\n'), ((15635, 15647), 'pptx.util.Inches', 'Inches', (['(0.08)'], {}), '(0.08)\n', (15641, 15647), False, 'from pptx.util import Inches, Length, Pt\n'), ((15714, 15726), 'pptx.util.Inches', 'Inches', (['(0.08)'], {}), '(0.08)\n', (15720, 15726), False, 'from pptx.util import Inches, Length, Pt\n'), ((15791, 15803), 'pptx.util.Inches', 'Inches', (['(0.08)'], {}), '(0.08)\n', (15797, 15803), False, 'from pptx.util import Inches, Length, Pt\n'), ((15871, 15883), 'pptx.util.Inches', 'Inches', (['(0.08)'], {}), '(0.08)\n', (15877, 15883), False, 'from pptx.util import Inches, Length, Pt\n'), ((22261, 22270), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (22267, 22270), False, 'from pptx.util import Inches, Length, Pt\n'), ((22295, 22301), 'pptx.util.Pt', 'Pt', (['(10)'], {}), '(10)\n', (22297, 22301), False, 'from pptx.util import Inches, Length, Pt\n'), ((22570, 22579), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (22576, 22579), False, 'from pptx.util import Inches, Length, Pt\n'), ((22639, 22648), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (22645, 22648), False, 'from pptx.util import Inches, Length, Pt\n'), ((26665, 26674), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (26671, 26674), False, 'from pptx.util import Inches, Length, Pt\n'), ((26694, 26700), 'pptx.util.Pt', 'Pt', (['(10)'], {}), '(10)\n', (26696, 26700), False, 'from pptx.util import Inches, Length, Pt\n'), ((26941, 26950), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (26947, 26950), False, 'from pptx.util import Inches, Length, Pt\n'), ((27000, 27009), 'pptx.util.Inches', 'Inches', (['(1)'], {}), '(1)\n', (27006, 27009), False, 'from pptx.util import Inches, Length, Pt\n')]