def test_build_cell__with_sep(cell_styles, expected): # .. note:: # # CALS default value for @colsep and @rowsep is "1". builder = CalsBuilder() # -- create a minimal <row> element row_elem = etree.XML("<row/>") # -- setup a minimal cell p_elem = etree.XML("<p>text</p>") cell_x1_y1 = Cell([p_elem], x=1, y=1, styles=cell_styles) cell_x2_y1 = Cell([p_elem], x=2, y=1, styles=cell_styles) cell_x1_y2 = Cell([p_elem], x=1, y=2, styles=cell_styles) cell_x2_y2 = Cell([p_elem], x=2, y=2, styles=cell_styles) builder.setup_table(Table([cell_x1_y1, cell_x2_y1, cell_x1_y2, cell_x2_y2])) # -- build the cell builder.build_cell(row_elem, cell_x1_y1) # -- check the '<entry>' attributes entry_elem = row_elem[0] # type: ElementType assert entry_elem.tag == u"entry" assert entry_elem.attrib == expected assert entry_elem[0] == p_elem
def test_g6(): # fmt: off g6 = Grid([ Cell("a", x=1, y=1), Cell("bb", x=2, y=1), Cell("cc", x=1, y=2), Cell("d", x=2, y=2) ]) actual = draw(g6) expected = textwrap.dedent("""\ +-----------+-----------+ | a | bb | +-----------+-----------+ | cc | d | +-----------+-----------+""") assert expected == actual
def test_g1(): # fmt: off g1 = Grid([ Cell("aaa", x=1, y=1, width=2), Cell("bb", x=3, y=1), Cell("cc", x=1, y=2), Cell("dddddddddd", x=2, y=2, width=2) ]) actual = draw(g1) expected = textwrap.dedent("""\ +-----------------------+-----------+ | aaa | bb | +-----------+-----------------------+ | cc | ddddddddd | +-----------+-----------------------+""") assert expected == actual
def test_build_cell__align(cell_styles, expected): builder = CalsBuilder() # -- create a minimal <row> element row_elem = etree.XML("<row/>") # -- setup a minimal cell p_elem = etree.XML("<p>text</p>") cell = Cell([p_elem], x=1, y=1, styles=cell_styles) builder.setup_table(Table([cell])) # -- build the cell builder.build_cell(row_elem, cell) # -- check the '<entry>' attributes entry_elem = row_elem[0] # type: ElementType assert entry_elem.tag == u"entry" # we don't want to check @colsep/@rowsep here actual = dict(entry_elem.attrib) actual.pop("colsep", None) actual.pop("rowsep", None) assert actual == expected assert entry_elem[0] == p_elem
def insert_cell(self, content, styles=None, nature=None, width=1, height=1): """ Insert a new cell in the column at the next free position, or at the end. :param content: User-defined cell content. It can be of any type: ``None``, :class:`str`, :class:`int`, :class:`float`, a container (:class:`list`), a XML element, etc. The same content can be shared by several cells, it's your own responsibility to handle the copy (or deep copy) of the *content* reference when needed. :type styles: typing.Dict[str, str] :param styles: User-defined cell styles: a dictionary of key-value pairs. This values are useful to store some HTML-like styles (border-style, border-width, border-color, vertical-align, text-align, etc.). Of course, we are not tied to the HTML-like styles, you can use your own list of styles. :type nature: str :ivar nature: a way to distinguish the body cells, from the header and the footer. The default value is ``None``, but you can use "body", "header", "footer" or whatever is suitable for your needs. If set to ``None``, the cell nature is inherited from the column nature. :param int width: Width of the cell (columns spanning), default to 1. :param int height: Height of the cell (rows spanning), default to 1. .. versionchanged:: 0.4.2 The *nature* of a cell is inherited from its parent's column. """ caught_cells = self._caught_cells x = self._pos if caught_cells: boxes = tuple(cell.box for cell in caught_cells) bounding_box = boxes[0].union(*boxes[1:]) for y in range(1, bounding_box.max.y + 1): if all((x, y) not in box for box in boxes): break else: y = bounding_box.max.y + 1 else: y = 1 nature = self.nature if nature is None else nature cell = Cell(content, styles=styles, nature=nature, x=x, y=y, width=width, height=height) self._table[cell.min] = cell
def test_build_cell__body(kwargs, attrib): builder = FormexBuilder() p_elem = P(u"text") cell_x1_y1 = Cell([p_elem], x=1, y=1, **kwargs) table = Table([cell_x1_y1]) builder._table = table # -- build the cell row_elem = ROW() row_y1 = next(iter(table.rows)) builder.build_cell(row_elem, cell_x1_y1, row_y1) # -- check the '<CELL>' attributes entry_elem = row_elem[0] # type: etree._Element assert entry_elem.tag == u"CELL" assert entry_elem.attrib == attrib assert entry_elem[0] == p_elem
def test_g5(): # fmt: off g5 = Grid([ Cell("aa", x=1, y=1, height=2), Cell("bb", x=2, y=1), Cell("cccc", x=3, y=1), Cell("ddd", x=2, y=2), Cell("eeeee", x=3, y=2), Cell("ff", x=1, y=3, width=2), Cell("gggggg", x=3, y=3), ]) actual = draw(g5) expected = textwrap.dedent("""\ +-----------+-----------+-----------+ | aa | bb | cccc | | +-----------+-----------+ | | ddd | eeeee | +-----------------------+-----------+ | ff | gggggg | +-----------------------+-----------+""") assert expected == actual
def test_g4(): # fmt: off g4 = Grid([ Cell("aa", x=1, y=1, height=2), Cell("bbb", x=2, y=1, width=2), Cell("ccc", x=2, y=2, height=2), Cell("dd", x=3, y=2), Cell("eeee", x=1, y=3), Cell("ffffff", x=3, y=3), ]) actual = draw(g4) expected = textwrap.dedent("""\ +-----------+-----------------------+ | aa | bbb | | +-----------+-----------+ | | ccc | dd | +-----------| +-----------+ | eeee | | ffffff | +-----------+-----------+-----------+""") assert expected == actual
def fill_missing(self, bounding_box, content, styles=None, nature=None): """ Fill the missing cells in the table. This method is useful when some rows has missing cells (holes). :type bounding_box: Box :param bounding_box: The bounding box delimiting the cells/rows to fill if missing. :param content: User-defined cell content. It can be of any type: ``None``, :class:`str`, :class:`int`, :class:`float`, a container (:class:`list`), a XML element, etc. The same content can be shared by several cells, it's your own responsibility to handle the copy (or deep copy) of the *content* reference when needed. :type styles: typing.Dict[str, str] :param styles: User-defined cell styles: a dictionary of key-value pairs. This values are useful to store some HTML-like styles (border-style, border-width, border-color, vertical-align, text-align, etc.). Of course, we are not tied to the HTML-like styles, you can use your own list of styles. :type nature: str :ivar nature: a way to distinguish the body cells, from the header and the footer. The default value is ``None``, but you can use "body", "header", "footer" or whatever is suitable for your needs. If set to ``None``, the cell nature is inherited from the row nature. .. versionadded:: 0.5.0 """ for y in range(bounding_box.min.y, bounding_box.max.y + 1): for x in range(bounding_box.min.x, bounding_box.max.x + 1): if (x, y) not in self: cell = Cell(content, styles=styles, nature=nature, x=x, y=y) self[(x, y)] = cell