Воркед
This commit is contained in:
1 parent
ac32c55ab9
commit
ee94d8e529
1138 files changed
+55771
-77901
No files matched your search
@@ -5,7 +5,7 @@ from typing import IO, TYPE_CHECKING, Any, Callable, Optional, Union
|
||||
|
||||
from ._extension import load_ipython_extension # noqa: F401
|
||||
|
||||
__all__ = ["get_console", "reconfigure", "print", "inspect"]
|
||||
__all__ = ["get_console", "reconfigure", "print", "inspect", "print_json"]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .console import Console
|
||||
@@ -40,7 +40,8 @@ def reconfigure(*args: Any, **kwargs: Any) -> None:
|
||||
"""Reconfigures the global console by replacing it with another.
|
||||
|
||||
Args:
|
||||
console (Console): Replacement console instance.
|
||||
*args (Any): Positional arguments for the replacement :class:`~rich.console.Console`.
|
||||
**kwargs (Any): Keyword arguments for the replacement :class:`~rich.console.Console`.
|
||||
"""
|
||||
from pip._vendor.rich.console import Console
|
||||
|
||||
@@ -80,7 +81,7 @@ def print_json(
|
||||
indent: Union[None, int, str] = 2,
|
||||
highlight: bool = True,
|
||||
skip_keys: bool = False,
|
||||
ensure_ascii: bool = True,
|
||||
ensure_ascii: bool = False,
|
||||
check_circular: bool = True,
|
||||
allow_nan: bool = True,
|
||||
default: Optional[Callable[[Any], Any]] = None,
|
||||
|
||||
@@ -207,7 +207,6 @@ Supports much of the *markdown* __syntax__!
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
console = Console(
|
||||
file=io.StringIO(),
|
||||
force_terminal=True,
|
||||
@@ -227,10 +226,6 @@ if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
c = Console(record=True)
|
||||
c.print(test_card)
|
||||
# c.save_svg(
|
||||
# path="/Users/darrenburns/Library/Application Support/JetBrains/PyCharm2021.3/scratches/svg_export.svg",
|
||||
# title="Rich can export to SVG",
|
||||
# )
|
||||
|
||||
print(f"rendered in {pre_cache_taken}ms (cold cache)")
|
||||
print(f"rendered in {taken}ms (warm cache)")
|
||||
@@ -247,10 +242,6 @@ if __name__ == "__main__": # pragma: no cover
|
||||
"Textualize",
|
||||
"[u blue link=https://github.com/textualize]https://github.com/textualize",
|
||||
)
|
||||
sponsor_message.add_row(
|
||||
"Buy devs a :coffee:",
|
||||
"[u blue link=https://ko-fi.com/textualize]https://ko-fi.com/textualize",
|
||||
)
|
||||
sponsor_message.add_row(
|
||||
"Twitter",
|
||||
"[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,6 +4,7 @@ CELL_WIDTHS = [
|
||||
(0, 0, 0),
|
||||
(1, 31, -1),
|
||||
(127, 159, -1),
|
||||
(173, 173, 0),
|
||||
(768, 879, 0),
|
||||
(1155, 1161, 0),
|
||||
(1425, 1469, 0),
|
||||
@@ -11,13 +12,16 @@ CELL_WIDTHS = [
|
||||
(1473, 1474, 0),
|
||||
(1476, 1477, 0),
|
||||
(1479, 1479, 0),
|
||||
(1536, 1541, 0),
|
||||
(1552, 1562, 0),
|
||||
(1564, 1564, 0),
|
||||
(1611, 1631, 0),
|
||||
(1648, 1648, 0),
|
||||
(1750, 1756, 0),
|
||||
(1750, 1757, 0),
|
||||
(1759, 1764, 0),
|
||||
(1767, 1768, 0),
|
||||
(1770, 1773, 0),
|
||||
(1807, 1807, 0),
|
||||
(1809, 1809, 0),
|
||||
(1840, 1866, 0),
|
||||
(1958, 1968, 0),
|
||||
@@ -28,149 +32,137 @@ CELL_WIDTHS = [
|
||||
(2085, 2087, 0),
|
||||
(2089, 2093, 0),
|
||||
(2137, 2139, 0),
|
||||
(2259, 2273, 0),
|
||||
(2275, 2306, 0),
|
||||
(2362, 2362, 0),
|
||||
(2364, 2364, 0),
|
||||
(2369, 2376, 0),
|
||||
(2381, 2381, 0),
|
||||
(2192, 2193, 0),
|
||||
(2200, 2207, 0),
|
||||
(2250, 2307, 0),
|
||||
(2362, 2364, 0),
|
||||
(2366, 2383, 0),
|
||||
(2385, 2391, 0),
|
||||
(2402, 2403, 0),
|
||||
(2433, 2433, 0),
|
||||
(2433, 2435, 0),
|
||||
(2492, 2492, 0),
|
||||
(2497, 2500, 0),
|
||||
(2509, 2509, 0),
|
||||
(2494, 2500, 0),
|
||||
(2503, 2504, 0),
|
||||
(2507, 2509, 0),
|
||||
(2519, 2519, 0),
|
||||
(2530, 2531, 0),
|
||||
(2558, 2558, 0),
|
||||
(2561, 2562, 0),
|
||||
(2561, 2563, 0),
|
||||
(2620, 2620, 0),
|
||||
(2625, 2626, 0),
|
||||
(2622, 2626, 0),
|
||||
(2631, 2632, 0),
|
||||
(2635, 2637, 0),
|
||||
(2641, 2641, 0),
|
||||
(2672, 2673, 0),
|
||||
(2677, 2677, 0),
|
||||
(2689, 2690, 0),
|
||||
(2689, 2691, 0),
|
||||
(2748, 2748, 0),
|
||||
(2753, 2757, 0),
|
||||
(2759, 2760, 0),
|
||||
(2765, 2765, 0),
|
||||
(2750, 2757, 0),
|
||||
(2759, 2761, 0),
|
||||
(2763, 2765, 0),
|
||||
(2786, 2787, 0),
|
||||
(2810, 2815, 0),
|
||||
(2817, 2817, 0),
|
||||
(2817, 2819, 0),
|
||||
(2876, 2876, 0),
|
||||
(2879, 2879, 0),
|
||||
(2881, 2884, 0),
|
||||
(2893, 2893, 0),
|
||||
(2901, 2902, 0),
|
||||
(2878, 2884, 0),
|
||||
(2887, 2888, 0),
|
||||
(2891, 2893, 0),
|
||||
(2901, 2903, 0),
|
||||
(2914, 2915, 0),
|
||||
(2946, 2946, 0),
|
||||
(3008, 3008, 0),
|
||||
(3021, 3021, 0),
|
||||
(3072, 3072, 0),
|
||||
(3076, 3076, 0),
|
||||
(3134, 3136, 0),
|
||||
(3006, 3010, 0),
|
||||
(3014, 3016, 0),
|
||||
(3018, 3021, 0),
|
||||
(3031, 3031, 0),
|
||||
(3072, 3076, 0),
|
||||
(3132, 3132, 0),
|
||||
(3134, 3140, 0),
|
||||
(3142, 3144, 0),
|
||||
(3146, 3149, 0),
|
||||
(3157, 3158, 0),
|
||||
(3170, 3171, 0),
|
||||
(3201, 3201, 0),
|
||||
(3201, 3203, 0),
|
||||
(3260, 3260, 0),
|
||||
(3263, 3263, 0),
|
||||
(3270, 3270, 0),
|
||||
(3276, 3277, 0),
|
||||
(3262, 3268, 0),
|
||||
(3270, 3272, 0),
|
||||
(3274, 3277, 0),
|
||||
(3285, 3286, 0),
|
||||
(3298, 3299, 0),
|
||||
(3328, 3329, 0),
|
||||
(3315, 3315, 0),
|
||||
(3328, 3331, 0),
|
||||
(3387, 3388, 0),
|
||||
(3393, 3396, 0),
|
||||
(3405, 3405, 0),
|
||||
(3390, 3396, 0),
|
||||
(3398, 3400, 0),
|
||||
(3402, 3405, 0),
|
||||
(3415, 3415, 0),
|
||||
(3426, 3427, 0),
|
||||
(3457, 3457, 0),
|
||||
(3457, 3459, 0),
|
||||
(3530, 3530, 0),
|
||||
(3538, 3540, 0),
|
||||
(3535, 3540, 0),
|
||||
(3542, 3542, 0),
|
||||
(3544, 3551, 0),
|
||||
(3570, 3571, 0),
|
||||
(3633, 3633, 0),
|
||||
(3636, 3642, 0),
|
||||
(3655, 3662, 0),
|
||||
(3761, 3761, 0),
|
||||
(3764, 3772, 0),
|
||||
(3784, 3789, 0),
|
||||
(3784, 3790, 0),
|
||||
(3864, 3865, 0),
|
||||
(3893, 3893, 0),
|
||||
(3895, 3895, 0),
|
||||
(3897, 3897, 0),
|
||||
(3953, 3966, 0),
|
||||
(3968, 3972, 0),
|
||||
(3902, 3903, 0),
|
||||
(3953, 3972, 0),
|
||||
(3974, 3975, 0),
|
||||
(3981, 3991, 0),
|
||||
(3993, 4028, 0),
|
||||
(4038, 4038, 0),
|
||||
(4141, 4144, 0),
|
||||
(4146, 4151, 0),
|
||||
(4153, 4154, 0),
|
||||
(4157, 4158, 0),
|
||||
(4184, 4185, 0),
|
||||
(4139, 4158, 0),
|
||||
(4182, 4185, 0),
|
||||
(4190, 4192, 0),
|
||||
(4194, 4196, 0),
|
||||
(4199, 4205, 0),
|
||||
(4209, 4212, 0),
|
||||
(4226, 4226, 0),
|
||||
(4229, 4230, 0),
|
||||
(4237, 4237, 0),
|
||||
(4253, 4253, 0),
|
||||
(4226, 4237, 0),
|
||||
(4239, 4239, 0),
|
||||
(4250, 4253, 0),
|
||||
(4352, 4447, 2),
|
||||
(4448, 4607, 0),
|
||||
(4957, 4959, 0),
|
||||
(5906, 5908, 0),
|
||||
(5906, 5909, 0),
|
||||
(5938, 5940, 0),
|
||||
(5970, 5971, 0),
|
||||
(6002, 6003, 0),
|
||||
(6068, 6069, 0),
|
||||
(6071, 6077, 0),
|
||||
(6086, 6086, 0),
|
||||
(6089, 6099, 0),
|
||||
(6068, 6099, 0),
|
||||
(6109, 6109, 0),
|
||||
(6155, 6157, 0),
|
||||
(6155, 6159, 0),
|
||||
(6277, 6278, 0),
|
||||
(6313, 6313, 0),
|
||||
(6432, 6434, 0),
|
||||
(6439, 6440, 0),
|
||||
(6450, 6450, 0),
|
||||
(6457, 6459, 0),
|
||||
(6679, 6680, 0),
|
||||
(6683, 6683, 0),
|
||||
(6742, 6742, 0),
|
||||
(6744, 6750, 0),
|
||||
(6752, 6752, 0),
|
||||
(6754, 6754, 0),
|
||||
(6757, 6764, 0),
|
||||
(6771, 6780, 0),
|
||||
(6432, 6443, 0),
|
||||
(6448, 6459, 0),
|
||||
(6679, 6683, 0),
|
||||
(6741, 6750, 0),
|
||||
(6752, 6780, 0),
|
||||
(6783, 6783, 0),
|
||||
(6832, 6848, 0),
|
||||
(6912, 6915, 0),
|
||||
(6964, 6964, 0),
|
||||
(6966, 6970, 0),
|
||||
(6972, 6972, 0),
|
||||
(6978, 6978, 0),
|
||||
(6832, 6862, 0),
|
||||
(6912, 6916, 0),
|
||||
(6964, 6980, 0),
|
||||
(7019, 7027, 0),
|
||||
(7040, 7041, 0),
|
||||
(7074, 7077, 0),
|
||||
(7080, 7081, 0),
|
||||
(7083, 7085, 0),
|
||||
(7142, 7142, 0),
|
||||
(7144, 7145, 0),
|
||||
(7149, 7149, 0),
|
||||
(7151, 7153, 0),
|
||||
(7212, 7219, 0),
|
||||
(7222, 7223, 0),
|
||||
(7040, 7042, 0),
|
||||
(7073, 7085, 0),
|
||||
(7142, 7155, 0),
|
||||
(7204, 7223, 0),
|
||||
(7376, 7378, 0),
|
||||
(7380, 7392, 0),
|
||||
(7394, 7400, 0),
|
||||
(7380, 7400, 0),
|
||||
(7405, 7405, 0),
|
||||
(7412, 7412, 0),
|
||||
(7416, 7417, 0),
|
||||
(7616, 7673, 0),
|
||||
(7675, 7679, 0),
|
||||
(7415, 7417, 0),
|
||||
(7616, 7679, 0),
|
||||
(8203, 8207, 0),
|
||||
(8232, 8238, 0),
|
||||
(8288, 8291, 0),
|
||||
(8288, 8292, 0),
|
||||
(8294, 8303, 0),
|
||||
(8400, 8432, 0),
|
||||
(8986, 8987, 2),
|
||||
(9001, 9002, 2),
|
||||
@@ -212,17 +204,16 @@ CELL_WIDTHS = [
|
||||
(11904, 11929, 2),
|
||||
(11931, 12019, 2),
|
||||
(12032, 12245, 2),
|
||||
(12272, 12283, 2),
|
||||
(12288, 12329, 2),
|
||||
(12330, 12333, 0),
|
||||
(12334, 12350, 2),
|
||||
(12272, 12329, 2),
|
||||
(12330, 12335, 0),
|
||||
(12336, 12350, 2),
|
||||
(12353, 12438, 2),
|
||||
(12441, 12442, 0),
|
||||
(12443, 12543, 2),
|
||||
(12549, 12591, 2),
|
||||
(12593, 12686, 2),
|
||||
(12688, 12771, 2),
|
||||
(12784, 12830, 2),
|
||||
(12783, 12830, 2),
|
||||
(12832, 12871, 2),
|
||||
(12880, 19903, 2),
|
||||
(19968, 42124, 2),
|
||||
@@ -234,36 +225,33 @@ CELL_WIDTHS = [
|
||||
(43010, 43010, 0),
|
||||
(43014, 43014, 0),
|
||||
(43019, 43019, 0),
|
||||
(43045, 43046, 0),
|
||||
(43043, 43047, 0),
|
||||
(43052, 43052, 0),
|
||||
(43204, 43205, 0),
|
||||
(43136, 43137, 0),
|
||||
(43188, 43205, 0),
|
||||
(43232, 43249, 0),
|
||||
(43263, 43263, 0),
|
||||
(43302, 43309, 0),
|
||||
(43335, 43345, 0),
|
||||
(43335, 43347, 0),
|
||||
(43360, 43388, 2),
|
||||
(43392, 43394, 0),
|
||||
(43443, 43443, 0),
|
||||
(43446, 43449, 0),
|
||||
(43452, 43453, 0),
|
||||
(43392, 43395, 0),
|
||||
(43443, 43456, 0),
|
||||
(43493, 43493, 0),
|
||||
(43561, 43566, 0),
|
||||
(43569, 43570, 0),
|
||||
(43573, 43574, 0),
|
||||
(43561, 43574, 0),
|
||||
(43587, 43587, 0),
|
||||
(43596, 43596, 0),
|
||||
(43644, 43644, 0),
|
||||
(43596, 43597, 0),
|
||||
(43643, 43645, 0),
|
||||
(43696, 43696, 0),
|
||||
(43698, 43700, 0),
|
||||
(43703, 43704, 0),
|
||||
(43710, 43711, 0),
|
||||
(43713, 43713, 0),
|
||||
(43756, 43757, 0),
|
||||
(43766, 43766, 0),
|
||||
(44005, 44005, 0),
|
||||
(44008, 44008, 0),
|
||||
(44013, 44013, 0),
|
||||
(43755, 43759, 0),
|
||||
(43765, 43766, 0),
|
||||
(44003, 44010, 0),
|
||||
(44012, 44013, 0),
|
||||
(44032, 55203, 2),
|
||||
(55216, 55295, 0),
|
||||
(63744, 64255, 2),
|
||||
(64286, 64286, 0),
|
||||
(65024, 65039, 0),
|
||||
@@ -272,8 +260,10 @@ CELL_WIDTHS = [
|
||||
(65072, 65106, 2),
|
||||
(65108, 65126, 2),
|
||||
(65128, 65131, 2),
|
||||
(65279, 65279, 0),
|
||||
(65281, 65376, 2),
|
||||
(65504, 65510, 2),
|
||||
(65529, 65531, 0),
|
||||
(66045, 66045, 0),
|
||||
(66272, 66272, 0),
|
||||
(66422, 66426, 0),
|
||||
@@ -285,102 +275,108 @@ CELL_WIDTHS = [
|
||||
(68325, 68326, 0),
|
||||
(68900, 68903, 0),
|
||||
(69291, 69292, 0),
|
||||
(69373, 69375, 0),
|
||||
(69446, 69456, 0),
|
||||
(69633, 69633, 0),
|
||||
(69506, 69509, 0),
|
||||
(69632, 69634, 0),
|
||||
(69688, 69702, 0),
|
||||
(69759, 69761, 0),
|
||||
(69811, 69814, 0),
|
||||
(69817, 69818, 0),
|
||||
(69744, 69744, 0),
|
||||
(69747, 69748, 0),
|
||||
(69759, 69762, 0),
|
||||
(69808, 69818, 0),
|
||||
(69821, 69821, 0),
|
||||
(69826, 69826, 0),
|
||||
(69837, 69837, 0),
|
||||
(69888, 69890, 0),
|
||||
(69927, 69931, 0),
|
||||
(69933, 69940, 0),
|
||||
(69927, 69940, 0),
|
||||
(69957, 69958, 0),
|
||||
(70003, 70003, 0),
|
||||
(70016, 70017, 0),
|
||||
(70070, 70078, 0),
|
||||
(70016, 70018, 0),
|
||||
(70067, 70080, 0),
|
||||
(70089, 70092, 0),
|
||||
(70095, 70095, 0),
|
||||
(70191, 70193, 0),
|
||||
(70196, 70196, 0),
|
||||
(70198, 70199, 0),
|
||||
(70094, 70095, 0),
|
||||
(70188, 70199, 0),
|
||||
(70206, 70206, 0),
|
||||
(70367, 70367, 0),
|
||||
(70371, 70378, 0),
|
||||
(70400, 70401, 0),
|
||||
(70209, 70209, 0),
|
||||
(70367, 70378, 0),
|
||||
(70400, 70403, 0),
|
||||
(70459, 70460, 0),
|
||||
(70464, 70464, 0),
|
||||
(70462, 70468, 0),
|
||||
(70471, 70472, 0),
|
||||
(70475, 70477, 0),
|
||||
(70487, 70487, 0),
|
||||
(70498, 70499, 0),
|
||||
(70502, 70508, 0),
|
||||
(70512, 70516, 0),
|
||||
(70712, 70719, 0),
|
||||
(70722, 70724, 0),
|
||||
(70726, 70726, 0),
|
||||
(70709, 70726, 0),
|
||||
(70750, 70750, 0),
|
||||
(70835, 70840, 0),
|
||||
(70842, 70842, 0),
|
||||
(70847, 70848, 0),
|
||||
(70850, 70851, 0),
|
||||
(71090, 71093, 0),
|
||||
(71100, 71101, 0),
|
||||
(71103, 71104, 0),
|
||||
(70832, 70851, 0),
|
||||
(71087, 71093, 0),
|
||||
(71096, 71104, 0),
|
||||
(71132, 71133, 0),
|
||||
(71219, 71226, 0),
|
||||
(71229, 71229, 0),
|
||||
(71231, 71232, 0),
|
||||
(71339, 71339, 0),
|
||||
(71341, 71341, 0),
|
||||
(71344, 71349, 0),
|
||||
(71351, 71351, 0),
|
||||
(71453, 71455, 0),
|
||||
(71458, 71461, 0),
|
||||
(71463, 71467, 0),
|
||||
(71727, 71735, 0),
|
||||
(71737, 71738, 0),
|
||||
(71995, 71996, 0),
|
||||
(71998, 71998, 0),
|
||||
(72003, 72003, 0),
|
||||
(72148, 72151, 0),
|
||||
(72154, 72155, 0),
|
||||
(72160, 72160, 0),
|
||||
(71216, 71232, 0),
|
||||
(71339, 71351, 0),
|
||||
(71453, 71467, 0),
|
||||
(71724, 71738, 0),
|
||||
(71984, 71989, 0),
|
||||
(71991, 71992, 0),
|
||||
(71995, 71998, 0),
|
||||
(72000, 72000, 0),
|
||||
(72002, 72003, 0),
|
||||
(72145, 72151, 0),
|
||||
(72154, 72160, 0),
|
||||
(72164, 72164, 0),
|
||||
(72193, 72202, 0),
|
||||
(72243, 72248, 0),
|
||||
(72243, 72249, 0),
|
||||
(72251, 72254, 0),
|
||||
(72263, 72263, 0),
|
||||
(72273, 72278, 0),
|
||||
(72281, 72283, 0),
|
||||
(72330, 72342, 0),
|
||||
(72344, 72345, 0),
|
||||
(72752, 72758, 0),
|
||||
(72760, 72765, 0),
|
||||
(72767, 72767, 0),
|
||||
(72273, 72283, 0),
|
||||
(72330, 72345, 0),
|
||||
(72751, 72758, 0),
|
||||
(72760, 72767, 0),
|
||||
(72850, 72871, 0),
|
||||
(72874, 72880, 0),
|
||||
(72882, 72883, 0),
|
||||
(72885, 72886, 0),
|
||||
(72873, 72886, 0),
|
||||
(73009, 73014, 0),
|
||||
(73018, 73018, 0),
|
||||
(73020, 73021, 0),
|
||||
(73023, 73029, 0),
|
||||
(73031, 73031, 0),
|
||||
(73098, 73102, 0),
|
||||
(73104, 73105, 0),
|
||||
(73109, 73109, 0),
|
||||
(73111, 73111, 0),
|
||||
(73459, 73460, 0),
|
||||
(73107, 73111, 0),
|
||||
(73459, 73462, 0),
|
||||
(73472, 73473, 0),
|
||||
(73475, 73475, 0),
|
||||
(73524, 73530, 0),
|
||||
(73534, 73538, 0),
|
||||
(78896, 78912, 0),
|
||||
(78919, 78933, 0),
|
||||
(92912, 92916, 0),
|
||||
(92976, 92982, 0),
|
||||
(94031, 94031, 0),
|
||||
(94033, 94087, 0),
|
||||
(94095, 94098, 0),
|
||||
(94176, 94179, 2),
|
||||
(94180, 94180, 0),
|
||||
(94192, 94193, 2),
|
||||
(94192, 94193, 0),
|
||||
(94208, 100343, 2),
|
||||
(100352, 101589, 2),
|
||||
(101632, 101640, 2),
|
||||
(110592, 110878, 2),
|
||||
(110576, 110579, 2),
|
||||
(110581, 110587, 2),
|
||||
(110589, 110590, 2),
|
||||
(110592, 110882, 2),
|
||||
(110898, 110898, 2),
|
||||
(110928, 110930, 2),
|
||||
(110933, 110933, 2),
|
||||
(110948, 110951, 2),
|
||||
(110960, 111355, 2),
|
||||
(113821, 113822, 0),
|
||||
(119143, 119145, 0),
|
||||
(119163, 119170, 0),
|
||||
(113824, 113827, 0),
|
||||
(118528, 118573, 0),
|
||||
(118576, 118598, 0),
|
||||
(119141, 119145, 0),
|
||||
(119149, 119170, 0),
|
||||
(119173, 119179, 0),
|
||||
(119210, 119213, 0),
|
||||
(119362, 119364, 0),
|
||||
@@ -395,8 +391,11 @@ CELL_WIDTHS = [
|
||||
(122907, 122913, 0),
|
||||
(122915, 122916, 0),
|
||||
(122918, 122922, 0),
|
||||
(123023, 123023, 0),
|
||||
(123184, 123190, 0),
|
||||
(123566, 123566, 0),
|
||||
(123628, 123631, 0),
|
||||
(124140, 124143, 0),
|
||||
(125136, 125142, 0),
|
||||
(125252, 125258, 0),
|
||||
(126980, 126980, 2),
|
||||
@@ -416,7 +415,9 @@ CELL_WIDTHS = [
|
||||
(127951, 127955, 2),
|
||||
(127968, 127984, 2),
|
||||
(127988, 127988, 2),
|
||||
(127992, 128062, 2),
|
||||
(127992, 127994, 2),
|
||||
(127995, 127999, 0),
|
||||
(128000, 128062, 2),
|
||||
(128064, 128064, 2),
|
||||
(128066, 128252, 2),
|
||||
(128255, 128317, 2),
|
||||
@@ -430,22 +431,24 @@ CELL_WIDTHS = [
|
||||
(128716, 128716, 2),
|
||||
(128720, 128722, 2),
|
||||
(128725, 128727, 2),
|
||||
(128732, 128735, 2),
|
||||
(128747, 128748, 2),
|
||||
(128756, 128764, 2),
|
||||
(128992, 129003, 2),
|
||||
(129008, 129008, 2),
|
||||
(129292, 129338, 2),
|
||||
(129340, 129349, 2),
|
||||
(129351, 129400, 2),
|
||||
(129402, 129483, 2),
|
||||
(129485, 129535, 2),
|
||||
(129648, 129652, 2),
|
||||
(129656, 129658, 2),
|
||||
(129664, 129670, 2),
|
||||
(129680, 129704, 2),
|
||||
(129712, 129718, 2),
|
||||
(129728, 129730, 2),
|
||||
(129744, 129750, 2),
|
||||
(129351, 129535, 2),
|
||||
(129648, 129660, 2),
|
||||
(129664, 129672, 2),
|
||||
(129680, 129725, 2),
|
||||
(129727, 129733, 2),
|
||||
(129742, 129755, 2),
|
||||
(129760, 129768, 2),
|
||||
(129776, 129784, 2),
|
||||
(131072, 196605, 2),
|
||||
(196608, 262141, 2),
|
||||
(917505, 917505, 0),
|
||||
(917536, 917631, 0),
|
||||
(917760, 917999, 0),
|
||||
]
|
||||
@@ -1,5 +1,6 @@
|
||||
CONSOLE_HTML_FORMAT = """\
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
@@ -10,11 +11,8 @@ body {{
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<html>
|
||||
<body>
|
||||
<code>
|
||||
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">{code}</pre>
|
||||
</code>
|
||||
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><code style="font-family:inherit">{code}</code></pre>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import IO, Callable
|
||||
|
||||
|
||||
def get_fileno(file_like: IO[str]) -> int | None:
|
||||
"""Get fileno() from a file, accounting for poorly implemented file-like objects.
|
||||
|
||||
Args:
|
||||
file_like (IO): A file-like object.
|
||||
|
||||
Returns:
|
||||
int | None: The result of fileno if available, or None if operation failed.
|
||||
"""
|
||||
fileno: Callable[[], int] | None = getattr(file_like, "fileno", None)
|
||||
if fileno is not None:
|
||||
try:
|
||||
return fileno()
|
||||
except Exception:
|
||||
# `fileno` is documented as potentially raising a OSError
|
||||
# Alas, from the issues, there are so many poorly implemented file-like objects,
|
||||
# that `fileno()` can raise just about anything.
|
||||
return None
|
||||
return None
|
||||
@@ -1,5 +1,3 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import inspect
|
||||
from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature
|
||||
from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
from types import TracebackType
|
||||
from typing import IO, Iterable, Iterator, List, Optional, Type
|
||||
|
||||
|
||||
class NullFile(IO[str]):
|
||||
def close(self) -> None:
|
||||
pass
|
||||
|
||||
def isatty(self) -> bool:
|
||||
return False
|
||||
|
||||
def read(self, __n: int = 1) -> str:
|
||||
return ""
|
||||
|
||||
def readable(self) -> bool:
|
||||
return False
|
||||
|
||||
def readline(self, __limit: int = 1) -> str:
|
||||
return ""
|
||||
|
||||
def readlines(self, __hint: int = 1) -> List[str]:
|
||||
return []
|
||||
|
||||
def seek(self, __offset: int, __whence: int = 1) -> int:
|
||||
return 0
|
||||
|
||||
def seekable(self) -> bool:
|
||||
return False
|
||||
|
||||
def tell(self) -> int:
|
||||
return 0
|
||||
|
||||
def truncate(self, __size: Optional[int] = 1) -> int:
|
||||
return 0
|
||||
|
||||
def writable(self) -> bool:
|
||||
return False
|
||||
|
||||
def writelines(self, __lines: Iterable[str]) -> None:
|
||||
pass
|
||||
|
||||
def __next__(self) -> str:
|
||||
return ""
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
return iter([""])
|
||||
|
||||
def __enter__(self) -> IO[str]:
|
||||
return self
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
__t: Optional[Type[BaseException]],
|
||||
__value: Optional[BaseException],
|
||||
__traceback: Optional[TracebackType],
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
def write(self, text: str) -> int:
|
||||
return 0
|
||||
|
||||
def flush(self) -> None:
|
||||
pass
|
||||
|
||||
def fileno(self) -> int:
|
||||
return -1
|
||||
|
||||
|
||||
NULL_FILE = NullFile()
|
||||
@@ -151,7 +151,6 @@ if __name__ == "__main__":
|
||||
|
||||
@dataclass
|
||||
class E:
|
||||
|
||||
size: Optional[int] = None
|
||||
ratio: int = 1
|
||||
minimum_size: int = 1
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
from typing import Any
|
||||
@@ -380,7 +381,7 @@ class LegacyWindowsTerm:
|
||||
WindowsCoordinates: The current cursor position.
|
||||
"""
|
||||
coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition
|
||||
return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X))
|
||||
return WindowsCoordinates(row=coord.Y, col=coord.X)
|
||||
|
||||
@property
|
||||
def screen_size(self) -> WindowsCoordinates:
|
||||
@@ -390,9 +391,7 @@ class LegacyWindowsTerm:
|
||||
WindowsCoordinates: The width and height of the screen as WindowsCoordinates.
|
||||
"""
|
||||
screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize
|
||||
return WindowsCoordinates(
|
||||
row=cast(int, screen_size.Y), col=cast(int, screen_size.X)
|
||||
)
|
||||
return WindowsCoordinates(row=screen_size.Y, col=screen_size.X)
|
||||
|
||||
def write_text(self, text: str) -> None:
|
||||
"""Write text directly to the terminal without any modification of styles
|
||||
|
||||
@@ -30,7 +30,6 @@ try:
|
||||
)
|
||||
|
||||
except (AttributeError, ImportError, ValueError):
|
||||
|
||||
# Fallback if we can't load the Windows DLL
|
||||
def get_windows_console_features() -> WindowsConsoleFeatures:
|
||||
features = WindowsConsoleFeatures()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Iterable, List, Tuple
|
||||
from typing import Iterable
|
||||
|
||||
from ._loop import loop_last
|
||||
from .cells import cell_len, chop_cells
|
||||
@@ -7,7 +9,11 @@ from .cells import cell_len, chop_cells
|
||||
re_word = re.compile(r"\s*\S+\s*")
|
||||
|
||||
|
||||
def words(text: str) -> Iterable[Tuple[int, int, str]]:
|
||||
def words(text: str) -> Iterable[tuple[int, int, str]]:
|
||||
"""Yields each word from the text as a tuple
|
||||
containing (start_index, end_index, word). A "word" in this context may
|
||||
include the actual word and any whitespace to the right.
|
||||
"""
|
||||
position = 0
|
||||
word_match = re_word.match(text, position)
|
||||
while word_match is not None:
|
||||
@@ -17,35 +23,59 @@ def words(text: str) -> Iterable[Tuple[int, int, str]]:
|
||||
word_match = re_word.match(text, end)
|
||||
|
||||
|
||||
def divide_line(text: str, width: int, fold: bool = True) -> List[int]:
|
||||
divides: List[int] = []
|
||||
append = divides.append
|
||||
line_position = 0
|
||||
def divide_line(text: str, width: int, fold: bool = True) -> list[int]:
|
||||
"""Given a string of text, and a width (measured in cells), return a list
|
||||
of cell offsets which the string should be split at in order for it to fit
|
||||
within the given width.
|
||||
|
||||
Args:
|
||||
text: The text to examine.
|
||||
width: The available cell width.
|
||||
fold: If True, words longer than `width` will be folded onto a new line.
|
||||
|
||||
Returns:
|
||||
A list of indices to break the line at.
|
||||
"""
|
||||
break_positions: list[int] = [] # offsets to insert the breaks at
|
||||
append = break_positions.append
|
||||
cell_offset = 0
|
||||
_cell_len = cell_len
|
||||
|
||||
for start, _end, word in words(text):
|
||||
word_length = _cell_len(word.rstrip())
|
||||
if line_position + word_length > width:
|
||||
remaining_space = width - cell_offset
|
||||
word_fits_remaining_space = remaining_space >= word_length
|
||||
|
||||
if word_fits_remaining_space:
|
||||
# Simplest case - the word fits within the remaining width for this line.
|
||||
cell_offset += _cell_len(word)
|
||||
else:
|
||||
# Not enough space remaining for this word on the current line.
|
||||
if word_length > width:
|
||||
# The word doesn't fit on any line, so we can't simply
|
||||
# place it on the next line...
|
||||
if fold:
|
||||
chopped_words = chop_cells(word, max_size=width, position=0)
|
||||
for last, line in loop_last(chopped_words):
|
||||
# Fold the word across multiple lines.
|
||||
folded_word = chop_cells(word, width=width)
|
||||
for last, line in loop_last(folded_word):
|
||||
if start:
|
||||
append(start)
|
||||
|
||||
if last:
|
||||
line_position = _cell_len(line)
|
||||
cell_offset = _cell_len(line)
|
||||
else:
|
||||
start += len(line)
|
||||
else:
|
||||
# Folding isn't allowed, so crop the word.
|
||||
if start:
|
||||
append(start)
|
||||
line_position = _cell_len(word)
|
||||
elif line_position and start:
|
||||
cell_offset = _cell_len(word)
|
||||
elif cell_offset and start:
|
||||
# The word doesn't fit within the remaining space on the current
|
||||
# line, but it *can* fit on to the next (empty) line.
|
||||
append(start)
|
||||
line_position = _cell_len(word)
|
||||
else:
|
||||
line_position += _cell_len(word)
|
||||
return divides
|
||||
cell_offset = _cell_len(word)
|
||||
|
||||
return break_positions
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
@@ -53,4 +83,11 @@ if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
console = Console(width=10)
|
||||
console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345")
|
||||
print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10, position=2))
|
||||
print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10))
|
||||
|
||||
console = Console(width=20)
|
||||
console.rule()
|
||||
console.print("TextualはPythonの高速アプリケーション開発フレームワークです")
|
||||
|
||||
console.rule()
|
||||
console.print("アプリケーションは1670万色を使用でき")
|
||||
@@ -27,7 +27,7 @@ class Align(JupyterMixin):
|
||||
renderable (RenderableType): A console renderable.
|
||||
align (AlignMethod): One of "left", "center", or "right""
|
||||
style (StyleType, optional): An optional style to apply to the background.
|
||||
vertical (Optional[VerticalAlginMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None.
|
||||
vertical (Optional[VerticalAlignMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None.
|
||||
pad (bool, optional): Pad the right with spaces. Defaults to True.
|
||||
width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None.
|
||||
height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None.
|
||||
@@ -240,6 +240,7 @@ class VerticalCenter(JupyterMixin):
|
||||
|
||||
Args:
|
||||
renderable (RenderableType): A renderable object.
|
||||
style (StyleType, optional): An optional style to apply to the background. Defaults to None.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -303,7 +304,7 @@ if __name__ == "__main__": # pragma: no cover
|
||||
),
|
||||
width=60,
|
||||
style="on dark_blue",
|
||||
title="Algin",
|
||||
title="Align",
|
||||
)
|
||||
|
||||
console.print(
|
||||
|
||||
@@ -9,6 +9,7 @@ from .text import Text
|
||||
|
||||
re_ansi = re.compile(
|
||||
r"""
|
||||
(?:\x1b[0-?])|
|
||||
(?:\x1b\](.*?)\x1b\\)|
|
||||
(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~]))
|
||||
""",
|
||||
@@ -43,6 +44,9 @@ def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]:
|
||||
if start > position:
|
||||
yield _AnsiToken(ansi_text[position:start])
|
||||
if sgr:
|
||||
if sgr == "(":
|
||||
position = end + 1
|
||||
continue
|
||||
if sgr.endswith("m"):
|
||||
yield _AnsiToken("", sgr[1:-1], osc)
|
||||
else:
|
||||
@@ -120,7 +124,7 @@ class AnsiDecoder:
|
||||
self.style = Style.null()
|
||||
|
||||
def decode(self, terminal_text: str) -> Iterable[Text]:
|
||||
"""Decode ANSI codes in an interable of lines.
|
||||
"""Decode ANSI codes in an iterable of lines.
|
||||
|
||||
Args:
|
||||
lines (Iterable[str]): An iterable of lines of terminal output.
|
||||
|
||||
@@ -48,7 +48,6 @@ class Bar(JupyterMixin):
|
||||
def __rich_console__(
|
||||
self, console: Console, options: ConsoleOptions
|
||||
) -> RenderResult:
|
||||
|
||||
width = min(
|
||||
self.width if self.width is not None else options.max_width,
|
||||
options.max_width,
|
||||
|
||||
@@ -188,260 +188,224 @@ class Box:
|
||||
return "".join(parts)
|
||||
|
||||
|
||||
# fmt: off
|
||||
ASCII: Box = Box(
|
||||
"""\
|
||||
+--+
|
||||
| ||
|
||||
|-+|
|
||||
| ||
|
||||
|-+|
|
||||
|-+|
|
||||
| ||
|
||||
+--+
|
||||
""",
|
||||
"+--+\n"
|
||||
"| ||\n"
|
||||
"|-+|\n"
|
||||
"| ||\n"
|
||||
"|-+|\n"
|
||||
"|-+|\n"
|
||||
"| ||\n"
|
||||
"+--+\n",
|
||||
ascii=True,
|
||||
)
|
||||
|
||||
ASCII2: Box = Box(
|
||||
"""\
|
||||
+-++
|
||||
| ||
|
||||
+-++
|
||||
| ||
|
||||
+-++
|
||||
+-++
|
||||
| ||
|
||||
+-++
|
||||
""",
|
||||
"+-++\n"
|
||||
"| ||\n"
|
||||
"+-++\n"
|
||||
"| ||\n"
|
||||
"+-++\n"
|
||||
"+-++\n"
|
||||
"| ||\n"
|
||||
"+-++\n",
|
||||
ascii=True,
|
||||
)
|
||||
|
||||
ASCII_DOUBLE_HEAD: Box = Box(
|
||||
"""\
|
||||
+-++
|
||||
| ||
|
||||
+=++
|
||||
| ||
|
||||
+-++
|
||||
+-++
|
||||
| ||
|
||||
+-++
|
||||
""",
|
||||
"+-++\n"
|
||||
"| ||\n"
|
||||
"+=++\n"
|
||||
"| ||\n"
|
||||
"+-++\n"
|
||||
"+-++\n"
|
||||
"| ||\n"
|
||||
"+-++\n",
|
||||
ascii=True,
|
||||
)
|
||||
|
||||
SQUARE: Box = Box(
|
||||
"""\
|
||||
┌─┬┐
|
||||
│ ││
|
||||
├─┼┤
|
||||
│ ││
|
||||
├─┼┤
|
||||
├─┼┤
|
||||
│ ││
|
||||
└─┴┘
|
||||
"""
|
||||
"┌─┬┐\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"└─┴┘\n"
|
||||
)
|
||||
|
||||
SQUARE_DOUBLE_HEAD: Box = Box(
|
||||
"""\
|
||||
┌─┬┐
|
||||
│ ││
|
||||
╞═╪╡
|
||||
│ ││
|
||||
├─┼┤
|
||||
├─┼┤
|
||||
│ ││
|
||||
└─┴┘
|
||||
"""
|
||||
"┌─┬┐\n"
|
||||
"│ ││\n"
|
||||
"╞═╪╡\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"└─┴┘\n"
|
||||
)
|
||||
|
||||
MINIMAL: Box = Box(
|
||||
"""\
|
||||
╷
|
||||
│
|
||||
╶─┼╴
|
||||
│
|
||||
╶─┼╴
|
||||
╶─┼╴
|
||||
│
|
||||
╵
|
||||
"""
|
||||
" ╷ \n"
|
||||
" │ \n"
|
||||
"╶─┼╴\n"
|
||||
" │ \n"
|
||||
"╶─┼╴\n"
|
||||
"╶─┼╴\n"
|
||||
" │ \n"
|
||||
" ╵ \n"
|
||||
)
|
||||
|
||||
|
||||
MINIMAL_HEAVY_HEAD: Box = Box(
|
||||
"""\
|
||||
╷
|
||||
│
|
||||
╺━┿╸
|
||||
│
|
||||
╶─┼╴
|
||||
╶─┼╴
|
||||
│
|
||||
╵
|
||||
"""
|
||||
" ╷ \n"
|
||||
" │ \n"
|
||||
"╺━┿╸\n"
|
||||
" │ \n"
|
||||
"╶─┼╴\n"
|
||||
"╶─┼╴\n"
|
||||
" │ \n"
|
||||
" ╵ \n"
|
||||
)
|
||||
|
||||
MINIMAL_DOUBLE_HEAD: Box = Box(
|
||||
"""\
|
||||
╷
|
||||
│
|
||||
═╪
|
||||
│
|
||||
─┼
|
||||
─┼
|
||||
│
|
||||
╵
|
||||
"""
|
||||
" ╷ \n"
|
||||
" │ \n"
|
||||
" ═╪ \n"
|
||||
" │ \n"
|
||||
" ─┼ \n"
|
||||
" ─┼ \n"
|
||||
" │ \n"
|
||||
" ╵ \n"
|
||||
)
|
||||
|
||||
|
||||
SIMPLE: Box = Box(
|
||||
"""\
|
||||
|
||||
|
||||
──
|
||||
|
||||
|
||||
──
|
||||
|
||||
|
||||
"""
|
||||
" \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
" \n"
|
||||
" \n"
|
||||
)
|
||||
|
||||
SIMPLE_HEAD: Box = Box(
|
||||
"""\
|
||||
|
||||
|
||||
──
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
" \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
)
|
||||
|
||||
|
||||
SIMPLE_HEAVY: Box = Box(
|
||||
"""\
|
||||
|
||||
|
||||
━━
|
||||
|
||||
|
||||
━━
|
||||
|
||||
|
||||
"""
|
||||
" \n"
|
||||
" \n"
|
||||
" ━━ \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" ━━ \n"
|
||||
" \n"
|
||||
" \n"
|
||||
)
|
||||
|
||||
|
||||
HORIZONTALS: Box = Box(
|
||||
"""\
|
||||
──
|
||||
|
||||
──
|
||||
|
||||
──
|
||||
──
|
||||
|
||||
──
|
||||
"""
|
||||
" ── \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
" ── \n"
|
||||
" \n"
|
||||
" ── \n"
|
||||
)
|
||||
|
||||
ROUNDED: Box = Box(
|
||||
"""\
|
||||
╭─┬╮
|
||||
│ ││
|
||||
├─┼┤
|
||||
│ ││
|
||||
├─┼┤
|
||||
├─┼┤
|
||||
│ ││
|
||||
╰─┴╯
|
||||
"""
|
||||
"╭─┬╮\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"╰─┴╯\n"
|
||||
)
|
||||
|
||||
HEAVY: Box = Box(
|
||||
"""\
|
||||
┏━┳┓
|
||||
┃ ┃┃
|
||||
┣━╋┫
|
||||
┃ ┃┃
|
||||
┣━╋┫
|
||||
┣━╋┫
|
||||
┃ ┃┃
|
||||
┗━┻┛
|
||||
"""
|
||||
"┏━┳┓\n"
|
||||
"┃ ┃┃\n"
|
||||
"┣━╋┫\n"
|
||||
"┃ ┃┃\n"
|
||||
"┣━╋┫\n"
|
||||
"┣━╋┫\n"
|
||||
"┃ ┃┃\n"
|
||||
"┗━┻┛\n"
|
||||
)
|
||||
|
||||
HEAVY_EDGE: Box = Box(
|
||||
"""\
|
||||
┏━┯┓
|
||||
┃ │┃
|
||||
┠─┼┨
|
||||
┃ │┃
|
||||
┠─┼┨
|
||||
┠─┼┨
|
||||
┃ │┃
|
||||
┗━┷┛
|
||||
"""
|
||||
"┏━┯┓\n"
|
||||
"┃ │┃\n"
|
||||
"┠─┼┨\n"
|
||||
"┃ │┃\n"
|
||||
"┠─┼┨\n"
|
||||
"┠─┼┨\n"
|
||||
"┃ │┃\n"
|
||||
"┗━┷┛\n"
|
||||
)
|
||||
|
||||
HEAVY_HEAD: Box = Box(
|
||||
"""\
|
||||
┏━┳┓
|
||||
┃ ┃┃
|
||||
┡━╇┩
|
||||
│ ││
|
||||
├─┼┤
|
||||
├─┼┤
|
||||
│ ││
|
||||
└─┴┘
|
||||
"""
|
||||
"┏━┳┓\n"
|
||||
"┃ ┃┃\n"
|
||||
"┡━╇┩\n"
|
||||
"│ ││\n"
|
||||
"├─┼┤\n"
|
||||
"├─┼┤\n"
|
||||
"│ ││\n"
|
||||
"└─┴┘\n"
|
||||
)
|
||||
|
||||
DOUBLE: Box = Box(
|
||||
"""\
|
||||
╔═╦╗
|
||||
║ ║║
|
||||
╠═╬╣
|
||||
║ ║║
|
||||
╠═╬╣
|
||||
╠═╬╣
|
||||
║ ║║
|
||||
╚═╩╝
|
||||
"""
|
||||
"╔═╦╗\n"
|
||||
"║ ║║\n"
|
||||
"╠═╬╣\n"
|
||||
"║ ║║\n"
|
||||
"╠═╬╣\n"
|
||||
"╠═╬╣\n"
|
||||
"║ ║║\n"
|
||||
"╚═╩╝\n"
|
||||
)
|
||||
|
||||
DOUBLE_EDGE: Box = Box(
|
||||
"""\
|
||||
╔═╤╗
|
||||
║ │║
|
||||
╟─┼╢
|
||||
║ │║
|
||||
╟─┼╢
|
||||
╟─┼╢
|
||||
║ │║
|
||||
╚═╧╝
|
||||
"""
|
||||
"╔═╤╗\n"
|
||||
"║ │║\n"
|
||||
"╟─┼╢\n"
|
||||
"║ │║\n"
|
||||
"╟─┼╢\n"
|
||||
"╟─┼╢\n"
|
||||
"║ │║\n"
|
||||
"╚═╧╝\n"
|
||||
)
|
||||
|
||||
MARKDOWN: Box = Box(
|
||||
"""\
|
||||
|
||||
| ||
|
||||
|-||
|
||||
| ||
|
||||
|-||
|
||||
|-||
|
||||
| ||
|
||||
|
||||
""",
|
||||
" \n"
|
||||
"| ||\n"
|
||||
"|-||\n"
|
||||
"| ||\n"
|
||||
"|-||\n"
|
||||
"|-||\n"
|
||||
"| ||\n"
|
||||
" \n",
|
||||
ascii=True,
|
||||
)
|
||||
# fmt: on
|
||||
|
||||
# Map Boxes that don't render with raster fonts on to equivalent that do
|
||||
LEGACY_WINDOWS_SUBSTITUTIONS = {
|
||||
@@ -464,7 +428,6 @@ PLAIN_HEADED_SUBSTITUTIONS = {
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
from pip._vendor.rich.columns import Columns
|
||||
from pip._vendor.rich.panel import Panel
|
||||
|
||||
@@ -514,4 +477,4 @@ if __name__ == "__main__": # pragma: no cover
|
||||
columns.add_renderable(table)
|
||||
console.print(columns)
|
||||
|
||||
# console.save_html("box.html", inline_styles=True)
|
||||
# console.save_svg("box.svg")
|
||||
@@ -1,11 +1,33 @@
|
||||
import re
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
from typing import Callable, List
|
||||
from typing import Callable
|
||||
|
||||
from ._cell_widths import CELL_WIDTHS
|
||||
|
||||
# Regex to match sequence of the most common character ranges
|
||||
_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match
|
||||
# Ranges of unicode ordinals that produce a 1-cell wide character
|
||||
# This is non-exhaustive, but covers most common Western characters
|
||||
_SINGLE_CELL_UNICODE_RANGES: list[tuple[int, int]] = [
|
||||
(0x20, 0x7E), # Latin (excluding non-printable)
|
||||
(0xA0, 0xAC),
|
||||
(0xAE, 0x002FF),
|
||||
(0x00370, 0x00482), # Greek / Cyrillic
|
||||
(0x02500, 0x025FC), # Box drawing, box elements, geometric shapes
|
||||
(0x02800, 0x028FF), # Braille
|
||||
]
|
||||
|
||||
# A set of characters that are a single cell wide
|
||||
_SINGLE_CELLS = frozenset(
|
||||
[
|
||||
character
|
||||
for _start, _end in _SINGLE_CELL_UNICODE_RANGES
|
||||
for character in map(chr, range(_start, _end + 1))
|
||||
]
|
||||
)
|
||||
|
||||
# When called with a string this will return True if all
|
||||
# characters are single-cell, otherwise False
|
||||
_is_single_cell_widths: Callable[[str], bool] = _SINGLE_CELLS.issuperset
|
||||
|
||||
|
||||
@lru_cache(4096)
|
||||
@@ -21,9 +43,9 @@ def cached_cell_len(text: str) -> int:
|
||||
Returns:
|
||||
int: Get the number of cells required to display text.
|
||||
"""
|
||||
_get_size = get_character_cell_size
|
||||
total_size = sum(_get_size(character) for character in text)
|
||||
return total_size
|
||||
if _is_single_cell_widths(text):
|
||||
return len(text)
|
||||
return sum(map(get_character_cell_size, text))
|
||||
|
||||
|
||||
def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int:
|
||||
@@ -37,9 +59,9 @@ def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> in
|
||||
"""
|
||||
if len(text) < 512:
|
||||
return _cell_len(text)
|
||||
_get_size = get_character_cell_size
|
||||
total_size = sum(_get_size(character) for character in text)
|
||||
return total_size
|
||||
if _is_single_cell_widths(text):
|
||||
return len(text)
|
||||
return sum(map(get_character_cell_size, text))
|
||||
|
||||
|
||||
@lru_cache(maxsize=4096)
|
||||
@@ -52,20 +74,7 @@ def get_character_cell_size(character: str) -> int:
|
||||
Returns:
|
||||
int: Number of cells (0, 1 or 2) occupied by that character.
|
||||
"""
|
||||
return _get_codepoint_cell_size(ord(character))
|
||||
|
||||
|
||||
@lru_cache(maxsize=4096)
|
||||
def _get_codepoint_cell_size(codepoint: int) -> int:
|
||||
"""Get the cell size of a character.
|
||||
|
||||
Args:
|
||||
character (str): A single character.
|
||||
|
||||
Returns:
|
||||
int: Number of cells (0, 1 or 2) occupied by that character.
|
||||
"""
|
||||
|
||||
codepoint = ord(character)
|
||||
_table = CELL_WIDTHS
|
||||
lower_bound = 0
|
||||
upper_bound = len(_table) - 1
|
||||
@@ -119,33 +128,44 @@ def set_cell_size(text: str, total: int) -> str:
|
||||
start = pos
|
||||
|
||||
|
||||
# TODO: This is inefficient
|
||||
# TODO: This might not work with CWJ type characters
|
||||
def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]:
|
||||
"""Break text in to equal (cell) length strings, returning the characters in reverse
|
||||
order"""
|
||||
_get_character_cell_size = get_character_cell_size
|
||||
characters = [
|
||||
(character, _get_character_cell_size(character)) for character in text
|
||||
]
|
||||
total_size = position
|
||||
lines: List[List[str]] = [[]]
|
||||
append = lines[-1].append
|
||||
def chop_cells(
|
||||
text: str,
|
||||
width: int,
|
||||
) -> list[str]:
|
||||
"""Split text into lines such that each line fits within the available (cell) width.
|
||||
|
||||
for character, size in reversed(characters):
|
||||
if total_size + size > max_size:
|
||||
lines.append([character])
|
||||
append = lines[-1].append
|
||||
total_size = size
|
||||
Args:
|
||||
text: The text to fold such that it fits in the given width.
|
||||
width: The width available (number of cells).
|
||||
|
||||
Returns:
|
||||
A list of strings such that each string in the list has cell width
|
||||
less than or equal to the available width.
|
||||
"""
|
||||
_get_character_cell_size = get_character_cell_size
|
||||
lines: list[list[str]] = [[]]
|
||||
|
||||
append_new_line = lines.append
|
||||
append_to_last_line = lines[-1].append
|
||||
|
||||
total_width = 0
|
||||
|
||||
for character in text:
|
||||
cell_width = _get_character_cell_size(character)
|
||||
char_doesnt_fit = total_width + cell_width > width
|
||||
|
||||
if char_doesnt_fit:
|
||||
append_new_line([character])
|
||||
append_to_last_line = lines[-1].append
|
||||
total_width = cell_width
|
||||
else:
|
||||
total_size += size
|
||||
append(character)
|
||||
append_to_last_line(character)
|
||||
total_width += cell_width
|
||||
|
||||
return ["".join(line) for line in lines]
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
print(get_character_cell_size("😽"))
|
||||
for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8):
|
||||
print(line)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
from colorsys import rgb_to_hls
|
||||
from enum import IntEnum
|
||||
from functools import lru_cache
|
||||
@@ -15,7 +15,7 @@ if TYPE_CHECKING: # pragma: no cover
|
||||
from .text import Text
|
||||
|
||||
|
||||
WINDOWS = platform.system() == "Windows"
|
||||
WINDOWS = sys.platform == "win32"
|
||||
|
||||
|
||||
class ColorSystem(IntEnum):
|
||||
@@ -29,6 +29,9 @@ class ColorSystem(IntEnum):
|
||||
def __repr__(self) -> str:
|
||||
return f"ColorSystem.{self.name}"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return repr(self)
|
||||
|
||||
|
||||
class ColorType(IntEnum):
|
||||
"""Type of color stored in Color class."""
|
||||
@@ -310,7 +313,7 @@ class Color(NamedTuple):
|
||||
"""A triplet of color components, if an RGB color."""
|
||||
|
||||
def __rich__(self) -> "Text":
|
||||
"""Dispays the actual color if Rich printed."""
|
||||
"""Displays the actual color if Rich printed."""
|
||||
from .style import Style
|
||||
from .text import Text
|
||||
|
||||
@@ -510,15 +513,14 @@ class Color(NamedTuple):
|
||||
def downgrade(self, system: ColorSystem) -> "Color":
|
||||
"""Downgrade a color system to a system with fewer colors."""
|
||||
|
||||
if self.type in [ColorType.DEFAULT, system]:
|
||||
if self.type in (ColorType.DEFAULT, system):
|
||||
return self
|
||||
# Convert to 8-bit color from truecolor color
|
||||
if system == ColorSystem.EIGHT_BIT and self.system == ColorSystem.TRUECOLOR:
|
||||
assert self.triplet is not None
|
||||
red, green, blue = self.triplet.normalized
|
||||
_h, l, s = rgb_to_hls(red, green, blue)
|
||||
# If saturation is under 10% assume it is grayscale
|
||||
if s < 0.1:
|
||||
_h, l, s = rgb_to_hls(*self.triplet.normalized)
|
||||
# If saturation is under 15% assume it is grayscale
|
||||
if s < 0.15:
|
||||
gray = round(l * 25.0)
|
||||
if gray == 0:
|
||||
color_number = 16
|
||||
@@ -528,8 +530,13 @@ class Color(NamedTuple):
|
||||
color_number = 231 + gray
|
||||
return Color(self.name, ColorType.EIGHT_BIT, number=color_number)
|
||||
|
||||
red, green, blue = self.triplet
|
||||
six_red = red / 95 if red < 95 else 1 + (red - 95) / 40
|
||||
six_green = green / 95 if green < 95 else 1 + (green - 95) / 40
|
||||
six_blue = blue / 95 if blue < 95 else 1 + (blue - 95) / 40
|
||||
|
||||
color_number = (
|
||||
16 + 36 * round(red * 5.0) + 6 * round(green * 5.0) + round(blue * 5.0)
|
||||
16 + 36 * round(six_red) + 6 * round(six_green) + round(six_blue)
|
||||
)
|
||||
return Color(self.name, ColorType.EIGHT_BIT, number=color_number)
|
||||
|
||||
@@ -585,7 +592,6 @@ def blend_rgb(
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
|
||||
from .console import Console
|
||||
from .table import Table
|
||||
from .text import Text
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import inspect
|
||||
import io
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import threading
|
||||
import zlib
|
||||
@@ -34,6 +32,8 @@ from typing import (
|
||||
cast,
|
||||
)
|
||||
|
||||
from pip._vendor.rich._null_file import NULL_FILE
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Literal, Protocol, runtime_checkable
|
||||
else:
|
||||
@@ -46,6 +46,7 @@ else:
|
||||
from . import errors, themes
|
||||
from ._emoji_replace import _emoji_replace
|
||||
from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT
|
||||
from ._fileno import get_fileno
|
||||
from ._log_render import FormatTimeCallable, LogRender
|
||||
from .align import Align, AlignMethod
|
||||
from .color import ColorSystem, blend_rgb
|
||||
@@ -74,7 +75,7 @@ if TYPE_CHECKING:
|
||||
|
||||
JUPYTER_DEFAULT_COLUMNS = 115
|
||||
JUPYTER_DEFAULT_LINES = 100
|
||||
WINDOWS = platform.system() == "Windows"
|
||||
WINDOWS = sys.platform == "win32"
|
||||
|
||||
HighlighterType = Callable[[Union[str, "Text"]], "Text"]
|
||||
JustifyMethod = Literal["default", "left", "center", "right", "full"]
|
||||
@@ -88,15 +89,15 @@ class NoChange:
|
||||
NO_CHANGE = NoChange()
|
||||
|
||||
try:
|
||||
_STDIN_FILENO = sys.__stdin__.fileno()
|
||||
_STDIN_FILENO = sys.__stdin__.fileno() # type: ignore[union-attr]
|
||||
except Exception:
|
||||
_STDIN_FILENO = 0
|
||||
try:
|
||||
_STDOUT_FILENO = sys.__stdout__.fileno()
|
||||
_STDOUT_FILENO = sys.__stdout__.fileno() # type: ignore[union-attr]
|
||||
except Exception:
|
||||
_STDOUT_FILENO = 1
|
||||
try:
|
||||
_STDERR_FILENO = sys.__stderr__.fileno()
|
||||
_STDERR_FILENO = sys.__stderr__.fileno() # type: ignore[union-attr]
|
||||
except Exception:
|
||||
_STDERR_FILENO = 2
|
||||
|
||||
@@ -104,7 +105,11 @@ _STD_STREAMS = (_STDIN_FILENO, _STDOUT_FILENO, _STDERR_FILENO)
|
||||
_STD_STREAMS_OUTPUT = (_STDOUT_FILENO, _STDERR_FILENO)
|
||||
|
||||
|
||||
_TERM_COLORS = {"256color": ColorSystem.EIGHT_BIT, "16color": ColorSystem.STANDARD}
|
||||
_TERM_COLORS = {
|
||||
"kitty": ColorSystem.EIGHT_BIT,
|
||||
"256color": ColorSystem.EIGHT_BIT,
|
||||
"16color": ColorSystem.STANDARD,
|
||||
}
|
||||
|
||||
|
||||
class ConsoleDimensions(NamedTuple):
|
||||
@@ -272,6 +277,7 @@ class ConsoleRenderable(Protocol):
|
||||
|
||||
# A type that may be rendered by Console.
|
||||
RenderableType = Union[ConsoleRenderable, RichCast, str]
|
||||
"""A string or any object that may be rendered by Rich."""
|
||||
|
||||
# The result of calling a __rich_console__ method.
|
||||
RenderResult = Iterable[Union[RenderableType, Segment]]
|
||||
@@ -516,7 +522,11 @@ def _is_jupyter() -> bool: # pragma: no cover
|
||||
return False
|
||||
ipython = get_ipython() # type: ignore[name-defined]
|
||||
shell = ipython.__class__.__name__
|
||||
if "google.colab" in str(ipython.__class__) or shell == "ZMQInteractiveShell":
|
||||
if (
|
||||
"google.colab" in str(ipython.__class__)
|
||||
or os.getenv("DATABRICKS_RUNTIME_VERSION")
|
||||
or shell == "ZMQInteractiveShell"
|
||||
):
|
||||
return True # Jupyter notebook or qtconsole
|
||||
elif shell == "TerminalInteractiveShell":
|
||||
return False # Terminal running IPython
|
||||
@@ -697,7 +707,11 @@ class Console:
|
||||
self._height = height
|
||||
|
||||
self._color_system: Optional[ColorSystem]
|
||||
self._force_terminal = force_terminal
|
||||
|
||||
self._force_terminal = None
|
||||
if force_terminal is not None:
|
||||
self._force_terminal = force_terminal
|
||||
|
||||
self._file = file
|
||||
self.quiet = quiet
|
||||
self.stderr = stderr
|
||||
@@ -739,13 +753,15 @@ class Console:
|
||||
self._is_alt_screen = False
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<console width={self.width} {str(self._color_system)}>"
|
||||
return f"<console width={self.width} {self._color_system!s}>"
|
||||
|
||||
@property
|
||||
def file(self) -> IO[str]:
|
||||
"""Get the file object to write to."""
|
||||
file = self._file or (sys.stderr if self.stderr else sys.stdout)
|
||||
file = getattr(file, "rich_proxied_file", file)
|
||||
if file is None:
|
||||
file = NULL_FILE
|
||||
return file
|
||||
|
||||
@file.setter
|
||||
@@ -928,6 +944,16 @@ class Console:
|
||||
# Return False for Idle which claims to be a tty but can't handle ansi codes
|
||||
return False
|
||||
|
||||
if self.is_jupyter:
|
||||
# return False for Jupyter, which may have FORCE_COLOR set
|
||||
return False
|
||||
|
||||
# If FORCE_COLOR env var has any value at all, we assume a terminal.
|
||||
force_color = self._environ.get("FORCE_COLOR")
|
||||
if force_color is not None:
|
||||
self._force_terminal = True
|
||||
return True
|
||||
|
||||
isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None)
|
||||
try:
|
||||
return False if isatty is None else isatty()
|
||||
@@ -979,19 +1005,14 @@ class Console:
|
||||
width: Optional[int] = None
|
||||
height: Optional[int] = None
|
||||
|
||||
if WINDOWS: # pragma: no cover
|
||||
streams = _STD_STREAMS_OUTPUT if WINDOWS else _STD_STREAMS
|
||||
for file_descriptor in streams:
|
||||
try:
|
||||
width, height = os.get_terminal_size()
|
||||
width, height = os.get_terminal_size(file_descriptor)
|
||||
except (AttributeError, ValueError, OSError): # Probably not a terminal
|
||||
pass
|
||||
else:
|
||||
for file_descriptor in _STD_STREAMS:
|
||||
try:
|
||||
width, height = os.get_terminal_size(file_descriptor)
|
||||
except (AttributeError, ValueError, OSError):
|
||||
pass
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
columns = self._environ.get("COLUMNS")
|
||||
if columns is not None and columns.isdigit():
|
||||
@@ -1125,7 +1146,7 @@ class Console:
|
||||
status: RenderableType,
|
||||
*,
|
||||
spinner: str = "dots",
|
||||
spinner_style: str = "status.spinner",
|
||||
spinner_style: StyleType = "status.spinner",
|
||||
speed: float = 1.0,
|
||||
refresh_per_second: float = 12.5,
|
||||
) -> "Status":
|
||||
@@ -1282,7 +1303,7 @@ class Console:
|
||||
|
||||
renderable = rich_cast(renderable)
|
||||
if hasattr(renderable, "__rich_console__") and not isclass(renderable):
|
||||
render_iterable = renderable.__rich_console__(self, _options) # type: ignore[union-attr]
|
||||
render_iterable = renderable.__rich_console__(self, _options)
|
||||
elif isinstance(renderable, str):
|
||||
text_renderable = self.render_str(
|
||||
renderable, highlight=_options.highlight, markup=_options.markup
|
||||
@@ -1359,9 +1380,14 @@ class Console:
|
||||
extra_lines = render_options.height - len(lines)
|
||||
if extra_lines > 0:
|
||||
pad_line = [
|
||||
[Segment(" " * render_options.max_width, style), Segment("\n")]
|
||||
if new_lines
|
||||
else [Segment(" " * render_options.max_width, style)]
|
||||
(
|
||||
[
|
||||
Segment(" " * render_options.max_width, style),
|
||||
Segment("\n"),
|
||||
]
|
||||
if new_lines
|
||||
else [Segment(" " * render_options.max_width, style)]
|
||||
)
|
||||
]
|
||||
lines.extend(pad_line * extra_lines)
|
||||
|
||||
@@ -1410,9 +1436,11 @@ class Console:
|
||||
rich_text.overflow = overflow
|
||||
else:
|
||||
rich_text = Text(
|
||||
_emoji_replace(text, default_variant=self._emoji_variant)
|
||||
if emoji_enabled
|
||||
else text,
|
||||
(
|
||||
_emoji_replace(text, default_variant=self._emoji_variant)
|
||||
if emoji_enabled
|
||||
else text
|
||||
),
|
||||
justify=justify,
|
||||
overflow=overflow,
|
||||
style=style,
|
||||
@@ -1502,14 +1530,18 @@ class Console:
|
||||
if text:
|
||||
sep_text = Text(sep, justify=justify, end=end)
|
||||
append(sep_text.join(text))
|
||||
del text[:]
|
||||
text.clear()
|
||||
|
||||
for renderable in objects:
|
||||
renderable = rich_cast(renderable)
|
||||
if isinstance(renderable, str):
|
||||
append_text(
|
||||
self.render_str(
|
||||
renderable, emoji=emoji, markup=markup, highlighter=_highlighter
|
||||
renderable,
|
||||
emoji=emoji,
|
||||
markup=markup,
|
||||
highlight=highlight,
|
||||
highlighter=_highlighter,
|
||||
)
|
||||
)
|
||||
elif isinstance(renderable, Text):
|
||||
@@ -1701,7 +1733,7 @@ class Console:
|
||||
indent: Union[None, int, str] = 2,
|
||||
highlight: bool = True,
|
||||
skip_keys: bool = False,
|
||||
ensure_ascii: bool = True,
|
||||
ensure_ascii: bool = False,
|
||||
check_circular: bool = True,
|
||||
allow_nan: bool = True,
|
||||
default: Optional[Callable[[Any], Any]] = None,
|
||||
@@ -1899,7 +1931,6 @@ class Console:
|
||||
end (str, optional): String to write at end of print data. Defaults to "\\\\n".
|
||||
style (Union[str, Style], optional): A style to apply to output. Defaults to None.
|
||||
justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``.
|
||||
overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None.
|
||||
emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to None.
|
||||
markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to None.
|
||||
highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to None.
|
||||
@@ -1960,6 +1991,20 @@ class Console:
|
||||
):
|
||||
buffer_extend(line)
|
||||
|
||||
def on_broken_pipe(self) -> None:
|
||||
"""This function is called when a `BrokenPipeError` is raised.
|
||||
|
||||
This can occur when piping Textual output in Linux and macOS.
|
||||
The default implementation is to exit the app, but you could implement
|
||||
this method in a subclass to change the behavior.
|
||||
|
||||
See https://docs.python.org/3/library/signal.html#note-on-sigpipe for details.
|
||||
"""
|
||||
self.quiet = True
|
||||
devnull = os.open(os.devnull, os.O_WRONLY)
|
||||
os.dup2(devnull, sys.stdout.fileno())
|
||||
raise SystemExit(1)
|
||||
|
||||
def _check_buffer(self) -> None:
|
||||
"""Check if the buffer may be rendered. Render it if it can (e.g. Console.quiet is False)
|
||||
Rendering is supported on Windows, Unix and Jupyter environments. For
|
||||
@@ -1969,13 +2014,21 @@ class Console:
|
||||
if self.quiet:
|
||||
del self._buffer[:]
|
||||
return
|
||||
|
||||
try:
|
||||
self._write_buffer()
|
||||
except BrokenPipeError:
|
||||
self.on_broken_pipe()
|
||||
|
||||
def _write_buffer(self) -> None:
|
||||
"""Write the buffer to the output file."""
|
||||
|
||||
with self._lock:
|
||||
if self.record:
|
||||
if self.record and not self._buffer_index:
|
||||
with self._record_buffer_lock:
|
||||
self._record_buffer.extend(self._buffer[:])
|
||||
|
||||
if self._buffer_index == 0:
|
||||
|
||||
if self.is_jupyter: # pragma: no cover
|
||||
from .jupyter import display
|
||||
|
||||
@@ -1985,31 +2038,50 @@ class Console:
|
||||
if WINDOWS:
|
||||
use_legacy_windows_render = False
|
||||
if self.legacy_windows:
|
||||
try:
|
||||
fileno = get_fileno(self.file)
|
||||
if fileno is not None:
|
||||
use_legacy_windows_render = (
|
||||
self.file.fileno() in _STD_STREAMS_OUTPUT
|
||||
fileno in _STD_STREAMS_OUTPUT
|
||||
)
|
||||
except (ValueError, io.UnsupportedOperation):
|
||||
pass
|
||||
|
||||
if use_legacy_windows_render:
|
||||
from pip._vendor.rich._win32_console import LegacyWindowsTerm
|
||||
from pip._vendor.rich._windows_renderer import legacy_windows_render
|
||||
|
||||
legacy_windows_render(
|
||||
self._buffer[:], LegacyWindowsTerm(self.file)
|
||||
)
|
||||
buffer = self._buffer[:]
|
||||
if self.no_color and self._color_system:
|
||||
buffer = list(Segment.remove_color(buffer))
|
||||
|
||||
legacy_windows_render(buffer, LegacyWindowsTerm(self.file))
|
||||
else:
|
||||
# Either a non-std stream on legacy Windows, or modern Windows.
|
||||
text = self._render_buffer(self._buffer[:])
|
||||
# https://bugs.python.org/issue37871
|
||||
# https://github.com/python/cpython/issues/82052
|
||||
# We need to avoid writing more than 32Kb in a single write, due to the above bug
|
||||
write = self.file.write
|
||||
for line in text.splitlines(True):
|
||||
try:
|
||||
write(line)
|
||||
except UnicodeEncodeError as error:
|
||||
error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***"
|
||||
raise
|
||||
# Worse case scenario, every character is 4 bytes of utf-8
|
||||
MAX_WRITE = 32 * 1024 // 4
|
||||
try:
|
||||
if len(text) <= MAX_WRITE:
|
||||
write(text)
|
||||
else:
|
||||
batch: List[str] = []
|
||||
batch_append = batch.append
|
||||
size = 0
|
||||
for line in text.splitlines(True):
|
||||
if size + len(line) > MAX_WRITE and batch:
|
||||
write("".join(batch))
|
||||
batch.clear()
|
||||
size = 0
|
||||
batch_append(line)
|
||||
size += len(line)
|
||||
if batch:
|
||||
write("".join(batch))
|
||||
batch.clear()
|
||||
except UnicodeEncodeError as error:
|
||||
error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***"
|
||||
raise
|
||||
else:
|
||||
text = self._render_buffer(self._buffer[:])
|
||||
try:
|
||||
@@ -2122,7 +2194,7 @@ class Console:
|
||||
|
||||
"""
|
||||
text = self.export_text(clear=clear, styles=styles)
|
||||
with open(path, "wt", encoding="utf-8") as write_file:
|
||||
with open(path, "w", encoding="utf-8") as write_file:
|
||||
write_file.write(text)
|
||||
|
||||
def export_html(
|
||||
@@ -2228,7 +2300,7 @@ class Console:
|
||||
code_format=code_format,
|
||||
inline_styles=inline_styles,
|
||||
)
|
||||
with open(path, "wt", encoding="utf-8") as write_file:
|
||||
with open(path, "w", encoding="utf-8") as write_file:
|
||||
write_file.write(html)
|
||||
|
||||
def export_svg(
|
||||
@@ -2238,18 +2310,24 @@ class Console:
|
||||
theme: Optional[TerminalTheme] = None,
|
||||
clear: bool = True,
|
||||
code_format: str = CONSOLE_SVG_FORMAT,
|
||||
font_aspect_ratio: float = 0.61,
|
||||
unique_id: Optional[str] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Generate an SVG from the console contents (requires record=True in Console constructor).
|
||||
|
||||
Args:
|
||||
path (str): The path to write the SVG to.
|
||||
title (str): The title of the tab in the output image
|
||||
title (str, optional): The title of the tab in the output image
|
||||
theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal
|
||||
clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``
|
||||
code_format (str): Format string used to generate the SVG. Rich will inject a number of variables
|
||||
code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables
|
||||
into the string in order to form the final SVG output. The default template used and the variables
|
||||
injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable.
|
||||
font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format``
|
||||
string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font).
|
||||
If you aren't specifying a different font inside ``code_format``, you probably don't need this.
|
||||
unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node
|
||||
ids). If not set, this defaults to a computed value based on the recorded content.
|
||||
"""
|
||||
|
||||
from pip._vendor.rich.cells import cell_len
|
||||
@@ -2293,7 +2371,7 @@ class Console:
|
||||
|
||||
width = self.width
|
||||
char_height = 20
|
||||
char_width = char_height * 0.61
|
||||
char_width = char_height * font_aspect_ratio
|
||||
line_height = char_height * 1.22
|
||||
|
||||
margin_top = 1
|
||||
@@ -2345,14 +2423,16 @@ class Console:
|
||||
if clear:
|
||||
self._record_buffer.clear()
|
||||
|
||||
unique_id = "terminal-" + str(
|
||||
zlib.adler32(
|
||||
("".join(segment.text for segment in segments)).encode(
|
||||
"utf-8", "ignore"
|
||||
if unique_id is None:
|
||||
unique_id = "terminal-" + str(
|
||||
zlib.adler32(
|
||||
("".join(repr(segment) for segment in segments)).encode(
|
||||
"utf-8",
|
||||
"ignore",
|
||||
)
|
||||
+ title.encode("utf-8", "ignore")
|
||||
)
|
||||
+ title.encode("utf-8", "ignore")
|
||||
)
|
||||
)
|
||||
y = 0
|
||||
for y, line in enumerate(Segment.split_and_crop_lines(segments, length=width)):
|
||||
x = 0
|
||||
@@ -2482,25 +2562,34 @@ class Console:
|
||||
theme: Optional[TerminalTheme] = None,
|
||||
clear: bool = True,
|
||||
code_format: str = CONSOLE_SVG_FORMAT,
|
||||
font_aspect_ratio: float = 0.61,
|
||||
unique_id: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Generate an SVG file from the console contents (requires record=True in Console constructor).
|
||||
|
||||
Args:
|
||||
path (str): The path to write the SVG to.
|
||||
title (str): The title of the tab in the output image
|
||||
title (str, optional): The title of the tab in the output image
|
||||
theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal
|
||||
clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``
|
||||
code_format (str): Format string used to generate the SVG. Rich will inject a number of variables
|
||||
code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables
|
||||
into the string in order to form the final SVG output. The default template used and the variables
|
||||
injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable.
|
||||
font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format``
|
||||
string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font).
|
||||
If you aren't specifying a different font inside ``code_format``, you probably don't need this.
|
||||
unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node
|
||||
ids). If not set, this defaults to a computed value based on the recorded content.
|
||||
"""
|
||||
svg = self.export_svg(
|
||||
title=title,
|
||||
theme=theme,
|
||||
clear=clear,
|
||||
code_format=code_format,
|
||||
font_aspect_ratio=font_aspect_ratio,
|
||||
unique_id=unique_id,
|
||||
)
|
||||
with open(path, "wt", encoding="utf-8") as write_file:
|
||||
with open(path, "w", encoding="utf-8") as write_file:
|
||||
write_file.write(svg)
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
from itertools import zip_longest
|
||||
from typing import (
|
||||
Iterator,
|
||||
TYPE_CHECKING,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
TypeVar,
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -119,7 +119,7 @@ class Lines:
|
||||
|
||||
Args:
|
||||
console (Console): Console instance.
|
||||
width (int): Number of characters per line.
|
||||
width (int): Number of cells available per line.
|
||||
justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left".
|
||||
overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold".
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ DEFAULT_STYLES: Dict[str, Style] = {
|
||||
"logging.level.notset": Style(dim=True),
|
||||
"logging.level.debug": Style(color="green"),
|
||||
"logging.level.info": Style(color="blue"),
|
||||
"logging.level.warning": Style(color="red"),
|
||||
"logging.level.warning": Style(color="yellow"),
|
||||
"logging.level.error": Style(color="red", bold=True),
|
||||
"logging.level.critical": Style(color="red", bold=True, reverse=True),
|
||||
"log.level": Style.null(),
|
||||
@@ -120,6 +120,7 @@ DEFAULT_STYLES: Dict[str, Style] = {
|
||||
"traceback.exc_type": Style(color="bright_red", bold=True),
|
||||
"traceback.exc_value": Style.null(),
|
||||
"traceback.offset": Style(color="bright_red", bold=True),
|
||||
"traceback.error_range": Style(underline=True, bold=True, dim=False),
|
||||
"bar.back": Style(color="grey23"),
|
||||
"bar.complete": Style(color="rgb(249,38,114)"),
|
||||
"bar.finished": Style(color="rgb(114,156,31)"),
|
||||
@@ -138,10 +139,11 @@ DEFAULT_STYLES: Dict[str, Style] = {
|
||||
"tree.line": Style(),
|
||||
"markdown.paragraph": Style(),
|
||||
"markdown.text": Style(),
|
||||
"markdown.emph": Style(italic=True),
|
||||
"markdown.em": Style(italic=True),
|
||||
"markdown.emph": Style(italic=True), # For commonmark backwards compatibility
|
||||
"markdown.strong": Style(bold=True),
|
||||
"markdown.code": Style(bgcolor="black", color="bright_white"),
|
||||
"markdown.code_block": Style(dim=True, color="cyan", bgcolor="black"),
|
||||
"markdown.code": Style(bold=True, color="cyan", bgcolor="black"),
|
||||
"markdown.code_block": Style(color="cyan", bgcolor="black"),
|
||||
"markdown.block_quote": Style(color="magenta"),
|
||||
"markdown.list": Style(color="cyan"),
|
||||
"markdown.item": Style(),
|
||||
@@ -157,7 +159,8 @@ DEFAULT_STYLES: Dict[str, Style] = {
|
||||
"markdown.h6": Style(italic=True),
|
||||
"markdown.h7": Style(italic=True, dim=True),
|
||||
"markdown.link": Style(color="bright_blue"),
|
||||
"markdown.link_url": Style(color="blue"),
|
||||
"markdown.link_url": Style(color="blue", underline=True),
|
||||
"markdown.s": Style(strike=True),
|
||||
"iso8601.date": Style(color="blue"),
|
||||
"iso8601.time": Style(color="magenta"),
|
||||
"iso8601.timezone": Style(color="yellow"),
|
||||
|
||||
@@ -34,7 +34,7 @@ class FileProxy(io.TextIOBase):
|
||||
line, new_line, text = text.partition("\n")
|
||||
if new_line:
|
||||
lines.append("".join(buffer) + line)
|
||||
del buffer[:]
|
||||
buffer.clear()
|
||||
else:
|
||||
buffer.append(line)
|
||||
break
|
||||
@@ -52,3 +52,6 @@ class FileProxy(io.TextIOBase):
|
||||
if output:
|
||||
self.__console.print(output)
|
||||
del self.__buffer[:]
|
||||
|
||||
def fileno(self) -> int:
|
||||
return self.__file.fileno()
|
||||
@@ -1,8 +1,7 @@
|
||||
# coding: utf-8
|
||||
"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2
|
||||
|
||||
The functions declared in this module should cover the different
|
||||
usecases needed to generate a string representation of a file size
|
||||
use cases needed to generate a string representation of a file size
|
||||
using several different units. Since there are many standards regarding
|
||||
file size units, three different functions have been implemented.
|
||||
|
||||
@@ -27,7 +26,7 @@ def _to_str(
|
||||
if size == 1:
|
||||
return "1 byte"
|
||||
elif size < base:
|
||||
return "{:,} bytes".format(size)
|
||||
return f"{size:,} bytes"
|
||||
|
||||
for i, suffix in enumerate(suffixes, 2): # noqa: B007
|
||||
unit = base**i
|
||||
|
||||
@@ -82,7 +82,7 @@ class ReprHighlighter(RegexHighlighter):
|
||||
|
||||
base_style = "repr."
|
||||
highlights = [
|
||||
r"(?P<tag_start><)(?P<tag_name>[-\w.:|]*)(?P<tag_contents>[\w\W]*?)(?P<tag_end>>)",
|
||||
r"(?P<tag_start><)(?P<tag_name>[-\w.:|]*)(?P<tag_contents>[\w\W]*)(?P<tag_end>>)",
|
||||
r'(?P<attrib_name>[\w_]{1,50})=(?P<attrib_value>"?[\w_]+"?)?',
|
||||
r"(?P<brace>[][{}()])",
|
||||
_combine_regex(
|
||||
@@ -98,7 +98,7 @@ class ReprHighlighter(RegexHighlighter):
|
||||
r"(?P<number>(?<!\w)\-?[0-9]+\.?[0-9]*(e[-+]?\d+?)?\b|0x[0-9a-fA-F]*)",
|
||||
r"(?P<path>\B(/[-\w._+]+)*\/)(?P<filename>[-\w._+]*)?",
|
||||
r"(?<![\\\w])(?P<str>b?'''.*?(?<!\\)'''|b?'.*?(?<!\\)'|b?\"\"\".*?(?<!\\)\"\"\"|b?\".*?(?<!\\)\")",
|
||||
r"(?P<url>(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#]*)",
|
||||
r"(?P<url>(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#~@]*)",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
Loaded 100 of 1138 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user