Merge branch 'master' of github.com:Textualize/rich

This commit is contained in:
Darren Burns 2022-03-21 09:51:09 +00:00
commit a8d2bb2004
No known key found for this signature in database
GPG key ID: B0939B45037DC345
12 changed files with 126 additions and 92 deletions

View file

@ -0,0 +1,24 @@
on:
release:
types: [ released ]
jobs:
asv-publish-and-copy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.10.2'
- run: 'pip install asv'
- run: 'asv publish'
- uses: pina/github-action-push-to-another-repository@v1.4.1
name: 'Copy files to Textualize/rich-benchmarks repo'
env:
API_TOKEN_GITHUB: ${{ secrets.PUBLISH_ASV }}
with:
source-directory: /benchmarks/html
destination-github-username: Textualize
destination-repository-name: rich-benchmarks
user-email: darren@textualize.io

View file

@ -10,12 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Improve performance of cell_length https://github.com/Textualize/rich/pull/2061
- Improve performance of chop_cells https://github.com/Textualize/rich/pull/2077
## [12.0.1] - 2022-03-14
### Fixed
- Fix capturing stdout on legacy Windows https://github.com/Textualize/rich/pull/2055
- Fix capturing stdout on legacy Windows https://github.com/Textualize/rich/pull/2066
## [12.0.0] - 2022-03-10

76
poetry.lock generated
View file

