def test_indices(): d = BlockDiagramDrawer() with pytest.raises(IndexError): d.mutable_block(-1, -1) with pytest.raises(IndexError): d.set_row_min_height(-1, 500) with pytest.raises(IndexError): d.set_col_min_width(-1, 500)
def test_content_stretches_other_blocks(): d = BlockDiagramDrawer() d.mutable_block(0, 0).horizontal_alignment = 0.5 d.mutable_block(1, 0).horizontal_alignment = 0.5 d.mutable_block(0, 1).horizontal_alignment = 0.5 d.mutable_block(1, 1).horizontal_alignment = 0.5 d.mutable_block(0, 0).content = 'long text\nwith multiple lines' d.mutable_block(1, 0).draw_curve(NORMAL_BOX_CHARS, top=True, bottom=True, left=True, right=True) d.mutable_block(1, 1).draw_curve(NORMAL_BOX_CHARS, top=True, bottom=True, left=True, right=True) d.mutable_block(0, 1).draw_curve(NORMAL_BOX_CHARS, top=True, bottom=True, left=True, right=True) _assert_same_diagram( d.render(), """ long text ┼ with multiple lines│ ─────────┼─────────┼"""[1:], )
def test_lines_stretch_content(): d = BlockDiagramDrawer() d.mutable_block(0, 0).left = 'l' d.mutable_block(2, 4).right = 'r' d.mutable_block(11, 15).bottom = 'b' d.mutable_block(16, 17).top = 't' d.mutable_block(19, 20).center = 'c' d.mutable_block(21, 23).content = 'C' _assert_same_diagram(d.render(), """ C"""[1:])
def _curve_pieces_diagram(chars: BoxDrawCharacterSet) -> BlockDiagramDrawer: d = BlockDiagramDrawer() for x in range(4): for y in range(4): block = d.mutable_block(x * 2, y * 2) block.horizontal_alignment = 0.5 block.draw_curve(chars, top=bool(y & 1), bottom=bool(y & 2), left=bool(x & 2), right=bool(x & 1)) return d
def render(self, horizontal_spacing: int = 1, vertical_spacing: int = 1, crossing_char: str = None, use_unicode_characters: bool = True) -> str: """Outputs text containing the diagram.""" block_diagram = BlockDiagramDrawer() w = self.width() h = self.height() # Communicate padding into block diagram. for x in range(0, w - 1): block_diagram.set_col_min_width( x * 2 + 1, # Horizontal separation looks narrow, so partials round up. int(np.ceil(self.horizontal_padding.get(x, horizontal_spacing)))) block_diagram.set_col_min_width(x * 2, 1) for y in range(0, h - 1): block_diagram.set_row_min_height( y * 2 + 1, # Vertical separation looks wide, so partials round down. int(np.floor(self.vertical_padding.get(y, vertical_spacing)))) block_diagram.set_row_min_height(y * 2, 1) # Draw vertical lines. for x_b, y1_b, y2_b, emphasize in self.vertical_lines: x = int(x_b * 2) y1, y2 = int(min(y1_b, y2_b) * 2), int(max(y1_b, y2_b) * 2) charset = pick_charset(use_unicode_characters, emphasize) # Caps. block_diagram.mutable_block(x, y1).draw_curve(charset, bottom=True) block_diagram.mutable_block(x, y2).draw_curve(charset, top=True) # Span. for y in range(y1 + 1, y2): block_diagram.mutable_block(x, y).draw_curve(charset, top=True, bottom=True) # Draw horizontal lines. for y_b, x1_b, x2_b, emphasize in self.horizontal_lines: y = int(y_b * 2) x1, x2 = int(min(x1_b, x2_b) * 2), int(max(x1_b, x2_b) * 2) charset = pick_charset(use_unicode_characters, emphasize) # Caps. block_diagram.mutable_block(x1, y).draw_curve(charset, right=True) block_diagram.mutable_block(x2, y).draw_curve(charset, left=True) # Span. for x in range(x1 + 1, x2): block_diagram.mutable_block(x, y).draw_curve( charset, left=True, right=True, crossing_char=crossing_char) # Place entries. for (x, y), v in self.entries.items(): x *= 2 y *= 2 block_diagram.mutable_block(x, y).content = v.text return block_diagram.render()
def test_lines_meet_content(): d = BlockDiagramDrawer() b = d.mutable_block(0, 0) b.content = 'long text\nwith multiple lines' b.left = '>' b.right = '<' b.top = 'v' b.bottom = '^' _assert_same_diagram(d.render(), """ long text<<<<<<<<<< with multiple lines"""[1:]) b.horizontal_alignment = 0.5 _assert_same_diagram(d.render(), """ >>>>>long text<<<<< with multiple lines"""[1:]) _assert_same_diagram(d.render(min_block_height=5), """ v v >>>>>long text<<<<< with multiple lines ^"""[1:]) _assert_same_diagram(d.render(min_block_height=4), """ v >>>>>long text<<<<< with multiple lines ^"""[1:]) _assert_same_diagram(d.render(min_block_height=20, min_block_width=40), """ v v v v v v v v v >>>>>>>>>>>>>>>long text<<<<<<<<<<<<<<<< with multiple lines ^ ^ ^ ^ ^ ^ ^ ^ ^"""[1:]) _assert_same_diagram(d.render(min_block_height=21, min_block_width=41), """ v v v v v v v v v v >>>>>>>>>>>>>>>>long text<<<<<<<<<<<<<<<< with multiple lines ^ ^ ^ ^ ^ ^ ^ ^ ^"""[1:]) b.content = 'short text' _assert_same_diagram(d.render(min_block_height=21, min_block_width=41), """ v v v v v v v v v v >>>>>>>>>>>>>>>>short text<<<<<<<<<<<<<<< ^ ^ ^ ^ ^ ^ ^ ^ ^ ^"""[1:]) b.content = 'abc\ndef\nghi' _assert_same_diagram(d.render(min_block_height=21, min_block_width=41), """ v v v v v v v v v abc >>>>>>>>>>>>>>>>>>>def<<<<<<<<<<<<<<<<<<< ghi ^ ^ ^ ^ ^ ^ ^ ^ ^"""[1:])
def test_mixed_block_curve(): diagram = BlockDiagramDrawer() for a, b, c, d in itertools.product(range(3), repeat=4): x = (a * 3 + b) * 2 y = (c * 3 + d) * 2 block = diagram.mutable_block(x, y) block.horizontal_alignment = 0.5 block.draw_curve( NORMAL_BOX_CHARS, top=a == 2, bottom=b == 2, left=c == 2, right=d == 2) block.draw_curve( BOLD_BOX_CHARS, top=a == 1, bottom=b == 1, left=c == 1, right=d == 1) actual = diagram.render(min_block_width=3, min_block_height=3) expected = """ ┃ ┃ ┃ │ │ │ ╻ ╷ ╹ ┃ ╿ ╵ ╽ │ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ╺━ ┏━ ┍━ ┗━ ┣━ ┡━ ┕━ ┢━ ┝━ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ╶─ ┎─ ┌─ ┖─ ┠─ ┞─ └─ ┟─ ├─ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ━╸ ━┓ ━┑ ━┛ ━┫ ━┩ ━┙ ━┪ ━┥ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ━━━ ━┳━ ━┯━ ━┻━ ━╋━ ━╇━ ━┷━ ━╈━ ━┿━ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ━╾─ ━┱─ ━┭─ ━┹─ ━╉─ ━╃─ ━┵─ ━╅─ ━┽─ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ─╴ ─┒ ─┐ ─┚ ─┨ ─┦ ─┘ ─┧ ─┤ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ─╼━ ─┲━ ─┮━ ─┺━ ─╊━ ─╄━ ─┶━ ─╆━ ─┾━ ┃ │ ┃ │ ┃ │ ┃ ┃ ┃ │ │ │ ─── ─┰─ ─┬─ ─┸─ ─╂─ ─╀─ ─┴─ ─╁─ ─┼─ ┃ │ ┃ │ ┃ │"""[1:] _assert_same_diagram(actual, expected)