PyTermGUI 7.7.1__tar.gz → 7.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. {pytermgui-7.7.1 → pytermgui-7.7.2}/PKG-INFO +1 -1
  2. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/__init__.py +1 -1
  3. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/regex.py +1 -1
  4. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/collapsible.py +8 -0
  5. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/window_manager/layouts.py +2 -1
  6. pytermgui-7.7.1/pytermgui/cell.py +0 -320
  7. pytermgui-7.7.1/tests/not_test_cell.py +0 -125
  8. {pytermgui-7.7.1 → pytermgui-7.7.2}/.gitignore +0 -0
  9. {pytermgui-7.7.1 → pytermgui-7.7.2}/CHANGELOG.md +0 -0
  10. {pytermgui-7.7.1 → pytermgui-7.7.2}/LICENSE +0 -0
  11. {pytermgui-7.7.1 → pytermgui-7.7.2}/README.md +0 -0
  12. {pytermgui-7.7.1 → pytermgui-7.7.2}/examples/README.md +0 -0
  13. {pytermgui-7.7.1 → pytermgui-7.7.2}/pyproject.toml +0 -0
  14. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/animations.py +0 -0
  15. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/ansi_interface.py +0 -0
  16. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/cmd.py +0 -0
  17. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/color_info.py +0 -0
  18. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/colors.py +0 -0
  19. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/context_managers.py +0 -0
  20. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/enums.py +0 -0
  21. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/exceptions.py +0 -0
  22. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/exporters.py +0 -0
  23. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/fancy_repr.py +0 -0
  24. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/file_loaders.py +0 -0
  25. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/helpers.py +0 -0
  26. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/highlighters.py +0 -0
  27. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/input.py +0 -0
  28. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/inspector.py +0 -0
  29. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/__init__.py +0 -0
  30. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/aliases.py +0 -0
  31. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/language.py +0 -0
  32. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/macros.py +0 -0
  33. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/parsing.py +0 -0
  34. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/style_maps.py +0 -0
  35. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/markup/tokens.py +0 -0
  36. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/palettes.py +0 -0
  37. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/prettifiers.py +0 -0
  38. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/pretty.py +0 -0
  39. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/py.typed +0 -0
  40. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/serialization.py +0 -0
  41. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/term.py +0 -0
  42. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/__init__.py +0 -0
  43. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/base.py +0 -0
  44. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/boxes.py +0 -0
  45. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/button.py +0 -0
  46. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/checkbox.py +0 -0
  47. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/color_picker.py +0 -0
  48. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/containers.py +0 -0
  49. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/fancy_repr.py +0 -0
  50. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/frames.py +0 -0
  51. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/inline.py +0 -0
  52. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/input_field.py +0 -0
  53. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/keyboard_button.py +0 -0
  54. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/pixel_matrix.py +0 -0
  55. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/slider.py +0 -0
  56. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/styles.py +0 -0
  57. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/widgets/toggle.py +0 -0
  58. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/win32console.py +0 -0
  59. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/window_manager/__init__.py +0 -0
  60. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/window_manager/compositor.py +0 -0
  61. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/window_manager/manager.py +0 -0
  62. {pytermgui-7.7.1 → pytermgui-7.7.2}/pytermgui/window_manager/window.py +0 -0
  63. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/__init__.py +0 -0
  64. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/_exporter_targets.py +0 -0
  65. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/colorgrids.py +0 -0
  66. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test.json +0 -0
  67. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test.yaml +0 -0
  68. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_animations.py +0 -0
  69. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_auto.py +0 -0
  70. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_colors.py +0 -0
  71. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_dump_n_load.py +0 -0
  72. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_exporters.py +0 -0
  73. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_fancy_repr.py +0 -0
  74. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_helpers.py +0 -0
  75. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_highlight_markup_literal.py +0 -0
  76. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_layouts.py +0 -0
  77. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_parser.py +0 -0
  78. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_regex.py +0 -0
  79. {pytermgui-7.7.1 → pytermgui-7.7.2}/tests/test_styles.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyTermGUI
