]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_vendor/rich/box.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _vendor / rich / box.py
1 import sys
2 from typing import TYPE_CHECKING, Iterable, List
3
4 if sys.version_info >= (3, 8):
5 from typing import Literal
6 else:
7 from pip._vendor.typing_extensions import Literal # pragma: no cover
8
9
10 from ._loop import loop_last
11
12 if TYPE_CHECKING:
13 from pip._vendor.rich.console import ConsoleOptions
14
15
16 class Box:
17 """Defines characters to render boxes.
18
19 ┌─┬┐ top
20 │ ││ head
21 ├─┼┤ head_row
22 │ ││ mid
23 ├─┼┤ row
24 ├─┼┤ foot_row
25 │ ││ foot
26 └─┴┘ bottom
27
28 Args:
29 box (str): Characters making up box.
30 ascii (bool, optional): True if this box uses ascii characters only. Default is False.
31 """
32
33 def __init__(self, box: str, *, ascii: bool = False) -> None:
34 self._box = box
35 self.ascii = ascii
36 line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines()
37 # top
38 self.top_left, self.top, self.top_divider, self.top_right = iter(line1)
39 # head
40 self.head_left, _, self.head_vertical, self.head_right = iter(line2)
41 # head_row
42 (
43 self.head_row_left,
44 self.head_row_horizontal,
45 self.head_row_cross,
46 self.head_row_right,
47 ) = iter(line3)
48
49 # mid
50 self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)
51 # row
52 self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5)
53 # foot_row
54 (
55 self.foot_row_left,
56 self.foot_row_horizontal,
57 self.foot_row_cross,
58 self.foot_row_right,
59 ) = iter(line6)
60 # foot
61 self.foot_left, _, self.foot_vertical, self.foot_right = iter(line7)
62 # bottom
63 self.bottom_left, self.bottom, self.bottom_divider, self.bottom_right = iter(
64 line8
65 )
66
67 def __repr__(self) -> str:
68 return "Box(...)"
69
70 def __str__(self) -> str:
71 return self._box
72
73 def substitute(self, options: "ConsoleOptions", safe: bool = True) -> "Box":
74 """Substitute this box for another if it won't render due to platform issues.
75
76 Args:
77 options (ConsoleOptions): Console options used in rendering.
78 safe (bool, optional): Substitute this for another Box if there are known problems
79 displaying on the platform (currently only relevant on Windows). Default is True.
80
81 Returns:
82 Box: A different Box or the same Box.
83 """
84 box = self
85 if options.legacy_windows and safe:
86 box = LEGACY_WINDOWS_SUBSTITUTIONS.get(box, box)
87 if options.ascii_only and not box.ascii:
88 box = ASCII
89 return box
90
91 def get_plain_headed_box(self) -> "Box":
92 """If this box uses special characters for the borders of the header, then
93 return the equivalent box that does not.
94
95 Returns:
96 Box: The most similar Box that doesn't use header-specific box characters.
97 If the current Box already satisfies this criterion, then it's returned.
98 """
99 return PLAIN_HEADED_SUBSTITUTIONS.get(self, self)
100
101 def get_top(self, widths: Iterable[int]) -> str:
102 """Get the top of a simple box.
103
104 Args:
105 widths (List[int]): Widths of columns.
106
107 Returns:
108 str: A string of box characters.
109 """
110
111 parts: List[str] = []
112 append = parts.append
113 append(self.top_left)
114 for last, width in loop_last(widths):
115 append(self.top * width)
116 if not last:
117 append(self.top_divider)
118 append(self.top_right)
119 return "".join(parts)
120
121 def get_row(
122 self,
123 widths: Iterable[int],
124 level: Literal["head", "row", "foot", "mid"] = "row",
125 edge: bool = True,
126 ) -> str:
127 """Get the top of a simple box.
128
129 Args:
130 width (List[int]): Widths of columns.
131
132 Returns:
133 str: A string of box characters.
134 """
135 if level == "head":
136 left = self.head_row_left
137 horizontal = self.head_row_horizontal
138 cross = self.head_row_cross
139 right = self.head_row_right
140 elif level == "row":
141 left = self.row_left
142 horizontal = self.row_horizontal
143 cross = self.row_cross
144 right = self.row_right
145 elif level == "mid":
146 left = self.mid_left
147 horizontal = " "
148 cross = self.mid_vertical
149 right = self.mid_right
150 elif level == "foot":
151 left = self.foot_row_left
152 horizontal = self.foot_row_horizontal
153 cross = self.foot_row_cross
154 right = self.foot_row_right
155 else:
156 raise ValueError("level must be 'head', 'row' or 'foot'")
157
158 parts: List[str] = []
159 append = parts.append
160 if edge:
161 append(left)
162 for last, width in loop_last(widths):
163 append(horizontal * width)
164 if not last:
165 append(cross)
166 if edge:
167 append(right)
168 return "".join(parts)
169
170 def get_bottom(self, widths: Iterable[int]) -> str:
171 """Get the bottom of a simple box.
172
173 Args:
174 widths (List[int]): Widths of columns.
175
176 Returns:
177 str: A string of box characters.
178 """
179
180 parts: List[str] = []
181 append = parts.append
182 append(self.bottom_left)
183 for last, width in loop_last(widths):
184 append(self.bottom * width)
185 if not last:
186 append(self.bottom_divider)
187 append(self.bottom_right)
188 return "".join(parts)
189
190
191 ASCII: Box = Box(
192 """\
193 +--+
194 | ||
195 |-+|
196 | ||
197 |-+|
198 |-+|
199 | ||
200 +--+
201 """,
202 ascii=True,
203 )
204
205 ASCII2: Box = Box(
206 """\
207 +-++
208 | ||
209 +-++
210 | ||
211 +-++
212 +-++
213 | ||
214 +-++
215 """,
216 ascii=True,
217 )
218
219 ASCII_DOUBLE_HEAD: Box = Box(
220 """\
221 +-++
222 | ||
223 +=++
224 | ||
225 +-++
226 +-++
227 | ||
228 +-++
229 """,
230 ascii=True,
231 )
232
233 SQUARE: Box = Box(
234 """\
235 ┌─┬┐
236 │ ││
237 ├─┼┤
238 │ ││
239 ├─┼┤
240 ├─┼┤
241 │ ││
242 └─┴┘
243 """
244 )
245
246 SQUARE_DOUBLE_HEAD: Box = Box(
247 """\
248 ┌─┬┐
249 │ ││
250 ╞═╪╡
251 │ ││
252 ├─┼┤
253 ├─┼┤
254 │ ││
255 └─┴┘
256 """
257 )
258
259 MINIMAL: Box = Box(
260 """\
261
262
263 ╶─┼╴
264
265 ╶─┼╴
266 ╶─┼╴
267
268
269 """
270 )
271
272
273 MINIMAL_HEAVY_HEAD: Box = Box(
274 """\
275
276
277 ╺━┿╸
278
279 ╶─┼╴
280 ╶─┼╴
281
282
283 """
284 )
285
286 MINIMAL_DOUBLE_HEAD: Box = Box(
287 """\
288
289
290 ═╪
291
292 ─┼
293 ─┼
294
295
296 """
297 )
298
299
300 SIMPLE: Box = Box(
301 """\
302
303
304 ──
305
306
307 ──
308
309
310 """
311 )
312
313 SIMPLE_HEAD: Box = Box(
314 """\
315
316
317 ──
318
319
320
321
322
323 """
324 )
325
326
327 SIMPLE_HEAVY: Box = Box(
328 """\
329
330
331 ━━
332
333
334 ━━
335
336
337 """
338 )
339
340
341 HORIZONTALS: Box = Box(
342 """\
343 ──
344
345 ──
346
347 ──
348 ──
349
350 ──
351 """
352 )
353
354 ROUNDED: Box = Box(
355 """\
356 ╭─┬╮
357 │ ││
358 ├─┼┤
359 │ ││
360 ├─┼┤
361 ├─┼┤
362 │ ││
363 ╰─┴╯
364 """
365 )
366
367 HEAVY: Box = Box(
368 """\
369 ┏━┳┓
370 ┃ ┃┃
371 ┣━╋┫
372 ┃ ┃┃
373 ┣━╋┫
374 ┣━╋┫
375 ┃ ┃┃
376 ┗━┻┛
377 """
378 )
379
380 HEAVY_EDGE: Box = Box(
381 """\
382 ┏━┯┓
383 ┃ │┃
384 ┠─┼┨
385 ┃ │┃
386 ┠─┼┨
387 ┠─┼┨
388 ┃ │┃
389 ┗━┷┛
390 """
391 )
392
393 HEAVY_HEAD: Box = Box(
394 """\
395 ┏━┳┓
396 ┃ ┃┃
397 ┡━╇┩
398 │ ││
399 ├─┼┤
400 ├─┼┤
401 │ ││
402 └─┴┘
403 """
404 )
405
406 DOUBLE: Box = Box(
407 """\
408 ╔═╦╗
409 ║ ║║
410 ╠═╬╣
411 ║ ║║
412 ╠═╬╣
413 ╠═╬╣
414 ║ ║║
415 ╚═╩╝
416 """
417 )
418
419 DOUBLE_EDGE: Box = Box(
420 """\
421 ╔═╤╗
422 ║ │║
423 ╟─┼╢
424 ║ │║
425 ╟─┼╢
426 ╟─┼╢
427 ║ │║
428 ╚═╧╝
429 """
430 )
431
432 MARKDOWN: Box = Box(
433 """\
434
435 | ||
436 |-||
437 | ||
438 |-||
439 |-||
440 | ||
441
442 """,
443 ascii=True,
444 )
445
446 # Map Boxes that don't render with raster fonts on to equivalent that do
447 LEGACY_WINDOWS_SUBSTITUTIONS = {
448 ROUNDED: SQUARE,
449 MINIMAL_HEAVY_HEAD: MINIMAL,
450 SIMPLE_HEAVY: SIMPLE,
451 HEAVY: SQUARE,
452 HEAVY_EDGE: SQUARE,
453 HEAVY_HEAD: SQUARE,
454 }
455
456 # Map headed boxes to their headerless equivalents
457 PLAIN_HEADED_SUBSTITUTIONS = {
458 HEAVY_HEAD: SQUARE,
459 SQUARE_DOUBLE_HEAD: SQUARE,
460 MINIMAL_DOUBLE_HEAD: MINIMAL,
461 MINIMAL_HEAVY_HEAD: MINIMAL,
462 ASCII_DOUBLE_HEAD: ASCII2,
463 }
464
465
466 if __name__ == "__main__": # pragma: no cover
467
468 from pip._vendor.rich.columns import Columns
469 from pip._vendor.rich.panel import Panel
470
471 from . import box as box
472 from .console import Console
473 from .table import Table
474 from .text import Text
475
476 console = Console(record=True)
477
478 BOXES = [
479 "ASCII",
480 "ASCII2",
481 "ASCII_DOUBLE_HEAD",
482 "SQUARE",
483 "SQUARE_DOUBLE_HEAD",
484 "MINIMAL",
485 "MINIMAL_HEAVY_HEAD",
486 "MINIMAL_DOUBLE_HEAD",
487 "SIMPLE",
488 "SIMPLE_HEAD",
489 "SIMPLE_HEAVY",
490 "HORIZONTALS",
491 "ROUNDED",
492 "HEAVY",
493 "HEAVY_EDGE",
494 "HEAVY_HEAD",
495 "DOUBLE",
496 "DOUBLE_EDGE",
497 "MARKDOWN",
498 ]
499
500 console.print(Panel("[bold green]Box Constants", style="green"), justify="center")
501 console.print()
502
503 columns = Columns(expand=True, padding=2)
504 for box_name in sorted(BOXES):
505 table = Table(
506 show_footer=True, style="dim", border_style="not dim", expand=True
507 )
508 table.add_column("Header 1", "Footer 1")
509 table.add_column("Header 2", "Footer 2")
510 table.add_row("Cell", "Cell")
511 table.add_row("Cell", "Cell")
512 table.box = getattr(box, box_name)
513 table.title = Text(f"box.{box_name}", style="magenta")
514 columns.add_renderable(table)
515 console.print(columns)
516
517 # console.save_svg("box.svg")