@ -356,7 +356,7 @@ python-versions = "*"
[[package]]
name = "ipywidgets"
version = "7.6.5"
version = "7.7.0"
description = "IPython HTML widgets for Jupyter"
category = "main"
optional = true
@ -369,7 +369,7 @@ ipython-genutils = ">=0.2.0,<0.3.0"
jupyterlab-widgets = {version = ">=1.0.0", markers = "python_version >= \"3.6\""}
nbformat = ">=4.2.0"
traitlets = ">=4.3.1"
widgetsnbextension = ">=3.5.0,<3.6.0"
widgetsnbextension = ">=3.6.0,<3.7.0"
[package.extras]
test = ["pytest (>=3.6.0)", "pytest-cov", "mock"]
@ -466,7 +466,7 @@ pygments = ">=2.4.1,<3"
[[package]]
name = "jupyterlab-widgets"
version = "1.0.2"
version = "1.1.0"
description = "A JupyterLab extension."
category = "main"
optional = true
@ -490,7 +490,7 @@ python-versions = "*"
[[package]]
name = "mypy"
version = "0.931"
version = "0.941"
description = "Optional static typing for Python"
category = "dev"
optional = false
@ -505,6 +505,7 @@ typing-extensions = ">=3.10"
[package.extras]
dmypy = ["psutil (>=4.0)"]
python2 = ["typed-ast (>=1.4.0,<2)"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
@ -600,7 +601,7 @@ python-versions = "*"
[[package]]
name = "notebook"
version = "6.4.8"
version = "6.4.10"
description = "A web-based notebook environment for interactive computing"
category = "main"
optional = true
@ -613,7 +614,7 @@ ipython-genutils = "*"
jinja2 = "*"
jupyter-client = ">=5.3.4"
jupyter-core = ">=4.6.1"
nbconvert = "*"
nbconvert = ">=5"
nbformat = "*"
nest-asyncio = ">=1.5"
prometheus-client = "*"
@ -1037,7 +1038,7 @@ python-versions = "*"
[[package]]
name = "widgetsnbextension"
version = "3.5.2"
version = "3.6.0"
description = "IPython HTML widgets for Jupyter"
category = "main"
optional = true
@ -1064,7 +1065,7 @@ jupyter = ["ipywidgets"]
[metadata]
lock-version = "1.1"
python-versions = "^3.6.2"
content-hash = "5ce16f2949f71818ef5552c9001615a07b6e604a6291ff34b0f5fdc29a684cdc"
content-hash = "9d010fc1dade302bb784d0607a4c23d00e89f6709572310452428d347ff8b89a"
[metadata.files]
appnope = [
@ -1316,8 +1317,8 @@ ipython-genutils = [
{file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"},
]
ipywidgets = [
{file = "ipywidgets-7.6.5-py2.py3-none-any.whl", hash = "sha256:d258f582f915c62ea91023299603be095de19afb5ee271698f88327b9fe9bf43"},
{file = "ipywidgets-7.6.5.tar.gz", hash = "sha256:00974f7cb4d5f8d494c19810fedb9fa9b64bffd3cda7c2be23c133a1ad3c99c5"},
{file = "ipywidgets-7.7.0-py2.py3-none-any.whl", hash = "sha256:e58ff58bc94d481e91ecb6e13a5cb96a87b6b8ade135e055603d0ca24593df38"},
{file = "ipywidgets-7.7.0.tar.gz", hash = "sha256:ab4a5596855a88b83761921c768707d65e5847068139bc1729ddfe834703542a"},
]
jedi = [
{file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"},
@ -1344,8 +1345,8 @@ jupyterlab-pygments = [
{file = "jupyterlab_pygments-0.1.2.tar.gz", hash = "sha256:cfcda0873626150932f438eccf0f8bf22bfa92345b814890ab360d666b254146"},
]
jupyterlab-widgets = [
{file = "jupyterlab_widgets-1.0.2-py3-none-any.whl", hash = "sha256:f5d9efface8ec62941173ba1cffb2edd0ecddc801c11ae2931e30b50492eb8f7"},
{file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"},
{file = "jupyterlab_widgets-1.1.0-py3-none-any.whl", hash = "sha256:c2a9bd3789f120f64d73268c066ed3b000c56bc1dda217be5cdc43e7b4ebad3f"},
{file = "jupyterlab_widgets-1.1.0.tar.gz", hash = "sha256:d5f41bc1713795385f718d44dcba47e1e1473c6289f28a95aa6b2c0782ee372a"},
]
markupsafe = [
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
@ -1423,26 +1424,29 @@ mistune = [
{file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"},
]
mypy = [
{file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"},
{file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"},
{file = "mypy-0.931-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714"},
{file = "mypy-0.931-cp310-cp310-win_amd64.whl", hash = "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc"},
{file = "mypy-0.931-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d"},
{file = "mypy-0.931-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d"},
{file = "mypy-0.931-cp36-cp36m-win_amd64.whl", hash = "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c"},
{file = "mypy-0.931-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0"},
{file = "mypy-0.931-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05"},
{file = "mypy-0.931-cp37-cp37m-win_amd64.whl", hash = "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7"},
{file = "mypy-0.931-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0"},
{file = "mypy-0.931-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069"},
{file = "mypy-0.931-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799"},
{file = "mypy-0.931-cp38-cp38-win_amd64.whl", hash = "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a"},
{file = "mypy-0.931-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166"},
{file = "mypy-0.931-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266"},
{file = "mypy-0.931-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd"},
{file = "mypy-0.931-cp39-cp39-win_amd64.whl", hash = "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697"},
{file = "mypy-0.931-py3-none-any.whl", hash = "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d"},
{file = "mypy-0.931.tar.gz", hash = "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce"},
{file = "mypy-0.941-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:98f61aad0bb54f797b17da5b82f419e6ce214de0aa7e92211ebee9e40eb04276"},
{file = "mypy-0.941-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6a8e1f63357851444940351e98fb3252956a15f2cabe3d698316d7a2d1f1f896"},
{file = "mypy-0.941-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b30d29251dff4c59b2e5a1fa1bab91ff3e117b4658cb90f76d97702b7a2ae699"},
{file = "mypy-0.941-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8eaf55fdf99242a1c8c792247c455565447353914023878beadb79600aac4a2a"},
{file = "mypy-0.941-cp310-cp310-win_amd64.whl", hash = "sha256:080097eee5393fd740f32c63f9343580aaa0fb1cda0128fd859dfcf081321c3d"},
{file = "mypy-0.941-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f79137d012ff3227866222049af534f25354c07a0d6b9a171dba9f1d6a1fdef4"},
{file = "mypy-0.941-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e5974583a77d630a5868eee18f85ac3093caf76e018c510aeb802b9973304ce"},
{file = "mypy-0.941-cp36-cp36m-win_amd64.whl", hash = "sha256:0dd441fbacf48e19dc0c5c42fafa72b8e1a0ba0a39309c1af9c84b9397d9b15a"},
{file = "mypy-0.941-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0d3bcbe146247997e03bf030122000998b076b3ac6925b0b6563f46d1ce39b50"},
{file = "mypy-0.941-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bada0cf7b6965627954b3a128903a87cac79a79ccd83b6104912e723ef16c7b"},
{file = "mypy-0.941-cp37-cp37m-win_amd64.whl", hash = "sha256:eea10982b798ff0ccc3b9e7e42628f932f552c5845066970e67cd6858655d52c"},
{file = "mypy-0.941-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:108f3c7e14a038cf097d2444fa0155462362c6316e3ecb2d70f6dd99cd36084d"},
{file = "mypy-0.941-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d61b73c01fc1de799226963f2639af831307fe1556b04b7c25e2b6c267a3bc76"},
{file = "mypy-0.941-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:42c216a33d2bdba08098acaf5bae65b0c8196afeb535ef4b870919a788a27259"},
{file = "mypy-0.941-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc5ecff5a3bbfbe20091b1cad82815507f5ae9c380a3a9bf40f740c70ce30a9b"},
{file = "mypy-0.941-cp38-cp38-win_amd64.whl", hash = "sha256:bf446223b2e0e4f0a4792938e8d885e8a896834aded5f51be5c3c69566495540"},
{file = "mypy-0.941-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:745071762f32f65e77de6df699366d707fad6c132a660d1342077cbf671ef589"},
{file = "mypy-0.941-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:465a6ce9ca6268cadfbc27a2a94ddf0412568a6b27640ced229270be4f5d394d"},
{file = "mypy-0.941-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d051ce0946521eba48e19b25f27f98e5ce4dbc91fff296de76240c46b4464df0"},
{file = "mypy-0.941-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:818cfc51c25a5dbfd0705f3ac1919fff6971eb0c02e6f1a1f6a017a42405a7c0"},
{file = "mypy-0.941-cp39-cp39-win_amd64.whl", hash = "sha256:b2ce2788df0c066c2ff4ba7190fa84f18937527c477247e926abeb9b1168b8cc"},
{file = "mypy-0.941-py3-none-any.whl", hash = "sha256:3cf77f138efb31727ee7197bc824c9d6d7039204ed96756cc0f9ca7d8e8fc2a4"},
{file = "mypy-0.941.tar.gz", hash = "sha256:cbcc691d8b507d54cb2b8521f0a2a3d4daa477f62fe77f0abba41e5febb377b7"},
]
mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
@ -1469,8 +1473,8 @@ nodeenv = [
{file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"},
]
notebook = [
{file = "notebook-6.4.8-py3-none-any.whl", hash = "sha256:3e702fcc54b8ae597533c3864793b7a1e971dec9e112f67235828d8a798fd654"},
{file = "notebook-6.4.8.tar.gz", hash = "sha256:1e985c9dc6f678bdfffb9dc657306b5469bfa62d73e03f74e8defbf76d284312"},
{file = "notebook-6.4.10-py3-none-any.whl", hash = "sha256:49cead814bff0945fcb2ee07579259418672ac175d3dc3d8102a4b0a656ed4df"},
{file = "notebook-6.4.10.tar.gz", hash = "sha256:2408a76bc6289283a8eecfca67e298ec83c67db51a4c2e1b713dd180bb39e90e"},
]
packaging = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
@ -1794,8 +1798,8 @@ webencodings = [
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
]
widgetsnbextension = [
{file = "widgetsnbextension-3.5.2-py2.py3-none-any.whl", hash = "sha256:763a9fdc836d141fa080005a886d63f66f73d56dba1fb5961afc239c77708569"},
{file = "widgetsnbextension-3.5.2.tar.gz", hash = "sha256:e0731a60ba540cd19bbbefe771a9076dcd2dde90713a8f87f27f53f2d1db7727"},
{file = "widgetsnbextension-3.6.0-py2.py3-none-any.whl", hash = "sha256:4fd321cad39fdcf8a8e248a657202d42917ada8e8ed5dd3f60f073e0d54ceabd"},
{file = "widgetsnbextension-3.6.0.tar.gz", hash = "sha256:e84a7a9fcb9baf3d57106e184a7389a8f8eb935bf741a5eb9d60aa18cc029a80"},
]
zipp = [
{file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"},

View file

@ -40,7 +40,7 @@ jupyter = ["ipywidgets"]
[tool.poetry.dev-dependencies]
pytest = "^7.0.0"
black = "^22.1"
mypy = "^0.931"
mypy = "^0.941"
pytest-cov = "^3.0.0"
attrs = "^21.4.0"
types-dataclasses = "^0.6.4"

View file

@ -334,7 +334,7 @@ class LegacyWindowsTerm:
15, # bright white
]
def __init__(self, file: IO[str]) -> None:
def __init__(self, file: "IO[str]") -> None:
handle = GetStdHandle(STDOUT)
self._handle = handle
default_text = GetConsoleScreenBufferInfo(handle).wAttributes

View file

@ -11,9 +11,7 @@ def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) ->
buffer (Iterable[Segment]): Iterable of Segments to convert to Win32 API calls.
term (LegacyWindowsTerm): Used to call the Windows Console API.
"""
for segment in buffer:
text, style, control = segment
for text, style, control in buffer:
if not control:
if style:
term.write_styled(text, style)

View file

@ -1,5 +1,6 @@
from contextlib import suppress
import re
import sys
from contextlib import suppress
from typing import Iterable, NamedTuple
from .color import Color
@ -198,10 +199,10 @@ class AnsiDecoder:
return text
if __name__ == "__main__": # pragma: no cover
import pty
if sys.platform != "win32" and __name__ == "__main__": # pragma: no cover
import io
import os
import pty
import sys
decoder = AnsiDecoder()

View file

@ -113,14 +113,12 @@ def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]:
_get_character_cell_size = get_character_cell_size
characters = [
(character, _get_character_cell_size(character)) for character in text
][::-1]
]
total_size = position
lines: List[List[str]] = [[]]
append = lines[-1].append
pop = characters.pop
while characters:
character, size = pop()
for character, size in reversed(characters):
if total_size + size > max_size:
lines.append([character])
append = lines[-1].append
@ -128,6 +126,7 @@ def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]:
else:
total_size += size
append(character)
return ["".join(line) for line in lines]

View file

@ -82,6 +82,17 @@ class NoChange:
NO_CHANGE = NoChange()
try:
_STDOUT_FILENO = sys.__stdout__.fileno()
except Exception:
_STDOUT_FILENO = 1
try:
_STDERR_FILENO = sys.__stderr__.fileno()
except Exception:
_STDERR_FILENO = 2
_STD_STREAMS = (_STDOUT_FILENO, _STDERR_FILENO)
CONSOLE_HTML_FORMAT = """\
<!DOCTYPE html>
@ -1909,12 +1920,21 @@ class Console:
buffer_extend(line)
def _check_buffer(self) -> None:
"""Check if the buffer may be rendered."""
"""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
legacy Windows consoles, the win32 API is called directly.
This method will also record what it renders if recording is enabled via Console.record.
"""
if self.quiet:
del self._buffer[:]
return
with self._lock:
if self._buffer_index == 0:
if self.record:
with self._record_buffer_lock:
self._record_buffer.extend(self._buffer[:])
if self.is_jupyter: # pragma: no cover
from .jupyter import display
@ -1922,23 +1942,24 @@ class Console:
del self._buffer[:]
else:
if WINDOWS:
use_legacy_windows_render = False
if self.legacy_windows:
try:
file_no = self.file.fileno()
use_legacy_windows_render = (
self.file.fileno() in _STD_STREAMS
)
except (ValueError, io.UnsupportedOperation):
file_no = -1
pass
legacy_windows_stdout = self.legacy_windows and file_no == 1
if legacy_windows_stdout:
if use_legacy_windows_render:
from rich._win32_console import LegacyWindowsTerm
from rich._windows_renderer import legacy_windows_render
with open(file_no, "w") as output_file:
legacy_windows_render(
self._buffer[:], LegacyWindowsTerm(output_file)
self._buffer[:], LegacyWindowsTerm(self.file)
)
output_capture_enabled = bool(self._buffer_index)
if not legacy_windows_stdout or output_capture_enabled:
else:
# Either a non-std stream on legacy Windows, or modern Windows.
text = self._render_buffer(self._buffer[:])
# https://bugs.python.org/issue37871
write = self.file.write
@ -1965,9 +1986,6 @@ class Console:
append = output.append
color_system = self._color_system
legacy_windows = self.legacy_windows
if self.record:
with self._record_buffer_lock:
self._record_buffer.extend(buffer)
not_terminal = not self.is_terminal
if self.no_color and color_system:
buffer = Segment.remove_color(buffer)

View file

@ -90,13 +90,13 @@ class ReprHighlighter(RegexHighlighter):
r"(?P<ipv6>([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})",
r"(?P<eui64>(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})",
r"(?P<eui48>(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})",
r"(?P<uuid>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})",
r"(?P<call>[\w.]*?)\(",
r"\b(?P<bool_true>True)\b|\b(?P<bool_false>False)\b|\b(?P<none>None)\b",
r"(?P<ellipsis>\.\.\.)",
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<uuid>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})",
r"(?P<url>(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#]*)",
),
]

View file

@ -11,6 +11,7 @@ from typing import (
Iterator,
List,
Optional,
NamedTuple,
Sequence,
Tuple,
Type,
@ -58,7 +59,7 @@ ControlCode = Union[
@rich_repr()
class Segment:
class Segment(NamedTuple):
"""A piece of text with associated style. Segments are produced by the Console render process and
are ultimately converted in to strings to be written to the terminal.
@ -71,32 +72,19 @@ class Segment:
cell_length (int): The cell length of this Segment.
"""
__slots__ = ["text", "style", "control", "cell_length", "_tuple"]
text: str
style: Optional[Style] = None
control: Optional[Sequence[ControlCode]] = None
def __init__(
self,
text: str = "",
style: Optional[Style] = None,
control: Optional[Sequence[ControlCode]] = None,
):
self.text = text
self.style = style
self.control = control
@property
def cell_length(self) -> int:
"""The number of terminal cells required to display self.text.
self.cell_length = 0 if self.control else cell_len(self.text)
self._tuple = text, style, control
def __iter__(self) -> Iterator[Any]:
return iter(self._tuple)
def __eq__(self, other: object) -> bool:
if isinstance(other, Segment):
return self._tuple == other._tuple
return self._tuple == other
def __hash__(self) -> int:
return hash(self._tuple)
Returns:
int: A number of cells.
"""
text, _style, control = self
return 0 if control else cell_len(text)
def __rich_repr__(self) -> Result:
yield self.text

View file

@ -83,6 +83,7 @@ highlight_tests = [
('"""hello"""', [Span(0, 11, "repr.str")]),
("\\'foo'", []),
("it's no 'string'", [Span(8, 16, "repr.str")]),
("78351748-9b32-4e08-ad3e-7e9ff124d541", [Span(0, 36, "repr.uuid")]),
]