3
- Version: 7.7.1
3
+ Version: 7.7.2
4
4
  Summary: Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more!
5
5
  Project-URL: homepage, https://github.com/bczsalba/PyTermGUI
6
6
  Project-URL: repository, https://github.com/bczsalba/PyTermGUI
@@ -40,7 +40,7 @@ if "-m" in sys.argv: # pragma: no cover
40
40
 
41
41
  warnings.filterwarnings("ignore")
42
42
 
43
- __version__ = "7.7.1"
43
+ __version__ = "7.7.2"
44
44
 
45
45
 
46
46
  def auto(data: Any, **widget_args: Any) -> Optional[Widget | list[Splitter]]:
@@ -71,7 +71,7 @@ def real_length(text: str) -> int:
71
71
  The display-length of text.
72
72
  """
73
73
 
74
- return wcswidth(strip_ansi(text))
74
+ return max(wcswidth(strip_ansi(text)), 0)
75
75
 
76
76
 
77
77
  def escape_markup(text: str) -> str:
@@ -7,6 +7,7 @@ from typing import Any
7
7
  from ..enums import Overflow
8
8
  from ..input import keys
9
9
  from .containers import Container
10
+ from .base import Widget
10
11
  from .toggle import Toggle
11
12
 
12
13
  __all__ = ["Collapsible"]
@@ -53,6 +54,13 @@ class Collapsible(Container):
53
54
 
54
55
  self._is_expanded = False
55
56
 
57
+ @property
58
+ def selectables(self) -> list[tuple[Widget, int]]:
59
+ if self._is_expanded:
60
+ return super().selectables
61
+
62
+ return [(self.trigger, 0)]
63
+
56
64
  def toggle(self) -> Collapsible:
57
65
  """Toggles expanded state.
58
66
 
