nem sei pq tantos arquivos

This commit is contained in:
2025-02-11 11:07:58 -03:00
parent 66fb4eb17b
commit 2da09a8a25
1841 changed files with 115867 additions and 77478 deletions

View File

@@ -207,7 +207,6 @@ Supports much of the *markdown* __syntax__!
if __name__ == "__main__": # pragma: no cover
console = Console(
file=io.StringIO(),
force_terminal=True,

View File

@@ -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),
]

View File

@@ -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>
"""

View File

@@ -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

View File

@@ -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

View File

@@ -3,20 +3,6 @@ from typing import IO, Iterable, Iterator, List, Optional, Type
class NullFile(IO[str]):
# TODO: "mode", "name" and "closed" are only required for Python 3.6.
@property
def mode(self) -> str:
return ""
@property
def name(self) -> str:
return "NullFile"
def closed(self) -> bool:
return False
def close(self) -> None:
pass
@@ -60,7 +46,7 @@ class NullFile(IO[str]):
return iter([""])
def __enter__(self) -> IO[str]:
pass
return self
def __exit__(
self,

View File

@@ -151,7 +151,6 @@ if __name__ == "__main__":
@dataclass
class E:
size: Optional[int] = None
ratio: int = 1
minimum_size: int = 1

View File

@@ -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

View File

@@ -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()

View File

@@ -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万色を使用でき")

View File

@@ -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(

View File

@@ -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:

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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):
@@ -513,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
@@ -531,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)
@@ -588,7 +592,6 @@ def blend_rgb(
if __name__ == "__main__": # pragma: no cover
from .console import Console
from .table import Table
from .text import Text

View File

@@ -1,7 +1,5 @@
import inspect
import io
import os
import platform
import sys
import threading
import zlib
@@ -48,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
@@ -76,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"]
@@ -90,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
@@ -278,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]]
@@ -711,11 +711,6 @@ class Console:
self._force_terminal = None
if force_terminal is not None:
self._force_terminal = force_terminal
else:
# If FORCE_COLOR env var has any value at all, we force terminal.
force_color = self._environ.get("FORCE_COLOR")
if force_color is not None:
self._force_terminal = True
self._file = file
self.quiet = quiet
@@ -758,7 +753,7 @@ 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]:
@@ -949,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()
@@ -1000,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():
@@ -1146,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":
@@ -1303,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
@@ -1380,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)
@@ -1431,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,
@@ -1523,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):
@@ -1920,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.
@@ -1981,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
@@ -1990,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
@@ -2006,12 +2038,11 @@ 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
@@ -2026,13 +2057,31 @@ class Console:
# 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:
@@ -2145,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(
@@ -2251,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(
@@ -2540,7 +2589,7 @@ class Console:
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)

View File

@@ -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".

View File

@@ -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"),

View File

@@ -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()

View File

@@ -1,4 +1,3 @@
# coding: utf-8
"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2
The functions declared in this module should cover the different
@@ -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

View File

@@ -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$_+!`(),.?/;:&=%#~@]*)",
),
]

View File

@@ -1,3 +1,4 @@
from pathlib import Path
from json import loads, dumps
from typing import Any, Callable, Optional, Union
@@ -102,7 +103,6 @@ class JSON:
if __name__ == "__main__":
import argparse
import sys
@@ -131,8 +131,7 @@ if __name__ == "__main__":
if args.path == "-":
json_data = sys.stdin.read()
else:
with open(args.path, "rt") as json_file:
json_data = json_file.read()
json_data = Path(args.path).read_text()
except Exception as error:
error_console.print(f"Unable to read {args.path!r}; {error}")
sys.exit(-1)

Some files were not shown because too many files have changed in this diff Show More