Merge pull request #1387 from willmcgugan/10.7.0

10.7.0
This commit is contained in:
Will McGugan 2021-08-05 21:14:44 +01:00 committed by GitHub
commit 52d159aae0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 430 additions and 233 deletions

View File

@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [10.7.0] - 2021-08-05
### Added
- Added Text.apply_meta
- Added meta argument to Text.assemble
- Added Style.from_meta
- Added Style.on
- Added Text.on
### Changed
- Changed `RenderGroup` to `Group` and `render_group` to `group` (old names remain for compatibility but will be deprecated in the future)
- Changed `rich.repr.RichReprResult` to `rich.repr.Result` (old names remain for compatibility but will be deprecated in the future)
- Changed meta serialization to use pickle rather than marshal to permit callables
## [10.6.0] - 2021-07-12
### Deprecated

View File

@ -5,7 +5,7 @@ format-check:
format:
black .
typecheck:
mypy -p rich --strict
mypy -p rich --strict --no-incremental
typecheck-report:
mypy -p rich --strict --html-report mypy_report
.PHONY: docs

View File

@ -1,28 +1,28 @@
Render Groups
=============
The :class:`~rich.console.RenderGroup` class allows you to group several renderables together so they may be rendered in a context where only a single renderable may be supplied. For instance, you might want to display several renderables within a :class:`~rich.panel.Panel`.
The :class:`~rich.console.Group` class allows you to group several renderables together so they may be rendered in a context where only a single renderable may be supplied. For instance, you might want to display several renderables within a :class:`~rich.panel.Panel`.
To render two panels within a third panel, you would construct a RenderGroup with the *child* renderables as positional arguments then wrap the result in another Panel::
To render two panels within a third panel, you would construct a Group with the *child* renderables as positional arguments then wrap the result in another Panel::
from rich import print
from rich.console import RenderGroup
from rich.console import Group
from rich.panel import Panel
panel_group = RenderGroup(
panel_group = Group(
Panel("Hello", style="on blue"),
Panel("World", style="on red"),
)
print(Panel(panel_group))
This pattern is nice when you know in advance what renderables will be in a group, but can get awkward if you have a larger number of renderables, especially if they are dynamic. Rich provides a :func:`~rich.console.render_group` decorator to help with these situations. The decorator builds a render group from an iterator of renderables. The following is the equivalent of the previous example using the decorator::
This pattern is nice when you know in advance what renderables will be in a group, but can get awkward if you have a larger number of renderables, especially if they are dynamic. Rich provides a :func:`~rich.console.group` decorator to help with these situations. The decorator builds a group from an iterator of renderables. The following is the equivalent of the previous example using the decorator::
from rich import print
from rich.console import render_group
from rich.console import group
from rich.panel import Panel
@render_group()
@group()
def get_panels():
yield Panel("Hello", style="on blue")
yield Panel("World", style="on red")

View File

@ -5,6 +5,9 @@ Console Markup
Rich supports a simple markup which you can use to insert color and styles virtually everywhere Rich would accept a string (e.g. :meth:`~rich.console.Console.print` and :meth:`~rich.console.Console.log`).
Run the following command to see some examples::
python -m rich.markup
Syntax
------

View File

@ -7,7 +7,7 @@ from datetime import datetime
from rich import box
from rich.align import Align
from rich.console import Console, RenderGroup
from rich.console import Console, Group
from rich.layout import Layout
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn
@ -67,7 +67,7 @@ def make_sponsor_message() -> Panel:
message_panel = Panel(
Align.center(
RenderGroup(intro_message, "\n", Align.center(sponsor_message)),
Group(intro_message, "\n", Align.center(sponsor_message)),
vertical="middle",
),
box=box.ROUNDED,

View File

@ -1,8 +1,8 @@
from rich import print
from rich.console import RenderGroup
from rich.console import Group
from rich.panel import Panel
panel_group = RenderGroup(
panel_group = Group(
Panel("Hello", style="on blue"),
Panel("World", style="on red"),
)

View File

@ -1,9 +1,9 @@
from rich import print
from rich.console import render_group
from rich.console import group
from rich.panel import Panel
@render_group()
@group()
def get_panels():
yield Panel("Hello", style="on blue")
yield Panel("World", style="on red")

183
poetry.lock generated
View File

@ -94,11 +94,11 @@ d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
[[package]]
name = "bleach"
version = "3.3.0"
version = "4.0.0"
description = "An easy safelist-based HTML-sanitizing tool."
category = "main"
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
python-versions = ">=3.6"
[package.dependencies]
packaging = "*"
@ -192,7 +192,7 @@ python-versions = ">=2.7"
[[package]]
name = "importlib-metadata"
version = "4.6.1"
version = "4.6.3"
description = "Read metadata from Python packages"
category = "main"
optional = false
@ -509,7 +509,7 @@ python-versions = ">=3.5"
[[package]]
name = "notebook"
version = "6.4.0"
version = "6.4.1"
description = "A web-based notebook environment for interactive computing"
category = "main"
optional = true
@ -569,11 +569,11 @@ testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
name = "pathspec"
version = "0.8.1"
version = "0.9.0"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[[package]]
name = "pexpect"
@ -718,7 +718,7 @@ testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtuale
[[package]]
name = "python-dateutil"
version = "2.8.1"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
optional = true
@ -745,7 +745,7 @@ python-versions = ">=3.6"
[[package]]
name = "pyzmq"
version = "22.1.0"
version = "22.2.1"
description = "Python bindings for 0MQ"
category = "main"
optional = true
@ -757,7 +757,7 @@ py = {version = "*", markers = "implementation_name == \"pypy\""}
[[package]]
name = "regex"
version = "2021.7.6"
version = "2021.8.3"
description = "Alternative regular expression module, to replace re."
category = "dev"
optional = false
@ -940,6 +940,10 @@ argon2-cffi = [
{file = "argon2_cffi-20.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2"},
{file = "argon2_cffi-20.1.0-cp39-cp39-win32.whl", hash = "sha256:e2db6e85c057c16d0bd3b4d2b04f270a7467c147381e8fd73cbbe5bc719832be"},
{file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"},
{file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b94042e5dcaa5d08cf104a54bfae614be502c6f44c9c89ad1535b2ebdaacbd4c"},
{file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:8282b84ceb46b5b75c3a882b28856b8cd7e647ac71995e71b6705ec06fc232c3"},
{file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3aa804c0e52f208973845e8b10c70d8957c9e5a666f702793256242e9167c4e0"},
{file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:36320372133a003374ef4275fbfce78b7ab581440dfca9f9471be3dd9a522428"},
]
async-generator = [
{file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"},
@ -961,8 +965,8 @@ black = [
{file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
]
bleach = [
{file = "bleach-3.3.0-py2.py3-none-any.whl", hash = "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125"},
{file = "bleach-3.3.0.tar.gz", hash = "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433"},
{file = "bleach-4.0.0-py2.py3-none-any.whl", hash = "sha256:c1685a132e6a9a38bf93752e5faab33a9517a6c0bb2f37b785e47bf253bdb51d"},
{file = "bleach-4.0.0.tar.gz", hash = "sha256:ffa9221c6ac29399cc50fcc33473366edd0cf8d5e2cbbbb63296dc327fb67cc8"},
]
cffi = [
{file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"},
@ -972,6 +976,11 @@ cffi = [
{file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"},
{file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"},
{file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"},
{file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"},
{file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"},
{file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"},
{file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"},
{file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"},
{file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"},
{file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"},
{file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"},
@ -1089,8 +1098,8 @@ entrypoints = [
{file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"},
]
importlib-metadata = [
{file = "importlib_metadata-4.6.1-py3-none-any.whl", hash = "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"},
{file = "importlib_metadata-4.6.1.tar.gz", hash = "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac"},
{file = "importlib_metadata-4.6.3-py3-none-any.whl", hash = "sha256:51c6635429c77cf1ae634c997ff9e53ca3438b495f10a55ba28594dd69764a8b"},
{file = "importlib_metadata-4.6.3.tar.gz", hash = "sha256:0645585859e9a6689c523927a5032f2ba5919f1f7d0e84bd4533312320de1ff9"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
@ -1226,8 +1235,8 @@ nest-asyncio = [
{file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"},
]
notebook = [
{file = "notebook-6.4.0-py3-none-any.whl", hash = "sha256:f7f0a71a999c7967d9418272ae4c3378a220bd28330fbfb49860e46cf8a5838a"},
{file = "notebook-6.4.0.tar.gz", hash = "sha256:9c4625e2a2aa49d6eae4ce20cbc3d8976db19267e32d2a304880e0c10bf8aef9"},
{file = "notebook-6.4.1-py3-none-any.whl", hash = "sha256:5d999285fd449898c4dfa0b7880dd881f317c653eb221e8d51d0b5400751ce35"},
{file = "notebook-6.4.1.tar.gz", hash = "sha256:2a67037730e2b2991f5d684ecb07255bbb191f49234888e71e1fabf8e50679a6"},
]
packaging = [
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
@ -1241,8 +1250,8 @@ parso = [
{file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"},
]
pathspec = [
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},
{file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"},
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
]
pexpect = [
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
@ -1316,8 +1325,8 @@ pytest-cov = [
{file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"},
]
python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
pywin32 = [
{file = "pywin32-301-cp35-cp35m-win32.whl", hash = "sha256:93367c96e3a76dfe5003d8291ae16454ca7d84bb24d721e0b74a07610b7be4a7"},
@ -1339,81 +1348,71 @@ pywinpty = [
{file = "pywinpty-1.1.3.tar.gz", hash = "sha256:3a1d57b338390333812a5eed31c93c7d8ba82b131078063703e731946d90c9f2"},
]
pyzmq = [
{file = "pyzmq-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4e9b9a2f6944acdaf57316436c1acdcb30b8df76726bcf570ad9342bc5001654"},
{file = "pyzmq-22.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24fb5bb641f0b2aa25fc3832f4b6fc62430f14a7d328229fe994b2bcdc07c93a"},
{file = "pyzmq-22.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c4674004ed64685a38bee222cd75afa769424ec603f9329f0dd4777138337f48"},
{file = "pyzmq-22.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:461ed80d741692d9457ab820b1cc057ba9c37c394e67b647b639f623c8b321f6"},
{file = "pyzmq-22.1.0-cp36-cp36m-win32.whl", hash = "sha256:de5806be66c9108e4dcdaced084e8ceae14100aa559e2d57b4f0cceb98c462de"},
{file = "pyzmq-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a1c77796f395804d6002ff56a6a8168c1f98579896897ad7e35665a9b4a9eec5"},
{file = "pyzmq-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a81c9e6754465d09a87e3acd74d9bb1f0039b2d785c6899622f0afdb41d760"},
{file = "pyzmq-22.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0f0f27eaab9ba7b92d73d71c51d1a04464a1da6097a252d007922103253d2313"},
{file = "pyzmq-22.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4b8fb1b3174b56fd020e4b10232b1764e52cf7f3babcfb460c5253bdc48adad0"},
{file = "pyzmq-22.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c8fff75af4c7af92dce9f81fa2a83ed009c3e1f33ee8b5222db2ef80b94e242e"},
{file = "pyzmq-22.1.0-cp37-cp37m-win32.whl", hash = "sha256:cb9f9fe1305ef69b65794655fd89b2209b11bff3e837de981820a8aa051ef914"},
{file = "pyzmq-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bf80b2cec42d96117248b99d3c86e263a00469c840a778e6cb52d916f4fdf82c"},
{file = "pyzmq-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0ea7f4237991b0f745a4432c63e888450840bf8cb6c48b93fb7d62864f455529"},
{file = "pyzmq-22.1.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:12ffcf33db6ba7c0e5aaf901e65517f5e2b719367b80bcbfad692f546a297c7a"},
{file = "pyzmq-22.1.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d3ecfee2ee8d91ab2e08d2d8e89302c729b244e302bbc39c5b5dde42306ff003"},
{file = "pyzmq-22.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:68e2c4505992ab5b89f976f89a9135742b18d60068f761bef994a6805f1cae0c"},
{file = "pyzmq-22.1.0-cp38-cp38-win32.whl", hash = "sha256:285514956c08c7830da9d94e01f5414661a987831bd9f95e4d89cc8aaae8da10"},
{file = "pyzmq-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d5e5be93e1714a59a535bbbc086b9e4fd2448c7547c5288548f6fd86353cad9e"},
{file = "pyzmq-22.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:b2f707b52e09098a7770503e39294ca6e22ae5138ffa1dd36248b6436d23d78e"},
{file = "pyzmq-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:18dd2ca4540c476558099891c129e6f94109971d110b549db2a9775c817cedbd"},
{file = "pyzmq-22.1.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:c6d0c32532a0519997e1ded767e184ebb8543bdb351f8eff8570bd461e874efc"},
{file = "pyzmq-22.1.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9ee48413a2d3cd867fd836737b4c89c24cea1150a37f4856d82d20293fa7519f"},
{file = "pyzmq-22.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:4c4fe69c7dc0d13d4ae180ad650bb900854367f3349d3c16f0569f6c6447f698"},
{file = "pyzmq-22.1.0-cp39-cp39-win32.whl", hash = "sha256:fc712a90401bcbf3fa25747f189d6dcfccbecc32712701cad25c6355589dac57"},
{file = "pyzmq-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:68be16107f41563b9f67d93dff1c9f5587e0f76aa8fd91dc04c83d813bcdab1f"},
{file = "pyzmq-22.1.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:734ea6565c71fc2d03d5b8c7d0d7519c96bb5567e0396da1b563c24a4ac66f0c"},
{file = "pyzmq-22.1.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:1389b615917d4196962a9b469e947ba862a8ec6f5094a47da5e7a8d404bc07a4"},
{file = "pyzmq-22.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:41049cff5265e9cd75606aa2c90a76b9c80b98d8fe70ee08cf4af3cedb113358"},
{file = "pyzmq-22.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f49755684a963731479ff3035d45a8185545b4c9f662d368bd349c419839886d"},
{file = "pyzmq-22.1.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:6355f81947e1fe6e7bb9e123aeb3067264391d3ebe8402709f824ef8673fa6f3"},
{file = "pyzmq-22.1.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:089b974ec04d663b8685ac90e86bfe0e4da9d911ff3cf52cb765ff22408b102d"},
{file = "pyzmq-22.1.0.tar.gz", hash = "sha256:7040d6dd85ea65703904d023d7f57fab793d7ffee9ba9e14f3b897f34ff2415d"},
{file = "pyzmq-22.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b921758f8b5098faa85f341bbdd5e36d5339de5e9032ca2b07d8c8e7bec5069b"},
{file = "pyzmq-22.2.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:240b83b3a8175b2f616f80092cbb019fcd5c18598f78ffc6aa0ae9034b300f14"},
{file = "pyzmq-22.2.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:da7f7f3bb08bcf59a6b60b4e53dd8f08bb00c9e61045319d825a906dbb3c8fb7"},
{file = "pyzmq-22.2.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e66025b64c4724ba683d6d4a4e5ee23de12fe9ae683908f0c7f0f91b4a2fd94e"},
{file = "pyzmq-22.2.1-cp36-cp36m-win32.whl", hash = "sha256:50d007d5702171bc810c1e74498fa2c7bc5b50f9750697f7fd2a3e71a25aad91"},
{file = "pyzmq-22.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b4a51c7d906dc263a0cc5590761e53e0a68f2c2fefe549cbef21c9ee5d2d98a4"},
{file = "pyzmq-22.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:93705cb90baa9d6f75e8448861a1efd3329006f79095ab18846bd1eaa342f7c3"},
{file = "pyzmq-22.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:620b0abb813958cb3ecb5144c177e26cde92fee6f43c4b9de6b329515532bf27"},
{file = "pyzmq-22.2.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2dd3896b3c952cf6c8013deda53c1df16bf962f355b5503d23521e0f6403ae3d"},
{file = "pyzmq-22.2.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6e9c030222893afa86881d7485d3e841969760a16004bd23e9a83cca28b42778"},
{file = "pyzmq-22.2.1-cp37-cp37m-win32.whl", hash = "sha256:262f470e7acde18b7217aac78d19d2e29ced91a5afbeb7d98521ebf26461aa7e"},
{file = "pyzmq-22.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:246f27b88722cfa729bb04881e94484e40b085720d728c1b05133b3f331b0b7b"},
{file = "pyzmq-22.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0d17bac19e934e9f547a8811b7c2a32651a7840f38086b924e2e3dcb2fae5c3a"},
{file = "pyzmq-22.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5933d1f4087de6e52906f72d92e1e4dcc630d371860b92c55d7f7a4b815a664c"},
{file = "pyzmq-22.2.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac4497e4b7d134ee53ce5532d9cc3b640d6e71806a55062984e0c99a2f88f465"},
{file = "pyzmq-22.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66375a6094af72a6098ed4403b15b4db6bf00013c6febc1baa832e7abda827f4"},
{file = "pyzmq-22.2.1-cp38-cp38-win32.whl", hash = "sha256:b2c16d20bd0aef8e57bc9505fdd80ea0d6008020c3740accd96acf1b3d1b5347"},
{file = "pyzmq-22.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff345d48940c834168f81fa1d4724675099f148f1ab6369748c4d712ed71bf7c"},
{file = "pyzmq-22.2.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:f5c84c5de9a773bbf8b22c51e28380999ea72e5e85b4db8edf5e69a7a0d4d9f9"},
{file = "pyzmq-22.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2534a036b777f957bd6b89b55fb2136775ca2659fb0f1c85036ba78d17d86fd5"},
{file = "pyzmq-22.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a649065413ba4eab92a783a7caa4de8ce14cf46ba8a2a09951426143f1298adb"},
{file = "pyzmq-22.2.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c9cb0bd3a3cb7ccad3caa1d7b0d18ba71ed3a4a3610028e506a4084371d4d223"},
{file = "pyzmq-22.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4428302c389fffc0c9c07a78cad5376636b9d096f332acfe66b321ae9ff2c63"},
{file = "pyzmq-22.2.1-cp39-cp39-win32.whl", hash = "sha256:6a5b4566f66d953601d0d47d4071897f550a265bafd52ebcad5ac7aad3838cbb"},
{file = "pyzmq-22.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:89200ab6ef9081c72a04ed84c52a50b60dcb0655375aeedb40689bc7c934715e"},
{file = "pyzmq-22.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed67df4eaa99a20d162d76655bda23160abdf8abf82a17f41dfd3962e608dbcc"},
{file = "pyzmq-22.2.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:021e22a8c58ab294bd4b96448a2ca4e716e1d76600192ff84c33d71edb1fbd37"},
{file = "pyzmq-22.2.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:200ac096cee5499964c90687306a7244b79ef891f773ed4cf15019fd1f3df330"},
{file = "pyzmq-22.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b3f57bee62e36be5c97712de32237c5589caee0d1154c2ad01a888accfae20bc"},
{file = "pyzmq-22.2.1.tar.gz", hash = "sha256:6d18c76676771fd891ca8e0e68da0bbfb88e30129835c0ade748016adb3b6242"},
]
regex = [
{file = "regex-2021.7.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222"},
{file = "regex-2021.7.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407"},
{file = "regex-2021.7.6-cp36-cp36m-win32.whl", hash = "sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b"},
{file = "regex-2021.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb"},
{file = "regex-2021.7.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad"},
{file = "regex-2021.7.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895"},
{file = "regex-2021.7.6-cp37-cp37m-win32.whl", hash = "sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5"},
{file = "regex-2021.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f"},
{file = "regex-2021.7.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c"},
{file = "regex-2021.7.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0"},
{file = "regex-2021.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26"},
{file = "regex-2021.7.6-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f"},
{file = "regex-2021.7.6-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf"},
{file = "regex-2021.7.6-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd"},
{file = "regex-2021.7.6-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761"},
{file = "regex-2021.7.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068"},
{file = "regex-2021.7.6-cp38-cp38-win32.whl", hash = "sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0"},
{file = "regex-2021.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4"},
{file = "regex-2021.7.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026"},
{file = "regex-2021.7.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417"},
{file = "regex-2021.7.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde"},
{file = "regex-2021.7.6-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59"},
{file = "regex-2021.7.6-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985"},
{file = "regex-2021.7.6-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d"},
{file = "regex-2021.7.6-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58"},
{file = "regex-2021.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3"},
{file = "regex-2021.7.6-cp39-cp39-win32.whl", hash = "sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035"},
{file = "regex-2021.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c"},
{file = "regex-2021.7.6.tar.gz", hash = "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d"},
{file = "regex-2021.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8764a78c5464ac6bde91a8c87dd718c27c1cabb7ed2b4beaf36d3e8e390567f9"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4551728b767f35f86b8e5ec19a363df87450c7376d7419c3cac5b9ceb4bce576"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:577737ec3d4c195c4aef01b757905779a9e9aee608fa1cf0aec16b5576c893d3"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c856ec9b42e5af4fe2d8e75970fcc3a2c15925cbcc6e7a9bcb44583b10b95e80"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3835de96524a7b6869a6c710b26c90e94558c31006e96ca3cf6af6751b27dca1"},
{file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cea56288eeda8b7511d507bbe7790d89ae7049daa5f51ae31a35ae3c05408531"},
{file = "regex-2021.8.3-cp36-cp36m-win32.whl", hash = "sha256:a4eddbe2a715b2dd3849afbdeacf1cc283160b24e09baf64fa5675f51940419d"},
{file = "regex-2021.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:57fece29f7cc55d882fe282d9de52f2f522bb85290555b49394102f3621751ee"},
{file = "regex-2021.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a5c6dbe09aff091adfa8c7cfc1a0e83fdb8021ddb2c183512775a14f1435fe16"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff4a8ad9638b7ca52313d8732f37ecd5fd3c8e3aff10a8ccb93176fd5b3812f6"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b63e3571b24a7959017573b6455e05b675050bbbea69408f35f3cb984ec54363"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fbc20975eee093efa2071de80df7f972b7b35e560b213aafabcec7c0bd00bd8c"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14caacd1853e40103f59571f169704367e79fb78fac3d6d09ac84d9197cadd16"},
{file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb350eb1060591d8e89d6bac4713d41006cd4d479f5e11db334a48ff8999512f"},
{file = "regex-2021.8.3-cp37-cp37m-win32.whl", hash = "sha256:18fdc51458abc0a974822333bd3a932d4e06ba2a3243e9a1da305668bd62ec6d"},
{file = "regex-2021.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:026beb631097a4a3def7299aa5825e05e057de3c6d72b139c37813bfa351274b"},
{file = "regex-2021.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:16d9eaa8c7e91537516c20da37db975f09ac2e7772a0694b245076c6d68f85da"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3905c86cc4ab6d71635d6419a6f8d972cab7c634539bba6053c47354fd04452c"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937b20955806381e08e54bd9d71f83276d1f883264808521b70b33d98e4dec5d"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:28e8af338240b6f39713a34e337c3813047896ace09d51593d6907c66c0708ba"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c09d88a07483231119f5017904db8f60ad67906efac3f1baa31b9b7f7cca281"},
{file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:85f568892422a0e96235eb8ea6c5a41c8ccbf55576a2260c0160800dbd7c4f20"},
{file = "regex-2021.8.3-cp38-cp38-win32.whl", hash = "sha256:bf6d987edd4a44dd2fa2723fca2790f9442ae4de2c8438e53fcb1befdf5d823a"},
{file = "regex-2021.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:8fe58d9f6e3d1abf690174fd75800fda9bdc23d2a287e77758dc0e8567e38ce6"},
{file = "regex-2021.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7976d410e42be9ae7458c1816a416218364e06e162b82e42f7060737e711d9ce"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9569da9e78f0947b249370cb8fadf1015a193c359e7e442ac9ecc585d937f08d"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bbe342c5b2dec5c5223e7c363f291558bc27982ef39ffd6569e8c082bdc83"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f421e3cdd3a273bace013751c345f4ebeef08f05e8c10757533ada360b51a39"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea212df6e5d3f60341aef46401d32fcfded85593af1d82b8b4a7a68cd67fdd6b"},
{file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a3b73390511edd2db2d34ff09aa0b2c08be974c71b4c0505b4a048d5dc128c2b"},
{file = "regex-2021.8.3-cp39-cp39-win32.whl", hash = "sha256:f35567470ee6dbfb946f069ed5f5615b40edcbb5f1e6e1d3d2b114468d505fc6"},
{file = "regex-2021.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:bfa6a679410b394600eafd16336b2ce8de43e9b13f7fb9247d84ef5ad2b45e91"},
{file = "regex-2021.8.3.tar.gz", hash = "sha256:8935937dad2c9b369c3d932b0edbc52a62647c2afb2fafc0c280f14a8bf56a6a"},
]
send2trash = [
{file = "Send2Trash-1.7.1-py3-none-any.whl", hash = "sha256:c20fee8c09378231b3907df9c215ec9766a84ee20053d99fbad854fe8bd42159"},

View File

@ -2,7 +2,7 @@
name = "rich"
homepage = "https://github.com/willmcgugan/rich"
documentation = "https://rich.readthedocs.io/en/latest/"
version = "10.6.0"
version = "10.7.0"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
authors = ["Will McGugan <willmcgugan@gmail.com>"]
license = "MIT"

View File

@ -9,7 +9,7 @@ from rich.console import (
Console,
ConsoleOptions,
ConsoleRenderable,
RenderGroup,
Group,
RenderResult,
RenderableType,
)
@ -88,7 +88,7 @@ def make_test_card() -> Table:
)
table.add_row(
"Text",
RenderGroup(
Group(
Text.from_markup(
"""Word wrap text. Justify [green]left[/], [yellow]center[/], [blue]right[/] or [red]full[/].\n"""
),

View File

@ -3,7 +3,7 @@ from __future__ import absolute_import
from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature
from typing import Any, Iterable, Optional, Tuple
from .console import RenderableType, RenderGroup
from .console import RenderableType, Group
from .highlighter import ReprHighlighter
from .jupyter import JupyterMixin
from .panel import Panel
@ -79,7 +79,7 @@ class Inspect(JupyterMixin):
def __rich__(self) -> Panel:
return Panel.fit(
RenderGroup(*self._render()),
Group(*self._render()),
title=self.title,
border_style="scope.border",
padding=(0, 1),

View File

@ -289,7 +289,7 @@ class VerticalCenter(JupyterMixin):
if __name__ == "__main__": # pragma: no cover
from rich.console import Console, RenderGroup
from rich.console import Console, Group
from rich.highlighter import ReprHighlighter
from rich.panel import Panel
@ -297,7 +297,7 @@ if __name__ == "__main__": # pragma: no cover
console = Console()
panel = Panel(
RenderGroup(
Group(
Align.left(highlighter("align='left'")),
Align.center(highlighter("align='center'")),
Align.right(highlighter("align='right'")),

View File

@ -1,5 +1,4 @@
from functools import lru_cache
from logging import StrFormatStyle
from typing import Dict, List
from ._cell_widths import CELL_WIDTHS

View File

@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, NamedTuple, Optional, Tuple
from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE
from .color_triplet import ColorTriplet
from .repr import rich_repr, RichReprResult
from .repr import rich_repr, Result
from .terminal_theme import DEFAULT_TERMINAL_THEME
if TYPE_CHECKING: # pragma: no cover
@ -288,7 +288,7 @@ class Color(NamedTuple):
" >",
)
def __rich_repr__(self) -> RichReprResult:
def __rich_repr__(self) -> Result:
yield self.name
yield self.type
yield "number", self.number, None

View File

@ -10,10 +10,10 @@ from dataclasses import dataclass, field
from datetime import datetime
from functools import wraps
from getpass import getpass
from inspect import isclass
from itertools import islice
from time import monotonic
from types import FrameType, TracebackType
from inspect import isclass
from typing import (
IO,
TYPE_CHECKING,
@ -28,12 +28,10 @@ from typing import (
TextIO,
Tuple,
Type,
Tuple,
Union,
cast,
)
if sys.version_info >= (3, 8):
from typing import Literal, Protocol, runtime_checkable
else:
@ -43,7 +41,6 @@ else:
runtime_checkable,
) # pragma: no cover
from . import errors, themes
from ._emoji_replace import _emoji_replace
from ._log_render import FormatTimeCallable, LogRender
@ -408,7 +405,7 @@ class ScreenContext:
"""
if renderables:
self.screen.renderable = (
RenderGroup(*renderables) if len(renderables) > 1 else renderables[0]
Group(*renderables) if len(renderables) > 1 else renderables[0]
)
if style is not None:
self.screen.style = style
@ -432,7 +429,7 @@ class ScreenContext:
self.console.show_cursor(True)
class RenderGroup:
class Group:
"""Takes a group of renderables and returns a renderable object that renders the group.
Args:
@ -465,7 +462,10 @@ class RenderGroup:
yield from self.renderables
def render_group(fit: bool = True) -> Callable[..., Callable[..., RenderGroup]]:
RenderGroup = Group # TODO: deprecate at some point
def group(fit: bool = True) -> Callable[..., Callable[..., Group]]:
"""A decorator that turns an iterable of renderables in to a group.
Args:
@ -474,19 +474,22 @@ def render_group(fit: bool = True) -> Callable[..., Callable[..., RenderGroup]]:
def decorator(
method: Callable[..., Iterable[RenderableType]]
) -> Callable[..., RenderGroup]:
) -> Callable[..., Group]:
"""Convert a method that returns an iterable of renderables in to a RenderGroup."""
@wraps(method)
def _replace(*args: Any, **kwargs: Any) -> RenderGroup:
def _replace(*args: Any, **kwargs: Any) -> Group:
renderables = method(*args, **kwargs)
return RenderGroup(*renderables, fit=fit)
return Group(*renderables, fit=fit)
return _replace
return decorator
render_group = group
def _is_jupyter() -> bool: # pragma: no cover
"""Check if we're running in a Jupyter notebook."""
try:

View File

@ -20,7 +20,7 @@ from .console import Console, ConsoleOptions, RenderableType, RenderResult
from .highlighter import ReprHighlighter
from .panel import Panel
from .pretty import Pretty
from .repr import rich_repr, RichReprResult
from .repr import rich_repr, Result
from .region import Region
from .segment import Segment
from .style import StyleType
@ -175,7 +175,7 @@ class Layout:
self._render_map: RenderMap = {}
self._lock = RLock()
def __rich_repr__(self) -> RichReprResult:
def __rich_repr__(self) -> Result:
yield "name", self.name, None
yield "size", self.size, None
yield "minimum_size", self.minimum_size, 1

View File

@ -15,6 +15,8 @@ RE_TAGS = re.compile(
re.VERBOSE,
)
RE_HANDLER = re.compile(r"^([\w\.]*?)(\(.*?\))?$")
class Tag(NamedTuple):
"""A tag in console markup."""
@ -167,17 +169,34 @@ def render(
if open_tag.name.startswith("@"):
if open_tag.parameters:
handler_name = ""
parameters = open_tag.parameters.strip()
handler_match = RE_HANDLER.match(parameters)
if handler_match is not None:
handler_name, match_parameters = handler_match.groups()
parameters = (
"()" if match_parameters is None else match_parameters
)
try:
meta_params = literal_eval(open_tag.parameters)
meta_params = literal_eval(parameters)
except SyntaxError as error:
raise MarkupError(
f"error parsing {open_tag.parameters!r}; {error.msg}"
f"error parsing {parameters!r} in {open_tag.parameters!r}; {error.msg}"
)
except Exception as error:
raise MarkupError(
f"error parsing {open_tag.parameters!r}; {error}"
) from None
if handler_name:
meta_params = (
handler_name,
meta_params
if isinstance(meta_params, tuple)
else (meta_params,),
)
else:
meta_params = ()
@ -206,22 +225,20 @@ def render(
if __name__ == "__main__": # pragma: no cover
from rich.console import Console
from rich.text import Text
console = Console(highlight=True)
t = render("[b]Hello[/b] [@click='view.toggle', 'left']World[/]")
console.print(t)
console.print(t._spans)
console.print("Hello [1], [1,2,3] ['hello']")
console.print("foo")
console.print("Hello [link=https://www.willmcgugan.com]W[b red]o[/]rld[/]!")
MARKUP = [
"[red]Hello World[/red]",
"[magenta]Hello [b]World[/b]",
"[bold]Bold[italic] bold and italic [/bold]italic[/italic]",
"Click [link=https://www.willmcgugan.com]here[/link] to visit my Blog",
":warning-emoji: [bold red blink] DANGER![/]",
]
from rich.table import Table
from rich import print
print(escape("[red]"))
print(escape(r"\[red]"))
print(escape(r"\\[red]"))
print(escape(r"\\\[red]"))
grid = Table("Markup", "Result", padding=(0, 1))
for markup in MARKUP:
grid.add_row(Text(markup), markup)
print(grid)

View File

@ -25,7 +25,7 @@ from typing import (
)
from . import filesize, get_console
from .console import Console, JustifyMethod, RenderableType, RenderGroup
from .console import Console, JustifyMethod, RenderableType, Group
from .highlighter import Highlighter
from .jupyter import JupyterMixin
from .live import Live
@ -866,7 +866,7 @@ class Progress(JupyterMixin):
def get_renderable(self) -> RenderableType:
"""Get a renderable for the progress display."""
renderable = RenderGroup(*self.get_renderables())
renderable = Group(*self.get_renderables())
return renderable
def get_renderables(self) -> Iterable[RenderableType]:

View File

@ -18,7 +18,8 @@ from typing import (
T = TypeVar("T")
RichReprResult = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]]
Result = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]]
RichReprResult = Result
class ReprError(Exception):
@ -66,7 +67,7 @@ def auto(
else:
return f"{self.__class__.__name__}({', '.join(repr_str)})"
def auto_rich_repr(self: Type[T]) -> RichReprResult:
def auto_rich_repr(self: Type[T]) -> Result:
"""Auto generate __rich_rep__ from signature of __init__"""
try:
signature = inspect.signature(self.__init__) ## type: ignore
@ -125,7 +126,7 @@ if __name__ == "__main__":
@auto
class Foo:
def __rich_repr__(self) -> RichReprResult:
def __rich_repr__(self) -> Result:
yield "foo"
yield "bar", {"shopping": ["eggs", "ham", "pineapple"]}
yield "buy", "hand sanitizer"

View File

@ -12,7 +12,7 @@ if TYPE_CHECKING:
ConsoleOptions,
RenderResult,
RenderableType,
RenderGroup,
Group,
)
@ -32,9 +32,9 @@ class Screen:
style: Optional[StyleType] = None,
application_mode: bool = False,
) -> None:
from rich.console import RenderGroup
from rich.console import Group
self.renderable = RenderGroup(*renderables)
self.renderable = Group(*renderables)
self.style = style
self.application_mode = application_mode

View File

@ -1,15 +1,23 @@
from enum import IntEnum
from logging import getLogger
from typing import Dict, NamedTuple, Optional
from .repr import rich_repr, RichReprResult
from .cells import cell_len, set_cell_size, get_character_cell_size
from .style import Style
from functools import lru_cache
from itertools import filterfalse
from logging import getLogger
from operator import attrgetter
from typing import cast, Iterable, List, Sequence, Union, Tuple, TYPE_CHECKING
from typing import (
TYPE_CHECKING,
Dict,
Iterable,
List,
NamedTuple,
Optional,
Sequence,
Tuple,
Union,
)
from .cells import cell_len, get_character_cell_size, set_cell_size
from .repr import Result, rich_repr
from .style import Style
if TYPE_CHECKING:
from .console import Console, ConsoleOptions, RenderResult
@ -60,7 +68,7 @@ class Segment(NamedTuple):
control: Optional[Sequence[ControlCode]] = None
"""Optional sequence of control codes."""
def __rich_repr__(self) -> RichReprResult:
def __rich_repr__(self) -> Result:
yield self.text
if self.control is None:
if self.style is not None:
@ -83,22 +91,17 @@ class Segment(NamedTuple):
"""Check if the segment contains control codes."""
return self.control is not None
def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]: # type: ignore
"""Split segment in to two segments at the specified column.
@classmethod
@lru_cache(1024 * 16)
def _split_cells(cls, segment: "Segment", cut: int) -> Tuple["Segment", "Segment"]: # type: ignore
If the cut point falls in the middle of a 2-cell wide character then it is replaced
by two spaces, to preserve the display width of the parent segment.
Returns:
Tuple[Segment, Segment]: Two segments.
"""
text, style, control = self
assert cut >= 0
text, style, control = segment
_Segment = Segment
if cut >= self.cell_length:
return self, _Segment("", style, control)
if cut >= segment.cell_length:
return segment, _Segment("", style, control)
if len(text) == self.cell_length:
if len(text) == segment.cell_length:
# Fast path with all 1 cell characters
return (
_Segment(text[:cut], style, control),
_Segment(text[cut:], style, control),
@ -106,7 +109,7 @@ class Segment(NamedTuple):
cell_size = get_character_cell_size
pos = int((cut / self.cell_length) * len(text))
pos = int((cut / segment.cell_length) * len(text))
before = text[:pos]
cell_pos = cell_len(before)
@ -131,6 +134,17 @@ class Segment(NamedTuple):
_Segment(" " + text[pos:], style, control),
)
def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]:
"""Split segment in to two segments at the specified column.
If the cut point falls in the middle of a 2-cell wide character then it is replaced
by two spaces, to preserve the display width of the parent segment.
Returns:
Tuple[Segment, Segment]: Two segments.
"""
return self._split_cells(self, cut)
@classmethod
def line(cls) -> "Segment":
"""Make a new line segment."""
@ -574,9 +588,9 @@ class SegmentLines:
if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
from rich.console import Console
from rich.syntax import Syntax
from rich.text import Text
from rich.console import Console
code = """from rich.console import Console
console = Console()

View File

@ -1,13 +1,12 @@
import sys
from functools import lru_cache
from marshal import loads as marshal_loads, dumps as marshal_dumps
from marshal import loads, dumps
from random import randint
from time import time
from typing import Any, cast, Dict, Iterable, List, Optional, Type, Union
from . import errors
from .color import Color, ColorParseError, ColorSystem, blend_rgb
from .repr import rich_repr, RichReprResult
from .repr import rich_repr, Result
from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme
@ -96,6 +95,31 @@ class Style:
12: "53",
}
STYLE_ATTRIBUTES = {
"dim": "dim",
"d": "dim",
"bold": "bold",
"b": "bold",
"italic": "italic",
"i": "italic",
"underline": "underline",
"u": "underline",
"blink": "blink",
"blink2": "blink2",
"reverse": "reverse",
"r": "reverse",
"conceal": "conceal",
"c": "conceal",
"strike": "strike",
"s": "strike",
"underline2": "underline2",
"uu": "underline2",
"frame": "frame",
"encircle": "encircle",
"overline": "overline",
"o": "overline",
}
def __init__(
self,
*,
@ -165,8 +189,8 @@ class Style:
)
self._link = link
self._link_id = f"{time()}-{randint(0, 999999)}" if link else ""
self._meta = None if meta is None else marshal_dumps(meta)
self._link_id = f"{randint(0, 999999)}" if link else ""
self._meta = None if meta is None else dumps(meta)
self._hash = hash(
(
self._color,
@ -211,11 +235,60 @@ class Style:
None,
None,
None,
None,
)
)
style._null = not (color or bgcolor)
return style
@classmethod
def from_meta(cls, meta: Optional[Dict[str, Any]]) -> "Style":
"""Create a new style with meta data.
Returns:
meta (Optional[Dict[str, Any]]): A dictionary of meta data. Defaults to None.
"""
style: Style = cls.__new__(Style)
style._ansi = None
style._style_definition = None
style._color = None
style._bgcolor = None
style._set_attributes = 0
style._attributes = 0
style._link = None
style._link_id = ""
style._meta = dumps(meta)
style._hash = hash(
(
None,
None,
None,
None,
None,
style._meta,
)
)
style._null = not (meta)
return style
@classmethod
def on(cls, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Style":
"""Create a blank style with meta information.
Example:
style = Style.on(click=self.on_click)
Args:
meta (Optiona[Dict[str, Any]], optional): An optional dict of meta information.
**handlers (Any): Keyword arguments are translated in to handlers.
Returns:
Style: A Style with meta information attached.
"""
meta = {} if meta is None else meta
meta.update({f"@{key}": value for key, value in handlers.items()})
return cls.from_meta(meta)
bold = _Bit(0)
dim = _Bit(1)
italic = _Bit(2)
@ -352,7 +425,7 @@ class Style:
return value
raise ValueError("expected at least one non-None style")
def __rich_repr__(self) -> RichReprResult:
def __rich_repr__(self) -> Result:
yield "color", self.color, None
yield "bgcolor", self.bgcolor, None
yield "bold", self.bold, None,
@ -414,11 +487,7 @@ class Style:
@property
def meta(self) -> Dict[str, Any]:
"""Get meta information (can not be changed after construction)."""
return (
{}
if self._meta is None
else cast(Dict[str, Any], marshal_loads(self._meta))
)
return {} if self._meta is None else cast(Dict[str, Any], loads(self._meta))
@property
def without_color(self) -> "Style":
@ -433,7 +502,7 @@ class Style:
style._attributes = self._attributes
style._set_attributes = self._set_attributes
style._link = self._link
style._link_id = f"{time()}-{randint(0, 999999)}" if self._link else ""
style._link_id = f"{randint(0, 999999)}" if self._link else ""
style._hash = self._hash
style._null = False
style._meta = None
@ -456,30 +525,7 @@ class Style:
if style_definition.strip() == "none" or not style_definition:
return cls.null()
style_attributes = {
"dim": "dim",
"d": "dim",
"bold": "bold",
"b": "bold",
"italic": "italic",
"i": "italic",
"underline": "underline",
"u": "underline",
"blink": "blink",
"blink2": "blink2",
"reverse": "reverse",
"r": "reverse",
"conceal": "conceal",
"c": "conceal",
"strike": "strike",
"s": "strike",
"underline2": "underline2",
"uu": "underline2",
"frame": "frame",
"encircle": "encircle",
"overline": "overline",
"o": "overline",
}
STYLE_ATTRIBUTES = cls.STYLE_ATTRIBUTES
color: Optional[str] = None
bgcolor: Optional[str] = None
attributes: Dict[str, Optional[Any]] = {}
@ -502,7 +548,7 @@ class Style:
elif word == "not":
word = next(words, "")
attribute = style_attributes.get(word)
attribute = STYLE_ATTRIBUTES.get(word)
if attribute is None:
raise errors.StyleSyntaxError(
f"expected style attribute after 'not', found {word!r}"
@ -515,8 +561,8 @@ class Style:
raise errors.StyleSyntaxError("URL expected after 'link'")
link = word
elif word in style_attributes:
attributes[style_attributes[word]] = True
elif word in STYLE_ATTRIBUTES:
attributes[STYLE_ATTRIBUTES[word]] = True
else:
try:
@ -608,7 +654,7 @@ class Style:
style._attributes = self._attributes
style._set_attributes = self._set_attributes
style._link = self._link
style._link_id = f"{time()}-{randint(0, 999999)}" if self._link else ""
style._link_id = f"{randint(0, 999999)}" if self._link else ""
style._hash = self._hash
style._null = False
style._meta = self._meta
@ -631,7 +677,7 @@ class Style:
style._attributes = self._attributes
style._set_attributes = self._set_attributes
style._link = link
style._link_id = f"{time()}-{randint(0, 999999)}" if link else ""
style._link_id = f"{randint(0, 999999)}" if link else ""
style._hash = self._hash
style._null = False
style._meta = self._meta
@ -696,7 +742,7 @@ class Style:
new_style._hash = style._hash
new_style._null = self._null or style._null
if self._meta and style._meta:
new_style._meta = marshal_dumps({**self.meta, **style.meta})
new_style._meta = dumps({**self.meta, **style.meta})
else:
new_style._meta = self._meta or style._meta
return new_style

View File

@ -278,6 +278,7 @@ class Text(JupyterMixin):
no_wrap: Optional[bool] = None,
end: str = "\n",
tab_size: int = 8,
meta: Optional[Dict[str, Any]] = None,
) -> "Text":
"""Construct a text instance by combining a sequence of strings with optional styles.
The positional arguments should be either strings, or a tuple of string + style.
@ -288,6 +289,7 @@ class Text(JupyterMixin):
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
end (str, optional): Character to end text with. Defaults to "\\\\n".
tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8.
meta (Dict[str, Any], optional). Meta data to apply to text, or None for no meta data. Default to None
Returns:
Text: A new text instance.
@ -307,6 +309,8 @@ class Text(JupyterMixin):
append(part)
else:
append(*part)
if meta:
text.apply_meta(meta)
return text
@property
@ -390,6 +394,40 @@ class Text(JupyterMixin):
return
self._spans.append(Span(start, min(length, end), style))
def apply_meta(
self, meta: Dict[str, Any], start: int = 0, end: Optional[int] = None
) -> None:
"""Apply meta data to the text, or a portion of the text.
Args:
meta (Dict[str, Any]): A dict of meta information.
start (int): Start offset (negative indexing is supported). Defaults to 0.
end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
"""
style = Style.from_meta(meta)
self.stylize(style, start=start, end=end)
def on(self, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Text":
"""Apply event handlers (used by Textual project).
Example:
>>> from rich.text import Text
>>> text = Text("hello world")
>>> text.on(click="view.toggle('world')")
Args:
meta (Dict[str, Any]): Mapping of meta information.
**handlers: Keyword args are prefixed with "@" to defined handlers.
Returns:
Text: Self is returned to method may be chained.
"""
meta = {} if meta is None else meta
meta.update({f"@{key}": value for key, value in handlers.items()})
self.stylize(Style.from_meta(meta))
return self
def remove_suffix(self, suffix: str) -> None:
"""Remove a suffix if it exists.

View File

@ -21,7 +21,7 @@ from .console import (
ConsoleOptions,
ConsoleRenderable,
RenderResult,
render_group,
group,
)
from .constrain import Constrain
from .highlighter import RegexHighlighter, ReprHighlighter
@ -466,7 +466,7 @@ class Traceback:
"\n[i]During handling of the above exception, another exception occurred:\n",
)
@render_group()
@group()
def _render_syntax_error(self, syntax_error: _SyntaxError) -> RenderResult:
highlighter = ReprHighlighter()
path_highlighter = PathHighlighter()
@ -481,7 +481,7 @@ class Traceback:
syntax_error_text = highlighter(syntax_error.line.rstrip())
syntax_error_text.no_wrap = True
offset = min(syntax_error.offset - 1, len(syntax_error_text))
syntax_error_text.stylize("bold underline", offset, offset + 1)
syntax_error_text.stylize("bold underline", offset, offset)
syntax_error_text += Text.from_markup(
"\n" + " " * offset + "[traceback.offset]▲[/]",
style="pygments.text",
@ -504,7 +504,7 @@ class Traceback:
)
return lexer_name
@render_group()
@group()
def _render_stack(self, stack: Stack) -> RenderResult:
path_highlighter = PathHighlighter()
theme = self.theme

View File

@ -188,7 +188,7 @@ class Tree(JupyterMixin):
if __name__ == "__main__": # pragma: no cover
from rich.console import RenderGroup
from rich.console import Group
from rich.markdown import Markdown
from rich.panel import Panel
from rich.syntax import Syntax
@ -226,17 +226,17 @@ class Segment(NamedTuple):
node = root.add(":file_folder: Renderables", guide_style="red")
simple_node = node.add(":file_folder: [bold yellow]Atomic", guide_style="uu green")
simple_node.add(RenderGroup("📄 Syntax", syntax))
simple_node.add(RenderGroup("📄 Markdown", Panel(markdown, border_style="green")))
simple_node.add(Group("📄 Syntax", syntax))
simple_node.add(Group("📄 Markdown", Panel(markdown, border_style="green")))
containers_node = node.add(
":file_folder: [bold magenta]Containers", guide_style="bold magenta"
)
containers_node.expanded = True
panel = Panel.fit("Just a panel", border_style="red")
containers_node.add(RenderGroup("📄 Panels", panel))
containers_node.add(Group("📄 Panels", panel))
containers_node.add(RenderGroup("📄 [b magenta]Table", table))
containers_node.add(Group("📄 [b magenta]Table", table))
console = Console()
console.print(root)

View File

@ -14,7 +14,7 @@ from rich.console import (
Console,
ConsoleDimensions,
ConsoleOptions,
render_group,
group,
ScreenUpdate,
)
from rich.control import Control
@ -467,7 +467,7 @@ def test_out() -> None:
def test_render_group() -> None:
@render_group(fit=False)
@group(fit=False)
def renderable():
yield "one"
yield "two"
@ -481,7 +481,7 @@ def test_render_group() -> None:
def test_render_group_fit() -> None:
@render_group()
@group()
def renderable():
yield "one"
yield "two"

View File

@ -165,7 +165,28 @@ def test_events():
def test_events_broken():
with pytest.raises(MarkupError):
render("[@click=sdfwer]foo[/]")
render("[@click=sdfwer(sfs)]foo[/]")
with pytest.raises(MarkupError):
render("[@click='view.toggle]foo[/]")
def test_render_meta():
console = Console()
text = render("foo[@click=close]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": ("close", ())}
text = render("foo[@click=close()]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": ("close", ())}
text = render("foo[@click=close('dialog')]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {
"@click": ("close", ("dialog",))
}
text = render("foo[@click=close('dialog', 3)]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {
"@click": ("close", ("dialog", 3))
}
text = render("foo[@click=(1, 2, 3)]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": (1, 2, 3)}

View File

@ -219,3 +219,14 @@ def test_meta():
assert style.meta == {"foo": "bar", "egg": "baz"}
assert repr(style) == "Style(bold=True, meta={'foo': 'bar', 'egg': 'baz'})"
def test_from_meta():
style = Style.from_meta({"foo": "bar"})
assert style.color is None
assert style.bold is None
def test_on():
style = Style.on({"foo": "bar"}, click="CLICK") + Style(color="red")
assert style.meta == {"foo": "bar", "@click": "CLICK"}

View File

@ -542,6 +542,14 @@ def test_assemble():
assert text._spans == [Span(3, 6, "bold")]
def test_assemble_meta():
text = Text.assemble("foo", ("bar", "bold"), meta={"foo": "bar"})
assert str(text) == "foobar"
assert text._spans == [Span(3, 6, "bold"), Span(0, 6, Style(meta={"foo": "bar"}))]
console = Console()
assert text.get_style_at_offset(console, 0).meta == {"foo": "bar"}
def test_styled():
text = Text.styled("foo", "bold red")
assert text.style == ""
@ -676,3 +684,24 @@ def test_wrap_invalid_style():
console = Console(width=100, color_system="truecolor")
a = "[#######.................] xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [#######.................]"
console.print(a, justify="full")
def test_apply_meta():
text = Text("foobar")
text.apply_meta({"foo": "bar"}, 1, 3)
console = Console()
assert text.get_style_at_offset(console, 0).meta == {}
assert text.get_style_at_offset(console, 1).meta == {"foo": "bar"}
assert text.get_style_at_offset(console, 2).meta == {"foo": "bar"}
assert text.get_style_at_offset(console, 3).meta == {}
def test_on():
console = Console()
text = Text("foo")
text.on({"foo": "bar"}, click="CLICK")
expected = {"foo": "bar", "@click": "CLICK"}
assert text.get_style_at_offset(console, 0).meta == expected
assert text.get_style_at_offset(console, 1).meta == expected
assert text.get_style_at_offset(console, 2).meta == expected