@@ -285,7 +285,8 @@ class Layout:
285
285
  """Adds a new slot to the layout.
286
286
 
287
287
  Args:
288
- name: The name of the slot. Used for display purposes.
288
+ name: The **snakeified** name of the slot. A non-snake case name
289
+ will cause issues when trying to retrieve the slot (see GH#147).
289
290
  slot: An already instantiated `Slot` instance. If this is given,
290
291
  the additional width & height arguments will be ignored.
291
292
  width: The width for the new slot. See below for special types.
@@ -1,320 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
-
5
- STYLE_START_CHAR = "\x1b"
6
- STYLE_END_CHAR = "m"
7
-
8
- UNSETTER_LOOKUP = {
9
- **{"38": {"39"}, "48": {"49"}, "54": {"53"}},
10
- **{str(index + 20): {str(index)} for index in range(1, 10)},
11
- **{"22": {"1", "2"}},
12
- }
13
-
14
-
15
- def _is_color(style: str) -> bool:
16
- """Determines whether the given style string is a color."""
17
-
18
- if style.startswith(("38", "48")):
19
- return True
20
-
21
- if style.isdigit():
22
- index = int(style)
23
-
24
- if 30 <= index <= 38 or 40 <= index <= 48:
25
- return True
26
-
27
- return False
28
-
29
-
30
- def _process_styles(styles: list[str]) -> tuple[list[str], str, str]:
31
- """Processes the given styles, cleaning them up along the way.
32
-
33
- This does 2 major tasks:
34
-
35
- - Remove styles that are unset by later ones
36
- - Extract the fore and background colors, returning them
37
-
38
- Args:
39
- style: The list of styles to process.
40
-
41
- Returns:
42
- A tuple containing:
43
-
44
- - The processed list of styles
45
- - The foreground color
46
- - The background color
47
- """
48
-
49
- # TODO: Split up compound styles before handling them.
50
-
51
- applied = []
52
- foreground = ""
53
- background = ""
54
-
55
- for style in styles:
56
- unset_styles = UNSETTER_LOOKUP.get(style)
57
-
58
- if _is_color(style):
59
- if style.startswith("3"):
60
- foreground = style
61
- else:
62
- background = style
63
-
64
- continue
65
-
66
- if style == "39":
67
- foreground = ""
68
-
69
- elif style == "49":
70
- background = ""
71
-
72
- elif style == "0":
73
- applied = []
74
- foreground = ""
75
- background = ""
76
-
77
- elif unset_styles is not None:
78
- for unset_style in unset_styles:
79
- if unset_style in applied:
80
- applied.remove(unset_style)
81
-
82
- if style not in applied:
83
- applied.append(style)
84
-
85
- if foreground:
86
- applied.append(foreground)
87
-
88
- if background:
89
- applied.append(background)
90
-
91
- return applied, foreground, background
92
-
93
-
94
- def _split(styles: str) -> list[str]:
95
- """Splits styles into a list of their content.
96
-
97
- For example, `\x1b[38;5;141;1m` would become `38;5;141` and `1`.
98
- """
99
-
100
- return [style.rstrip("m") for style in styles.split("\x1b[")[1:]]
101
-
102
-
103
- def _combine(styles: list[str]) -> str:
104
- """Combines a list of style content into a compound style setter.
105
-
106
- Instead of doing individual tags, it puts all of the styles into
107
- a single unit, i.e. instead of `\x1b[38;5;141m\x1b[1m` it returns
108
- `\x1b[38;5;141;1m`.
109
- """
110
-
111
- if len(styles) == 0:
112
- return ""
113
-
114
- return f"\x1b[{';'.join(styles)}{STYLE_END_CHAR}"
115
-
116
-
117
- @dataclass
118
- class Cell:
119
- """A unit that represents a single, possibly ANSI-styled character."""
120
-
121
- char: str = ""
122
- styles: str = ""
123
-
124
- _foreground: str | None = None
125
- _background: str | None = None
126
-
127
- def __str__(self) -> str:
128
- """Gets the content of this cell."""
129
-
130
- return self.styles + self.char
131
-
132
- @property
133
- def foreground(self) -> str | None:
134
- """Returns the currently set foreground color in this cell."""
135
-
136
- return self._foreground
137
-
138
- @foreground.setter
139
- def foreground(self, new: str | None) -> None:
140
- """Allows setting the foreground color, while unsetting the current one."""
141
-
142
- current = self.foreground
143
-
144
- if current is not None:
145
- self.styles = self.styles.replace(current, "")
146
-
147
- self.styles += new
148
-
149
- if new is not None:
150
- self._foreground = f"\x1b[{new}m"
151
-
152
- else:
153
- self._foreground = None
154
-
155
- @property
156
- def background(self) -> str | None:
157
- """Returns the currently set background color in this cell."""
158
-
159
- return self._background
160
-
161
- @background.setter
162
- def background(self, new: str | None) -> None:
163
- """Allows setting the background color, while unsetting the current one."""
164
-
165
- current = self.background
166
-
167
- if current is not None:
168
- self.styles = self.styles.replace(current, "")
169
-
170
- self.styles += new
171
-
172
- if new is not None:
173
- self._background = f"\x1b[{new}m"
174
-
175
- else:
176
- self._background = None
177
-
178
- @classmethod
179
- def from_line(cls, line: str, styles: str = "") -> Generator[None, None, Cell]:
180
- """Yields Cells generated from a line of text.
181
-
182
- Args:
183
- line: The input line. May or may not contain ANSI styles.
184
- styles: Styles that are applied to the line from before the line started.
185
-
186
- Returns:
187
- A Cell generator.
188
- """
189
-
190
- in_style = False
191
- current_style = styles
192
- current_styles = []
193
-
194
- for char in line:
195
- if char == STYLE_START_CHAR:
196
- in_style = True
197
- current_style = ""
198
- continue
199
-
200
- if in_style:
201
- if char == "[":
202
- continue
203
-
204
- if char == STYLE_END_CHAR:
205
- current_styles.append(current_style)
206
- in_style = False
207
- continue
208
-
209
- current_style += char
210
- continue
211
-
212
- current_styles, fore, back = _process_styles(current_styles)
213
-
214
- yield Cell(char or " ", _combine(current_styles), fore, back)
215
-
216
- if current_style != "":
217
- current_styles, fore, back = _process_styles(
218
- current_styles + [current_style]
219
- )
220
-
221
- yield Cell("", _combine(current_styles), fore, back)
222
-
223
- @classmethod
224
- def first_of(cls, line: str) -> Cell:
225
- """Returns the first cell yielded by `from_line`."""
226
-
227
- for cell in cls.from_line(line):
228
- return cell
229
-
230
-
231
- class CellMatrix:
232
- def __init__(self, width: int, height: int, default: str = " ") -> None:
233
- self._cells = []
234
- self._changes: list[tuple[int, int, Cell]] = []
235
-
236
- for _ in range(height):
237
- row = []
238
-
239
- for _ in range(width):
240
- row.append(Cell(default))
241
-
242
- self._cells.append(row)
243
-
244
- self.width = width
245
- self.height = height
246
-
247
- def resize(self, width: int, height: int, default: str = " ") -> None:
248
- diff_cols = width - self.width
249
- diff_rows = height - self.height
250
-
251
- default_cell = list(Cell.from_line(default))[0]
252
-
253
- for row in range(self.height):
254
- self._cells[row].extend([default_cell] * diff_cols)
255
-
256
- for _ in range(diff_rows):
257
- self._cells.append([default_cell] * (width))
258
-
259
- self.width, self.height = width, height
260
-
261
- def add_text(
262
- self, text: str, offset: tuple[int, int] = (0, 0), register_change: bool = True
263
- ) -> None:
264
- x, y = offset
265
-
266
- if y >= self.height:
267
- return
268
-
269
- for i, cell in enumerate(Cell.from_line(text)):
270
- # Sometimes some styles (usually the global unsetter 0) are left over at
271
- # the end of a line of text. These are dealt with here; overflowing either
272
- # into the next cell in the same row, or the first cell of the next one.
273
- if cell.char == "":
274
- if x + i < self.width:
275
- self._cells[y][x + i].styles += cell.styles
276
-
277
- else:
278
- if y + 1 >= self.height:
279
- continue
280
-
281
- self._cells[y + 1][0].styles += cell.styles
282
-
283
- continue
284
-
285
- if self.width <= x + i:
286
- break
287
-
288
- if self._cells[y][x + i] != cell:
289
- self._cells[y][x + i] = cell
290
-
291
- if register_change:
292
- self._changes.append((x + i, y, cell))
293
-
294
- def fill(self, content: str) -> None:
295
- for row in range(self.height):
296
- for col in range(self.width):
297
- self.add_text(content, (col, row), register_change=False)
298
-
299
- def build_lines(self) -> list[str]:
300
- lines = []
301
- for row in self._cells:
302
- buff = ""
303
-
304
- for cell in row:
305
- buff += str(cell)
306
-
307
- lines.append(buff + "")
308
-
309
- return lines
310
-
311
- def get_diff(self, origin: tuple[int, int] = (1, 1)) -> tuple[str, int]:
312
- buff = ""
313
-
314
- for x, y, cell in self._changes:
315
- buff += f"\x1b[{y + origin[1]};{x + origin[0]}H{cell}"
316
-
317
- change_count = len(self._changes)
318
- self._changes.clear()
319
-
320
- return buff, change_count
@@ -1,125 +0,0 @@
1
- from pytermgui.cell import (
2
- Cell,
3
- CellMatrix,
4
- _is_color,
5
- _combine,
6
- _split,
7
- _process_styles,
8
- )
9
-
10
-
11
- def test_is_color():
12
- assert _is_color("31")
13
- assert _is_color("45")
14
- assert _is_color("38;5;141")
15
- assert _is_color("48;5;61")
16
- assert _is_color("38;2;22;33;44")
17
- assert _is_color("48;2;22;33;44")
18
-
19
- assert not _is_color("1")
20
- assert not _is_color("9")
21
- assert not _is_color("22")
22
- assert not _is_color("1")
23
-
24
-
25
- def test_combine():
26
- assert _combine(["41", "38;5;141", "1"]) == "\x1b[41;38;5;141;1m"
27
-
28
-
29
- def test_split():
30
- assert _split("\x1b[38;2;53;12;123m\x1b[1m\x1b[9m\x1b[48;2;21;21;21m") == [
31
- "38;2;53;12;123",
32
- "1",
33
- "9",
34
- "48;2;21;21;21",
35
- ]
36
-
37
-
38
- def test_process_styles():
39
- tests = [
40
- # Bold & Dim both get unset by the same unsetter
41
- (["38;5;141", "1", "9", "2", "22"], {"38;5;141", "9", "22"}),
42
- # 0 unsets everything
43
- (["38;2;66;66;66", "1", "0"], {"0"}),
44
- # Duplicates are ignored
45
- (["1", "1", "9"], {"1", "9"}),
46
- # Foreground colors work; background ones unset
47
- (["38;5;131", "1", "41", "49"], {"38;5;131", "1", "49"}),
48
- # Background colors work; foreground ones unset
49
- (["48;2;33;44;55", "7", "35", "39"], {"48;2;33;44;55", "7", "39"}),
50
- ]
51
-
52
- for target, expected in tests:
53
- output = _process_styles(target)[0]
54
-
55
- if len(set(output)) != len(output):
56
- raise ValueError(f"Output {output} contains duplicates.")
57
-
58
- assert set(output) == expected
59
-
60
-
61
- def test_cell_from_line():
62
- tests = [
63
- # General example
64
- (
65
- "\x1b[38;5;141\x1b[1mHello\x1b[7mThere",
66
- [
67
- Cell("H", "\x1b[38;5;141;1m", "38;5;141"),
68
- Cell("e", "\x1b[38;5;141;1m", "38;5;141"),
69
- Cell("l", "\x1b[38;5;141;1m", "38;5;141"),
70
- Cell("l", "\x1b[38;5;141;1m", "38;5;141"),
71
- Cell("o", "\x1b[38;5;141;1m", "38;5;141"),
72
- Cell("T", "\x1b[7;38;5;141;1m", "38;5;141"),
73
- Cell("h", "\x1b[7;38;5;141;1m", "38;5;141"),
74
- Cell("e", "\x1b[7;38;5;141;1m", "38;5;141"),
75
- Cell("r", "\x1b[7;38;5;141;1m", "38;5;141"),
76
- Cell("e", "\x1b[7;38;5;141;1m", "38;5;141"),
77
- # Trailing style
78
- Cell("", "\x1b[7;38;5;141;1m", "38;5;141"),
79
- ],
80
- ),
81
- # Achy breaky code (chode)
82
- # Unsetters & trailing
83
- (
84
- "\x1b[1m\x1b[33m1\x1b[22m2\x1b[0m",
85
- [
86
- Cell(char="1", styles="\x1b[1;33m"),
87
- Cell(char="2", styles="\x1b[22;33m"),
88
- Cell(char="", styles="\x1b[0m"),
89
- ],
90
- ),
91
- # (Future) Compound styles
92
- # (
93
- # "\x1b[1;33m1\x1b[22m2\x1b[0m",
94
- # [
95
- # Cell(char="1", styles="\x1b[1;33m"),
96
- # Cell(char="2", styles="\x1b[22;33m"),
97
- # Cell(char="", styles="\x1b[0m"),
98
- # ],
99
- # ),
100
- ]
101
-
102
- for target, expected in tests:
103
- assert list(Cell.from_line(target)) == expected
104
-
105
-
106
- def test_cell_foreground():
107
- assert Cell.first_of("\x1b[38;5;141mHello there").foreground == "\x1b[38;5;141m"
108
-
109
-
110
- def test_cell_matrix_resize():
111
- mat = CellMatrix(5, 5, default="x")
112
- mat.resize(10, 10, default="O")
113
-
114
- assert mat.build_lines() == [
115
- "xxxxxOOOOO",
116
- "xxxxxOOOOO",
117
- "xxxxxOOOOO",
118
- "xxxxxOOOOO",
119
- "xxxxxOOOOO",
120
- "OOOOOOOOOO",
121
- "OOOOOOOOOO",
122
- "OOOOOOOOOO",
123
- "OOOOOOOOOO",
124
- "OOOOOOOOOO",
125
- ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes