From 544646834a8bdcb1df5398bf401844dce81c30e3 Mon Sep 17 00:00:00 2001 From: Avrohom Perl Date: Sun, 3 Oct 2021 01:07:01 -0400 Subject: [PATCH 001/287] Remove unused import --- examples/table_movie.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/table_movie.py b/examples/table_movie.py index 515909d9c9..811eb51b70 100644 --- a/examples/table_movie.py +++ b/examples/table_movie.py @@ -6,7 +6,6 @@ from rich.align import Align from rich.console import Console from rich.live import Live -from rich.measure import Measurement from rich.table import Table from rich.text import Text From eed71007157010b4657d15656f5936a3a715ccb0 Mon Sep 17 00:00:00 2001 From: DSK Date: Sun, 3 Oct 2021 12:43:08 +0530 Subject: [PATCH 002/287] added example for calendar layout using columns and tables --- examples/columns2.py | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 examples/columns2.py diff --git a/examples/columns2.py b/examples/columns2.py new file mode 100644 index 0000000000..4e97eeba01 --- /dev/null +++ b/examples/columns2.py @@ -0,0 +1,56 @@ +""" +Builds calendar layout using Columns and Tables. +Usage: +python columns2.py [YEAR] +Example: +python columns2.py 2021 +""" +import argparse + +import calendar +from datetime import datetime + +from rich.table import Table +from rich.columns import Columns +from rich import print + + +def display_calendar(year=None): + + today = datetime.today() + year = int(year or today.year) + cal = calendar.Calendar() + + tables = [] + for month in range(1,13): + + table = Table(title=f"""{calendar.month_name[month]} {year}""", style="green") + + for wd in cal.iterweekdays(): + table.add_column("{:.3}".format(calendar.day_name[wd])) + + month_days = cal.monthdayscalendar(year, month) + for weekdays in month_days: + days = [] + for day in weekdays: + today_tuple = today.day, today.month, today.year + + if day and (day, month, year) == today_tuple : + _day = "[bold underline red]%s[/]" % day + else: + _day = "%s" % ('' if day == 0 else day) + days.append(_day) + table.add_row(*days) + + tables.append(table) + + columns = Columns(tables, equal=True, expand=True) + print(columns) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Rich calendar') + parser.add_argument('year', metavar='year', type=int, default=None) + args = parser.parse_args() + + display_calendar(args.year) From 9b233f49e5b90c90f7c45f4217fee8b8335f880b Mon Sep 17 00:00:00 2001 From: DSK Date: Sun, 3 Oct 2021 12:47:44 +0530 Subject: [PATCH 003/287] black formatting --- examples/columns2.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/columns2.py b/examples/columns2.py index 4e97eeba01..24642c0a81 100644 --- a/examples/columns2.py +++ b/examples/columns2.py @@ -16,13 +16,13 @@ def display_calendar(year=None): - + today = datetime.today() year = int(year or today.year) cal = calendar.Calendar() tables = [] - for month in range(1,13): + for month in range(1, 13): table = Table(title=f"""{calendar.month_name[month]} {year}""", style="green") @@ -34,11 +34,11 @@ def display_calendar(year=None): days = [] for day in weekdays: today_tuple = today.day, today.month, today.year - - if day and (day, month, year) == today_tuple : - _day = "[bold underline red]%s[/]" % day + + if day and (day, month, year) == today_tuple: + _day = "[bold underline red]%s[/]" % day else: - _day = "%s" % ('' if day == 0 else day) + _day = "%s" % ("" if day == 0 else day) days.append(_day) table.add_row(*days) @@ -48,9 +48,9 @@ def display_calendar(year=None): print(columns) -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Rich calendar') - parser.add_argument('year', metavar='year', type=int, default=None) +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Rich calendar") + parser.add_argument("year", metavar="year", type=int, default=None) args = parser.parse_args() display_calendar(args.year) From ca4471426a08c25bf3f0e92f955a2b077036bb06 Mon Sep 17 00:00:00 2001 From: DSK Date: Sun, 3 Oct 2021 12:55:24 +0530 Subject: [PATCH 004/287] cleanup: removed default arg for cli --- examples/columns2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/columns2.py b/examples/columns2.py index 24642c0a81..d04cf9709b 100644 --- a/examples/columns2.py +++ b/examples/columns2.py @@ -15,10 +15,10 @@ from rich import print -def display_calendar(year=None): +def display_calendar(year): today = datetime.today() - year = int(year or today.year) + year = int(year) cal = calendar.Calendar() tables = [] @@ -50,7 +50,7 @@ def display_calendar(year=None): if __name__ == "__main__": parser = argparse.ArgumentParser(description="Rich calendar") - parser.add_argument("year", metavar="year", type=int, default=None) + parser.add_argument("year", metavar="year", type=int) args = parser.parse_args() display_calendar(args.year) From 4dc5e0b71411d1d13d27dfc3c39eb1e716ca33de Mon Sep 17 00:00:00 2001 From: Avrohom Perl Date: Sun, 3 Oct 2021 03:38:26 -0400 Subject: [PATCH 005/287] Fix misspelled month in readme table example --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c3dc1983cc..9b5f9b6c73 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -12,6 +12,7 @@ The following people have contributed to the development of Rich: - [Alexander Mancevice](https://github.com/amancevice) - [Will McGugan](https://github.com/willmcgugan) - [Nathan Page](https://github.com/nathanrpage97) +- [Avi Perl](https://github.com/avi-perl) - [Kylian Point](https://github.com/p0lux) - [Kyle Pollina](https://github.com/kylepollina) - [Clément Robert](https://github.com/neutrinoceros) From aab29c823975252fdb7e5da86c167cfcad01ae2d Mon Sep 17 00:00:00 2001 From: Ilito Torquato Date: Sun, 3 Oct 2021 20:47:28 -0300 Subject: [PATCH 006/287] correct misspelled words, grammatical errors, translates sentences and removes duplications --- README.pt-br.md | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/README.pt-br.md b/README.pt-br.md index 504052efa7..1e0451822b 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -18,19 +18,19 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) -Rich é uma biblioteca Python para _rich_ text e formatação de estilos no termial. +Rich é uma biblioteca Python para _rich_ text e formatação de estilos no terminal. -A [API do Rich](https://rich.readthedocs.io/en/latest/) permite adicionar cores e estilos no output do termial de forma fácil. Rich também permite formataçao de tabelas, barra de progresso, markdown, highlight de sintaxe de código fonte, rastreio de erros (traceback), e muito mais. +A [API do Rich](https://rich.readthedocs.io/en/latest/) permite adicionar cores e estilos no output do terminal de forma fácil. Rich também permite formataçao de tabelas, barra de progresso, markdown, highlight de sintaxe de código fonte, rastreio de erros (traceback) e muito mais. ![Funcões](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) -Para mais detalhes, veja um vídeo de introdução so Rick em [calmcode.io](https://calmcode.io/rich/introduction.html) por [@fishnets88](https://twitter.com/fishnets88). +Para mais detalhes, veja um vídeo de introdução so Rich em [calmcode.io](https://calmcode.io/rich/introduction.html) por [@fishnets88](https://twitter.com/fishnets88). Veja aqui [o que estão falando sobre o Rich](https://www.willmcgugan.com/blog/pages/post/rich-tweets/). ## Compatibilidade -Rich funciona no Linux, OSX e Windows. True color / emoji funciona no novo Terminal do Windows, o terminal classico é limitado a 16 cores. Rich requer Python 3.6.1 or later. +Rich funciona no Linux, OSX e Windows. True color / emoji funciona no novo Terminal do Windows, o terminal classico é limitado a 16 cores. Rich requer Python 3.6.1 ou superior. Rich funciona com [Jupyter notebooks](https://jupyter.org/) sem a necessidade de configurações adicionais. @@ -111,7 +111,7 @@ Voce pode usar o objeto do Console para gerar facilmente uma saída para o termi ## Inspect do Rich -O Rich tem uma função [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) que gera um relatório de qualquer objeto no Python, como classes, instancias ou funções nativas. +O Rich tem uma função [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) que gera um relatório de qualquer objeto no Python, como classes, instâncias ou funções nativas. ```python >>> my_list = ["foo", "bar"] @@ -185,18 +185,18 @@ Para imprimir um emoji no console, coloque o nome do emoji entre dois ":" (dois 😃 🧛 💩 👍 🦝 ``` -Please use this feature wisely. +Por favor use esse recurso com sabedoria.
Tabelas -O Rich pode imprimir [tables](https://rich.readthedocs.io/en/latest/tables.html) flexiveis usando caracteres unicode como bordas. Existem várias opções de formatação de bordas, estilos, alinhamento das celulas etc. +O Rich pode imprimir [tables](https://rich.readthedocs.io/en/latest/tables.html) flexíveis usando caracteres unicode como bordas. Existem várias opções de formatação de bordas, estilos, alinhamento das celulas, etc. ![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) -A animação acima foi gerada com o arquivo [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) da pasta de exeplos. +A animação acima foi gerada com o arquivo [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) da pasta de exemplos. Veja um exemplo mais simple: @@ -236,7 +236,7 @@ Que gera o seguinte resultado: Observe que o markup é renderizado da mesma for que em `print()` e `log()`. De fato, tudo que é renderizável pelo Rich pode ser incluído nos cabeçalhos ou linhas (até mesmo outras tabelas). -A class `Table` é inteligente o suficiente para ajustar o tamanho das colunas para caber na largura do terminal, quebrando o texto em novas linhas como necessário. Veja a seguir o mesmo exemplo, só que desta vez com um terminal menor do que o tamanho original da tabela: +A classe `Table` é inteligente o suficiente para ajustar o tamanho das colunas para caber na largura do terminal, quebrando o texto em novas linhas quando necessário. Veja a seguir o mesmo exemplo, só que desta vez com um terminal menor do que o tamanho original da tabela: ![table2](https://github.com/willmcgugan/rich/raw/master/imgs/table2.png) @@ -256,7 +256,6 @@ for step in track(range(100)): do_step(step) ``` -It's not much harder to add multiple progress bars. Here's an example taken from the docs: Adicionar multiplas barras de progresso também é simples. Veja outro exemplo que existe na documentação: ![progress](https://github.com/willmcgugan/rich/raw/master/imgs/progress.gif) @@ -265,7 +264,7 @@ As colunas podem ser configuradas pra mostrar qualquer detalho necessário. As c ![progress](https://github.com/willmcgugan/rich/raw/master/imgs/downloader.gif) -Para testar isso no seu terminal, use o arquivo [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) para fazer o download de multiplas URLs simultaneamente, exibindo o progress de cada download. +Para testar isso no seu terminal, use o arquivo [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) para fazer o download de multiplas URLs simultaneamente, exibindo o progresso de cada download.
@@ -319,7 +318,6 @@ Isso gera o seguinte resultado: ![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/tree.png) -Veja o exemplo em [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) de um script that displays a tree view of any directory, similar to the linux `tree` command. Veja o exemplo em [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) de um código que gera uma árvore de exibição de um dicionário, semelhante ao comando `tree` do linux. @@ -340,7 +338,6 @@ directory = os.listdir(sys.argv[1]) print(Columns(directory)) ``` -The following screenshot is the output from the [columns example](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) which displays data pulled from an API in columns: O screenshot a seguir é do resultado do [exemplo de colunas](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) formatando em colunas os dados extraidos de uma API: ![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) @@ -444,14 +441,14 @@ Aqui estão alguns projetos que usam o Rich: - [cansarigol/pdbr](https://github.com/cansarigol/pdbr) pdb + Rich para auxiliar no debug - [plant99/felicette](https://github.com/plant99/felicette) - Imagem de satélites para tolos. + Imagem de satélites para iniciantes. - [seleniumbase/SeleniumBase](https://github.com/seleniumbase/SeleniumBase) Automatize & teste 10x mais rápido com Selenium & pytest. Baterias inclusas. - [smacke/ffsubsync](https://github.com/smacke/ffsubsync) Automagicamente sincronize legendas com vídeos. - [tryolabs/norfair](https://github.com/tryolabs/norfair) Biblioteca Python para adicionar rastreio em tempo real de objetos 2D em qualquer detector. -- [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint verifica boas praticas e comportamento que podem ser melhorados. +- [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint verifica boas práticas e comportamento que podem ser melhorados. - [ansible-community/molecule](https://github.com/ansible-community/molecule) Framework de test para Ansible Molecule - +[Muitos outros](https://github.com/willmcgugan/rich/network/dependents)! From 86e67b766de201bb043d3f24917e700820b7a76e Mon Sep 17 00:00:00 2001 From: DSK Date: Mon, 4 Oct 2021 21:02:29 +0530 Subject: [PATCH 007/287] cleanup based on review comments --- examples/{columns2.py => calendar_layout.py} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename examples/{columns2.py => calendar_layout.py} (74%) diff --git a/examples/columns2.py b/examples/calendar_layout.py similarity index 74% rename from examples/columns2.py rename to examples/calendar_layout.py index d04cf9709b..507351d7ef 100644 --- a/examples/columns2.py +++ b/examples/calendar_layout.py @@ -1,9 +1,9 @@ """ Builds calendar layout using Columns and Tables. Usage: -python columns2.py [YEAR] +python calendar.py [YEAR] Example: -python columns2.py 2021 +python calendar.py 2021 """ import argparse @@ -24,10 +24,10 @@ def display_calendar(year): tables = [] for month in range(1, 13): - table = Table(title=f"""{calendar.month_name[month]} {year}""", style="green") + table = Table(title=f"{calendar.month_name[month]} {year}", style="green") - for wd in cal.iterweekdays(): - table.add_column("{:.3}".format(calendar.day_name[wd])) + for week_day in cal.iterweekdays(): + table.add_column("{:.3}".format(calendar.day_name[week_day])) month_days = cal.monthdayscalendar(year, month) for weekdays in month_days: @@ -36,9 +36,9 @@ def display_calendar(year): today_tuple = today.day, today.month, today.year if day and (day, month, year) == today_tuple: - _day = "[bold underline red]%s[/]" % day + _day = f"[bold underline red]{day}" else: - _day = "%s" % ("" if day == 0 else day) + _day = "" if day == 0 else str(day) days.append(_day) table.add_row(*days) From c0deb0bcddfb125bb70a8cbc6c5c2c6ec729d5ff Mon Sep 17 00:00:00 2001 From: DSK Date: Mon, 4 Oct 2021 21:06:46 +0530 Subject: [PATCH 008/287] fix run command comment --- examples/calendar_layout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/calendar_layout.py b/examples/calendar_layout.py index 507351d7ef..5b27b60cd3 100644 --- a/examples/calendar_layout.py +++ b/examples/calendar_layout.py @@ -1,9 +1,9 @@ """ Builds calendar layout using Columns and Tables. Usage: -python calendar.py [YEAR] +python calendar_layout.py [YEAR] Example: -python calendar.py 2021 +python calendar_layout.py 2021 """ import argparse From ca8a509d08c6e25b2a5ab029d0b2783673cef7f0 Mon Sep 17 00:00:00 2001 From: 0xflotus <0xflotus@gmail.com> Date: Tue, 5 Oct 2021 23:56:54 +0200 Subject: [PATCH 009/287] fix: small error in docs --- docs/source/console.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index c5de7b5e38..6ea6e09266 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -384,7 +384,7 @@ Interactive mode Rich will remove animations such as progress bars and status indicators when not writing to a terminal as you probably don't want to write these out to a text file (for example). You can override this behavior by setting the ``force_interactive`` argument on the constructor. Set it to True to enable animations or False to disable them. .. note:: - Some CI systems support ANSI color and style but not anything that moves the cursor or selectively refreshes parts of the terminal. For these you might want to set ``force_terminal`` to ``True`` and ``force_interactve`` to ``False``. + Some CI systems support ANSI color and style but not anything that moves the cursor or selectively refreshes parts of the terminal. For these you might want to set ``force_terminal`` to ``True`` and ``force_interactive`` to ``False``. Environment variables --------------------- From 8375ccf2895ea6d626e9f611899f32bfc0ed76b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Wed, 6 Oct 2021 10:35:47 +0545 Subject: [PATCH 010/287] json: add support for default encoder --- rich/json.py | 23 ++++++++++++++++------- tests/test_json.py | 8 ++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 tests/test_json.py diff --git a/rich/json.py b/rich/json.py index 6266c92ab1..a63f1754d3 100644 --- a/rich/json.py +++ b/rich/json.py @@ -1,5 +1,5 @@ from json import loads, dumps -from typing import Any +from typing import Any, Callable, Optional from .text import Text from .highlighter import JSONHighlighter, NullHighlighter @@ -23,17 +23,26 @@ def __init__(self, json: str, indent: int = 2, highlight: bool = True) -> None: self.text.overflow = None @classmethod - def from_data(cls, data: Any, indent: int = 2, highlight: bool = True) -> "JSON": + def from_data( + cls, + data: Any, + indent: int = 2, + highlight: bool = True, + default: Optional[Callable[[Any], Any]] = None, + ) -> "JSON": """Encodes a JSON object from arbitrary data. + Args: + data (Any): An object that may be encoded in to JSON + indent (int, optional): Number of characters to indent by. Defaults to 2. + highlight (bool, optional): Enable highlighting. Defaults to True. + default (Callable, optional): Optional callable which will be called for objects that cannot be serialized. Defaults to None. + Returns: - Args: - data (Any): An object that may be encoded in to JSON - indent (int, optional): Number of characters to indent by. Defaults to 2. - highlight (bool, optional): Enable highlighting. Defaults to True. + JSON: New JSON object from the given data. """ json_instance: "JSON" = cls.__new__(cls) - json = dumps(data, indent=indent) + json = dumps(data, indent=indent, default=default) highlighter = JSONHighlighter() if highlight else NullHighlighter() json_instance.text = highlighter(json) json_instance.text.no_wrap = True diff --git a/tests/test_json.py b/tests/test_json.py new file mode 100644 index 0000000000..7571b0a393 --- /dev/null +++ b/tests/test_json.py @@ -0,0 +1,8 @@ +from rich.json import JSON +import datetime + + +def test_print_json_data_with_default(): + date = datetime.date(2021, 1, 1) + json = JSON.from_data({"date": date}, default=lambda d: d.isoformat()) + assert str(json.text) == '{\n "date": "2021-01-01"\n}' From 3f192d3f58181653673891bb085be07ab6b1d94a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Oct 2021 13:07:02 +0000 Subject: [PATCH 011/287] Bump pytest-cov from 2.12.1 to 3.0.0 Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.12.1 to 3.0.0. - [Release notes](https://github.com/pytest-dev/pytest-cov/releases) - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.12.1...v3.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- poetry.lock | 36 +++++++++++++++++++++++++++++------- pyproject.toml | 2 +- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9bd5f60d42..3374de9de0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -152,6 +152,9 @@ category = "dev" optional = false python-versions = ">=3.6" +[package.dependencies] +tomli = {version = "*", optional = true, markers = "extra == \"toml\""} + [package.extras] toml = ["tomli"] @@ -713,16 +716,15 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm [[package]] name = "pytest-cov" -version = "2.12.1" +version = "3.0.0" description = "Pytest plugin for measuring coverage." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" [package.dependencies] -coverage = ">=5.2.1" +coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" -toml = "*" [package.extras] testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] @@ -931,7 +933,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "97432dbcf77dd3aaa24f0cd35a7e70df03b64fe3b0397618bcb566507dcc40c3" +content-hash = "0215d2db0f3d908a013cd733e8019891e208c9b6b733a05658d49e96a8be3108" [metadata.files] appnope = [ @@ -1140,12 +1142,22 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1154,14 +1166,21 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1171,6 +1190,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1316,8 +1338,8 @@ pytest = [ {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, ] pytest-cov = [ - {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"}, - {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"}, + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, ] python-dateutil = [ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, diff --git a/pyproject.toml b/pyproject.toml index a0b8600c8b..6d1d265b13 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ jupyter = ["ipywidgets"] pytest = "^6.2.5" black = "^21.9b0" mypy = "^0.910" -pytest-cov = "^2.12.1" +pytest-cov = "^3.0.0" attrs = "^21.2.0" types-dataclasses = "^0.1.7" From 18bedc67df7323954e149bba5e70b2d55b6ff7af Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 6 Oct 2021 14:09:37 +0100 Subject: [PATCH 012/287] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e45601a35..8ed2419bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Official Py3.10 release +### Fixed + +- Fixed detection of custom repr when pretty printing dataclasses + ## [10.11.0] - 2021-09-24 ### Added From 510cec7116dcd64ae6f3da2ae72cada7f36c9e78 Mon Sep 17 00:00:00 2001 From: Troy Williams Date: Sat, 9 Oct 2021 09:37:08 -0400 Subject: [PATCH 013/287] Added section `Automatic Traceback Handler` to traceback.rst. It describes a method to automatically install the rich.traceback without having to include the code in your modules. --- docs/source/traceback.rst | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/source/traceback.rst b/docs/source/traceback.rst index 6b1a6f9cec..120ca0ceb4 100644 --- a/docs/source/traceback.rst +++ b/docs/source/traceback.rst @@ -26,7 +26,7 @@ The ``show_locals=True`` parameter causes Rich to display the value of local var See `exception.py `_ for a larger example. -Traceback handler +Traceback Handler ----------------- Rich can be installed as the default traceback handler so that all uncaught exceptions will be rendered with highlighting. Here's how:: @@ -36,6 +36,27 @@ Rich can be installed as the default traceback handler so that all uncaught exce There are a few options to configure the traceback handler, see :func:`~rich.traceback.install` for details. +Automatic Traceback Handler +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some cases you may want to have the traceback handler installed automatically without having to worry about importing the code in your module. You can do that by modifying the `sitecustomize.py` in your virtual environment. Typically it would be located in your virtual environment path, underneath the `site-packages` folder, something like this:: + + ./.venv/lib/python3.9/site-packages/sitecustomize.py + +In most cases this file will not exist. If it doesn't exist, you can create it by:: + + $ touch .venv/lib/python3.9/site-packages/sitecustomize.py + +Add the following code to the file:: + + from rich.traceback import install + install(show_locals=True) + +At this point, the traceback will be installed for any code that is run within the virtual environment. + +.. note:: + If you plan on sharing your code, it is probably best to include the traceback install in your main entry point module. + Suppressing Frames ------------------ @@ -73,4 +94,5 @@ Here's an example of printing an recursive error:: try: foo(1) except Exception: - console.print_exception(max_frames=20) \ No newline at end of file + console.print_exception(max_frames=20) + From ef53f4771bdc11af7a8f7ca15bcf538f8cccca07 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 10 Oct 2021 17:37:26 +0100 Subject: [PATCH 014/287] tweaked calendar example --- examples/calendar_layout.py | 56 ----------------------------- examples/print_calendar.py | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 56 deletions(-) delete mode 100644 examples/calendar_layout.py create mode 100644 examples/print_calendar.py diff --git a/examples/calendar_layout.py b/examples/calendar_layout.py deleted file mode 100644 index 5b27b60cd3..0000000000 --- a/examples/calendar_layout.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Builds calendar layout using Columns and Tables. -Usage: -python calendar_layout.py [YEAR] -Example: -python calendar_layout.py 2021 -""" -import argparse - -import calendar -from datetime import datetime - -from rich.table import Table -from rich.columns import Columns -from rich import print - - -def display_calendar(year): - - today = datetime.today() - year = int(year) - cal = calendar.Calendar() - - tables = [] - for month in range(1, 13): - - table = Table(title=f"{calendar.month_name[month]} {year}", style="green") - - for week_day in cal.iterweekdays(): - table.add_column("{:.3}".format(calendar.day_name[week_day])) - - month_days = cal.monthdayscalendar(year, month) - for weekdays in month_days: - days = [] - for day in weekdays: - today_tuple = today.day, today.month, today.year - - if day and (day, month, year) == today_tuple: - _day = f"[bold underline red]{day}" - else: - _day = "" if day == 0 else str(day) - days.append(_day) - table.add_row(*days) - - tables.append(table) - - columns = Columns(tables, equal=True, expand=True) - print(columns) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Rich calendar") - parser.add_argument("year", metavar="year", type=int) - args = parser.parse_args() - - display_calendar(args.year) diff --git a/examples/print_calendar.py b/examples/print_calendar.py new file mode 100644 index 0000000000..d9586aaa8a --- /dev/null +++ b/examples/print_calendar.py @@ -0,0 +1,70 @@ +""" +Builds calendar layout using Columns and Tables. +Usage: +python print_calendar.py [YEAR] +Example: +python print_calendar.py 2021 +""" +import argparse +import calendar +from datetime import datetime + +from rich.align import Align +from rich import box +from rich.columns import Columns +from rich.console import Console +from rich.table import Table +from rich.text import Text + + +def print_calendar(year): + """Print a calendar for a given year.""" + + today = datetime.today() + year = int(year) + cal = calendar.Calendar() + today_tuple = today.day, today.month, today.year + + tables = [] + + for month in range(1, 13): + table = Table( + title=f"{calendar.month_name[month]} {year}", + style="green", + box=box.SIMPLE_HEAVY, + padding=0, + ) + + for week_day in cal.iterweekdays(): + table.add_column( + "{:.3}".format(calendar.day_name[week_day]), justify="right" + ) + + month_days = cal.monthdayscalendar(year, month) + for weekdays in month_days: + days = [] + for index, day in enumerate(weekdays): + day_label = Text(str(day or ""), style="magenta") + if index in (5, 6): + day_label.stylize("blue") + if day and (day, month, year) == today_tuple: + day_label.stylize("white on dark_red") + days.append(day_label) + table.add_row(*days) + + tables.append(Align.center(table)) + + console = Console() + columns = Columns(tables, padding=1, expand=True) + console.rule(str(year)) + console.print() + console.print(columns) + console.rule(str(year)) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Rich calendar") + parser.add_argument("year", metavar="year", type=int) + args = parser.parse_args() + + print_calendar(args.year) From 7de08939641cae7444eb03d7e69bae01d21923ab Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Tue, 12 Oct 2021 18:16:51 +0200 Subject: [PATCH 015/287] feat(tree): add hide_root argument --- rich/tree.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/rich/tree.py b/rich/tree.py index 5fd46fd46b..bf3dda28cf 100644 --- a/rich/tree.py +++ b/rich/tree.py @@ -28,6 +28,7 @@ def __init__( guide_style: StyleType = "tree.line", expanded: bool = True, highlight: bool = False, + hide_root: bool = False, ) -> None: self.label = label self.style = style @@ -35,6 +36,7 @@ def __init__( self.children: List[Tree] = [] self.expanded = expanded self.highlight = highlight + self.hide_root = hide_root def add( self, @@ -105,6 +107,8 @@ def make_guide(index: int, style: Style) -> Segment: style_stack = StyleStack(get_style(self.style)) remove_guide_styles = Style(bold=False, underline2=False) + depth = 0 + while stack: stack_node = pop() try: @@ -123,7 +127,7 @@ def make_guide(index: int, style: Style) -> Segment: guide_style = guide_style_stack.current + get_style(node.guide_style) style = style_stack.current + get_style(node.style) - prefix = levels[1:] + prefix = levels[(1 if self.hide_root == False else 2) :] renderable_lines = console.render_lines( Styled(node.label, style), options.update( @@ -133,19 +137,21 @@ def make_guide(index: int, style: Style) -> Segment: height=None, ), ) - for first, line in loop_first(renderable_lines): - if prefix: - yield from _Segment.apply_style( - prefix, - style.background_style, - post_style=remove_guide_styles, - ) - yield from line - yield new_line - if first and prefix: - prefix[-1] = make_guide( - SPACE if last else CONTINUE, prefix[-1].style or null_style - ) + + if not (depth == 0 and self.hide_root == True): + for first, line in loop_first(renderable_lines): + if prefix: + yield from _Segment.apply_style( + prefix, + style.background_style, + post_style=remove_guide_styles, + ) + yield from line + yield new_line + if first and prefix: + prefix[-1] = make_guide( + SPACE if last else CONTINUE, prefix[-1].style or null_style + ) if node.expanded and node.children: levels[-1] = make_guide( @@ -157,6 +163,7 @@ def make_guide(index: int, style: Style) -> Segment: style_stack.push(get_style(node.style)) guide_style_stack.push(get_style(node.guide_style)) push(iter(loop_last(node.children))) + depth += 1 def __rich_measure__( self, console: "Console", options: "ConsoleOptions" @@ -222,7 +229,7 @@ class Segment(NamedTuple): """ ) - root = Tree("🌲 [b green]Rich Tree", highlight=True) + root = Tree("🌲 [b green]Rich Tree", highlight=True, hide_root=True) node = root.add(":file_folder: Renderables", guide_style="red") simple_node = node.add(":file_folder: [bold yellow]Atomic", guide_style="uu green") From 7c96a8f9d792883e9bf3b2f0b748508eb4558766 Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Tue, 12 Oct 2021 18:27:20 +0200 Subject: [PATCH 016/287] docs: add README.it.md --- README.cn.md | 1 + README.de-ch.md | 1 + README.de.md | 1 + README.es.md | 1 + README.fr.md | 1 + README.hi.md | 1 + README.it.md | 455 ++++++++++++++++++++++++++++++++++++++++++++++++ README.ja.md | 1 + README.kr.md | 1 + 9 files changed, 463 insertions(+) create mode 100644 README.it.md diff --git a/README.cn.md b/README.cn.md index 433b3069ff..070c9fd319 100644 --- a/README.cn.md +++ b/README.cn.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich 是一个 Python 库,可以为您在终端中提供富文本和精美格式。 diff --git a/README.de-ch.md b/README.de-ch.md index 5c92cab937..0cd9ff6a19 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich isch ä Python Library för _rich_ Text ond ganz schöni formatiärig im Törminäl diff --git a/README.de.md b/README.de.md index c7ed937cf6..a0f90034e9 100644 --- a/README.de.md +++ b/README.de.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich ist eine Python-Bibliothek für _rich_ Text und schöne Formatierung im Terminal. diff --git a/README.es.md b/README.es.md index 9588336e3b..9021f94620 100644 --- a/README.es.md +++ b/README.es.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich es un paquete de Python para texto _enriquecido_ y un hermoso formato en la terminal. diff --git a/README.fr.md b/README.fr.md index 73abe604e0..ee4566f738 100644 --- a/README.fr.md +++ b/README.fr.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich est une bibliothèque Python pour le _rich_ texte et la mise en forme dans le terminal. diff --git a/README.hi.md b/README.hi.md index 420edd8fcb..569a549e81 100644 --- a/README.hi.md +++ b/README.hi.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich टर्मिनल में _समृद्ध_ पाठ और सुंदर स्वरूपण के लिए एक Python संग्रह है। diff --git a/README.it.md b/README.it.md new file mode 100644 index 0000000000..a2434201b8 --- /dev/null +++ b/README.it.md @@ -0,0 +1,455 @@ +[![Downloads](https://pepy.tech/badge/rich/month)](https://pepy.tech/project/rich) +[![codecov](https://codecov.io/gh/willmcgugan/rich/branch/master/graph/badge.svg)](https://codecov.io/gh/willmcgugan/rich) +[![Rich blog](https://img.shields.io/badge/blog-rich%20news-yellowgreen)](https://www.willmcgugan.com/tag/rich/) +[![Twitter Follow](https://img.shields.io/twitter/follow/willmcgugan.svg?style=social)](https://twitter.com/willmcgugan) + +![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) + +[English readme](https://github.com/willmcgugan/rich/blob/master/README.md) + • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) + • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) + • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) + • [日本語 readme](https://github.com/willmcgugan/rich/blob/master/README.ja.md) + • [한국어 readme](https://github.com/willmcgugan/rich/blob/master/README.kr.md) + • [Français readme](https://github.com/willmcgugan/rich/blob/master/README.fr.md) + • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) + • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) + • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + + +Rich è una libreria Python per un testo _rich_ e con una piacevole formattazione nel terminale. + +Le [Rich API](https://rich.readthedocs.io/en/latest/) permettono di aggiungere facilmente colore e stile all'output del terminale. Rich permette di visualizzare tabelle, barre di avanzamento, markdown, evidenziazione della sintassi, tracebacks, e molto altro ancora — tutto già pronto all'uso. + +![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) + +Per una video-introduzione di Rich puoi vedere [calmcode.io](https://calmcode.io/rich/introduction.html) by [@fishnets88](https://twitter.com/fishnets88). + +Guarda cosa [le persone dicono su Rich](https://www.willmcgugan.com/blog/pages/post/rich-tweets/). + +## Compatibilità + +Rich funziona su Linux, OSX, e Windows. True color / emoji funzionano con il nuovo Windows Terminal, il terminale classico è limitato a 16 colori. Rich richiede Python 3.6.1 o superiore. + +Rich funziona con i [Jupyter notebooks](https://jupyter.org/) senza configurazioni aggiuntive. + +## Installazione + +Installa con `pip` o il tuo PyPi package manager preferito. + +```shell +pip install rich +``` + +Esegui il seguente comando per testare l'output di Rich sul tuo terminale: + +```shell +python -m rich +``` + +## Rich Print + +Utilizzare rich è semplicissimo, ti basta importare il metodo [rich print](https://rich.readthedocs.io/en/latest/introduction.html#quick-start), che ha la stessa signature della funzione builtin in Python. Prova: + +```python +from rich import print + +print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals()) +``` + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/print.png) + +## Rich REPL + +Rich può essere installo in Python REPL, in questo modo ogni struttura dati sarà visualizzata in modo gradevole ed evidenziato. + +```python +>>> from rich import pretty +>>> pretty.install() +``` + +![REPL](https://github.com/willmcgugan/rich/raw/master/imgs/repl.png) + +## Utilizzo di Console + +Per un maggiore personalizzazione dei contenuti puoi importare ed instanziare un oggetto [Console](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console). + +```python +from rich.console import Console + +console = Console() +``` + +L'oggetto Console ha il metodo `print` che utilizza volutamente un interfaccia simile a quella del `print` originale. Ad esempio: + +```python +console.print("Hello", "World!") +``` + +Come puoi immaginare, questo stamperà `"Hello World!"` sul terminale. Nota che diversamente dalla funzione builtin `print`, Rich potrebbe portare a capo il testo per rispettare le dimensioni del terminale. + +Ci sono diversi modi di aggiungere stile e colore al tuo output. Puoi impostare uno stile per l'intero output utilizzando l'argomento keyword `style`. Ad esempio: + +```python +console.print("Hello", "World!", style="bold red") +``` + +L'output sarà qualcosa tipo: + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/hello_world.png) + +Questo va bene per applicare uno stile ad una linea di testo alla volta. Per uno stile più ricercato, puoi utilizzare uno speciale linguaggio di markup che è simile nella sintassi a [bbcode](https://en.wikipedia.org/wiki/BBCode). Ad esempio: + +```python +console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a [i]way[/i].") +``` + +![Console Markup](https://github.com/willmcgugan/rich/raw/master/imgs/where_there_is_a_will.png) + +Puoi utilizzare l'oggetto Console per generare output sofisticati con il minimo sforzo. Vedi la docs di [Console API](https://rich.readthedocs.io/en/latest/console.html) per ulteriori dettagli. + +## Rich Inspect + +Rich ha una funzione [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) che può produrre un report per un qualsiasi oggetto Python, come una classe, un instanza, o un builtin. + +```python +>>> my_list = ["foo", "bar"] +>>> from rich import inspect +>>> inspect(my_list, methods=True) +``` + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/inspect.png) + +Vedi [inspect docs](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) per ulteriori dettagli. + +# Rich Library + +Rich contiene alcuni builtin _renderables_ che puoi utilizzare per creare eleganti output nella tua CLI e aiutarti nel debug del tuo codice. + +Fai click sulle seguenti intestazioni per ulteriori dettagli: + +
+Log + +L'oggetto Console ha un metodo `log()` che utilizza un'interfaccia simile a `print()`, ma visualizza anche una colonna con l'ora corrente, il file e la linea che hanno generato la chiamata. Di default Rich evidenzierà le strutture Python e le stringhe repr. Se logghi un oggetto di tipo collection (e.s. un dict o una lista) Rich automaticamente abbellirà l'output in modo che possa entrare nello spazio disponibile. Ecco qui un esempio di alcune delle feature discusse: + +```python +from rich.console import Console +console = Console() + +test_data = [ + {"jsonrpc": "2.0", "method": "sum", "params": [None, 1, 2, 4, False, True], "id": "1",}, + {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}, + {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"}, +] + +def test_log(): + enabled = False + context = { + "foo": "bar", + } + movies = ["Deadpool", "Rise of the Skywalker"] + console.log("Hello from", console, "!") + console.log(test_data, log_locals=True) + + +test_log() +``` + +Il codice appena mostrato produce il seguente output: + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/log.png) + +Nota l'argomento `log_locals`, che visualizza una tabella contenente le variabili locali dove il metodo log è stato chiamato. + +Il metodo log può essere usato per il logging su terminale di applicazioni che solitamente girano su server, ma ha anche uno scopo orientato al debugging. + +
+
+Logging Handler + +Puoi anche utilizzare la classe builtin [Handler](https://rich.readthedocs.io/en/latest/logging.html) per formattare e colorare l'output dal modulo logging di Python. Ecco un esempio dell'output: + +![Logging](https://github.com/willmcgugan/rich/raw/master/imgs/logging.png) + +
+ +
+Emoji + +Per inserire un emoji nell'output della console inseriscine il nome in mezzo a due ':'. Ad esempio: + +```python +>>> console.print(":smiley: :vampire: :pile_of_poo: :thumbs_up: :raccoon:") +😃 🧛 💩 👍 🦝 +``` + +Usa questa feature saggiamente. + +
+ +
+Tables + +Rich può visualizzare [tabelle](https://rich.readthedocs.io/en/latest/tables.html) flessibili con caratteri unicode. C'è una vasta gamma di opzioni per la formattazione di bordi, stili, allineamenti di celle etc. + +![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) + +Questa animazione è stata realizzata con [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) presente nella directory examples. + +Ecco qui un semplice esempio di tabella: + +```python +from rich.console import Console +from rich.table import Table + +console = Console() + +table = Table(show_header=True, header_style="bold magenta") +table.add_column("Date", style="dim", width=12) +table.add_column("Title") +table.add_column("Production Budget", justify="right") +table.add_column("Box Office", justify="right") +table.add_row( + "Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118" +) +table.add_row( + "May 25, 2018", + "[red]Solo[/red]: A Star Wars Story", + "$275,000,000", + "$393,151,347", +) +table.add_row( + "Dec 15, 2017", + "Star Wars Ep. VIII: The Last Jedi", + "$262,000,000", + "[bold]$1,332,539,889[/bold]", +) + +console.print(table) +``` + +Questo produce il seguente output: + +![table](https://github.com/willmcgugan/rich/raw/master/imgs/table.png) + +Nota che il console markup è visualizzato nello stesso modo di `print()` e `log()`. Infatti, tutto ciò che è visualizzabile da Rich può essere incluso nelle intestazioni / righe (anche altre tabelle). + +La classe `Table` è abbastanza smart da ridimensionare le colonne per entrare nello spazio residuo del terminale, wrappando il testo come richiesto. Ad esempio, con il terminale reso più piccolo della tabella sopra: + +![table2](https://github.com/willmcgugan/rich/raw/master/imgs/table2.png) + +
+ +
+Barre di avanzamento + +Rich può visualizzare, senza sfarfallio, multiple barre [di avanzamento](https://rich.readthedocs.io/en/latest/progress.html) per tenere traccia di task di lunga durata. + +Per un utilizzo base, wrappa ogni 'step' con la funzione `track` e itera sul risultato. Ad esempio: + +```python +from rich.progress import track + +for step in track(range(100)): + do_step(step) +``` + +Non è difficile aggiungere barre di avanzamento multiple. Ecco un esempio dalla documentazione: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/progress.gif) + +Le colonne possono essere configurate per visualizzare qualsiasi dettaglio tu voglia. Le colonne built-in includono percentuale di completamente, dimensione del file, velocità, e tempo rimasto. Ecco un altro esempio che mostra un download in corso: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/downloader.gif) + +Per testare tu stesso, vedi [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) che può scaricare multipli URL simultaneamente mentre mostra lo stato di avanzamento. + +
+ +
+Status + +Per situazioni in cui è difficile calcolare l'avanzamento, puoi utilizzare il metodo [status](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console.status) che mostrerà un animazione 'spinner' e un messaggio. L'animazione non ti impedisce di utilizzare la console normalmente. Ad esempio: + +```python +from time import sleep +from rich.console import Console + +console = Console() +tasks = [f"task {n}" for n in range(1, 11)] + +with console.status("[bold green]Working on tasks...") as status: + while tasks: + task = tasks.pop(0) + sleep(1) + console.log(f"{task} complete") +``` + +Questo produrrà il seguente output nel terminale. + +![status](https://github.com/willmcgugan/rich/raw/master/imgs/status.gif) + +L'animazione dello spinner è ispirata da [cli-spinners](https://www.npmjs.com/package/cli-spinners). Puoi selezionarne uno specificando `spinner` tra i parametri. Esegui il seguente comando per visualizzare le possibili opzioni: + +```shell +python -m rich.spinner +``` + +Questo produrrà il seguente output nel terminale. + +![spinners](https://github.com/willmcgugan/rich/raw/master/imgs/spinners.gif) + +
+ +
+Albero + +Rich può visualizzare un [albero](https://rich.readthedocs.io/en/latest/tree.html) con linee guida. Un albero è ideale per mostrare la struttura di un file, o altri dati gerarchici. + +Le etichette dell'albero possono essere semplice testo o qualsiasi altra cosa che Rich può visualizzare. Esegui il seguente comando per una dimostrazione: + +```shell +python -m rich.tree +``` + +Questo produrrà il seguente output: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/tree.png) + +Vedi l'esempio [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) per uno script che mostra una vista ad albero di ogni directory, simile a quella del comando linux `tree`. + +
+ +
+Colonne + +Rich può visualizzare contenuti in [colonne](https://rich.readthedocs.io/en/latest/columns.html) ordinate con larghezza uguale o ottimale. Ecco qui un clone base del comando (MacOS / Linux) `ls` che mostra il contenuto di una directory in colonna: + +```python +import os +import sys + +from rich import print +from rich.columns import Columns + +directory = os.listdir(sys.argv[1]) +print(Columns(directory)) +``` + +Il seguente screenshot è l'output dell'[esempio di columns](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) che visualizza i dati ottenuti da un API in colonna: + +![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) + +
+ +
+Markdown + +Rich può visualizzare [markdown](https://rich.readthedocs.io/en/latest/markdown.html) e tradurlo in modo da visualizzarlo su terminale. + +Per visualizzare markdown importa la classe `Markdown` e instanziala con una stringa contenente codice markdown. Dopo stampala sulla console. Ad esempio: + +```python +from rich.console import Console +from rich.markdown import Markdown + +console = Console() +with open("README.md") as readme: + markdown = Markdown(readme.read()) +console.print(markdown) +``` + +Questo produrrà un output simile al seguente: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/markdown.png) + +
+ +
+Evidenziazione della sintassi + +Rich utilizza la libreria [pygments](https://pygments.org/) per implementare il [syntax highlighting](https://rich.readthedocs.io/en/latest/syntax.html). L'utilizzo è simile a quello per visualizzare markdown; instanzia un oggetto `Syntax` e stampalo sulla console. Ad esempio: + +```python +from rich.console import Console +from rich.syntax import Syntax + +my_code = ''' +def iter_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: + """Itera e genera una tupla con un flag per il primo e ultimo valore.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + first = True + for value in iter_values: + yield first, False, previous_value + first = False + previous_value = value + yield first, True, previous_value +''' +syntax = Syntax(my_code, "python", theme="monokai", line_numbers=True) +console = Console() +console.print(syntax) +``` + +Questo produrrà il seguente output: + +![syntax](https://github.com/willmcgugan/rich/raw/master/imgs/syntax.png) + +
+ +
+Tracebacks + +Rich può visualizzare [gradevoli tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) che sono più semplici da leggere e che mostrano più codice rispetto ai Python tracebacks. Puoi impostare Rich come il traceback handler di default, in questo modo tutte le eccezioni non gestiti saranno visualizzate da Rich. + +Ecco come appare su OSX (simile a Linux): + +![traceback](https://github.com/willmcgugan/rich/raw/master/imgs/traceback.png) + +
+ +Tutti i Rich renderables utilizzano [Console Protocol](https://rich.readthedocs.io/en/latest/protocol.html), che puoi utilizzare per implementare nuovi contenuti su Rich. + +# Rich per le aziende + +Disponibile come parte dell'iscrizione a Tidelift. + +Lo sviluppatore di Rich e migliaia di altri packages lavorano con Tidelift per garantire supporto commerciale e mantenimento per i pacchetti open source che utilizzi per costruire le tue applicazioni. Risparmia tempo, riduci i rischi, e migliora la vita del codice, pagando i mantenitori dello stesso package che utilizzi. [Ulteriori informazioni.](https://tidelift.com/subscription/pkg/pypi-rich?utm_source=pypi-rich&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +# Progetti che usano Rich + +Ecco alcuni progetti che utilizzano Rich: + +- [BrancoLab/BrainRender](https://github.com/BrancoLab/BrainRender) + a python package for the visualization of three dimensional neuro-anatomical data +- [Ciphey/Ciphey](https://github.com/Ciphey/Ciphey) + Automated decryption tool +- [emeryberger/scalene](https://github.com/emeryberger/scalene) + a high-performance, high-precision CPU and memory profiler for Python +- [hedythedev/StarCli](https://github.com/hedythedev/starcli) + Browse GitHub trending projects from your command line +- [intel/cve-bin-tool](https://github.com/intel/cve-bin-tool) + This tool scans for a number of common, vulnerable components (openssl, libpng, libxml2, expat and a few others) to let you know if your system includes common libraries with known vulnerabilities. +- [nf-core/tools](https://github.com/nf-core/tools) + Python package with helper tools for the nf-core community. +- [cansarigol/pdbr](https://github.com/cansarigol/pdbr) + pdb + Rich library for enhanced debugging +- [plant99/felicette](https://github.com/plant99/felicette) + Satellite imagery for dummies. +- [seleniumbase/SeleniumBase](https://github.com/seleniumbase/SeleniumBase) + Automate & test 10x faster with Selenium & pytest. Batteries included. +- [smacke/ffsubsync](https://github.com/smacke/ffsubsync) + Automagically synchronize subtitles with video. +- [tryolabs/norfair](https://github.com/tryolabs/norfair) + Lightweight Python library for adding real-time 2D object tracking to any detector. +- [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint checks playbooks for practices and behaviour that could potentially be improved +- [ansible-community/molecule](https://github.com/ansible-community/molecule) Ansible Molecule testing framework +- +[Many more](https://github.com/willmcgugan/rich/network/dependents)! + + diff --git a/README.ja.md b/README.ja.md index 56793fedbb..b1a047a502 100644 --- a/README.ja.md +++ b/README.ja.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Richは、_リッチ_なテキストや美しい書式設定をターミナルで行うためのPythonライブラリです。 diff --git a/README.kr.md b/README.kr.md index e1939becd1..2b09c9f076 100644 --- a/README.kr.md +++ b/README.kr.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich는 터미널에서 _풍부한(rich)_ 텍스트와 아름다운 서식을 지원하기 위한 파이썬 라이브러리입니다. From 76a7b89cd8c935dec87ac89ec36b174c9a0636c4 Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Tue, 12 Oct 2021 16:11:24 -0700 Subject: [PATCH 017/287] change lambda with broken typing to def This function is annotated with a Callable[] syntax that works only because of a bug with attribute methods in the current mypy. In a future release of mypy this is fixed and this will start throwing an error. If a lambda is needed the only way to type it correctly would be defining a protocol and using __call__, but I've opted to replace the lambda with a def instead since it's much simpler. --- rich/pager.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rich/pager.py b/rich/pager.py index 4290021f21..ea9bdf08fa 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -17,9 +17,8 @@ def show(self, content: str) -> None: class SystemPager(Pager): """Uses the pager installed on the system.""" - _pager: Callable[[Any, str], Any] = lambda self, content: __import__("pydoc").pager( - content - ) + def _pager(self, content: str) -> Any: + return __import__("pydoc").pager(content) def show(self, content: str) -> None: """Use the same pager used by pydoc.""" From 19961c1a6a7448295377bb52479ac937e2bfdf9b Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Tue, 12 Oct 2021 16:13:16 -0700 Subject: [PATCH 018/287] Fix annotation for callable that needed optional This is annotated with Callable[], but it's being assigned a getattr that could be None. Add Optional to fix the typing. This mistake wasn't caught by mypy on current release, but it will start causing errors in the future. --- rich/measure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/measure.py b/rich/measure.py index 4382184f63..b57aa9c85e 100644 --- a/rich/measure.py +++ b/rich/measure.py @@ -100,8 +100,8 @@ def get( if hasattr(renderable, "__rich__"): renderable = renderable.__rich__() # type: ignore if is_renderable(renderable): - get_console_width: Callable[ - ["Console", "ConsoleOptions"], "Measurement" + get_console_width: Optional[ + Callable[["Console", "ConsoleOptions"], "Measurement"] ] = getattr(renderable, "__rich_measure__", None) if get_console_width is not None: render_width = ( From 67ef9a86c041b5b4d5f87a730d047aa3ea944633 Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Tue, 12 Oct 2021 16:16:33 -0700 Subject: [PATCH 019/287] update CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9b5f9b6c73..2f59597831 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -4,6 +4,7 @@ The following people have contributed to the development of Rich: +- [Gregory Beauregard](https://github.com/GBeauregard/pyffstream) - [Pete Davison](https://github.com/pd93) - [Oleksis Fraga](https://github.com/oleksis) - [Finn Hughes](https://github.com/finnhughes) From 8a33ce27db8ede85395d81aee3ac3e26034d5fdb Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Wed, 13 Oct 2021 17:23:10 +0200 Subject: [PATCH 020/287] fix a edge case bug when running under pytest --- CHANGELOG.md | 6 ++++++ CONTRIBUTORS.md | 1 + rich/console.py | 8 +++++++- tests/test_console.py | 11 +++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ed2419bd2..5c8f4baa10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.12.1] - unreleased + +### Fixed + +- Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run + ## [10.12.0] - 2021-10-06 ### Updated diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9b5f9b6c73..1a84b9e45c 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -13,6 +13,7 @@ The following people have contributed to the development of Rich: - [Will McGugan](https://github.com/willmcgugan) - [Nathan Page](https://github.com/nathanrpage97) - [Avi Perl](https://github.com/avi-perl) +- [Laurent Peuch](https://github.com/psycojoker) - [Kylian Point](https://github.com/p0lux) - [Kyle Pollina](https://github.com/kylepollina) - [Clément Robert](https://github.com/neutrinoceros) diff --git a/rich/console.py b/rich/console.py index d314d9bd8b..7f1e7faeb7 100644 --- a/rich/console.py +++ b/rich/console.py @@ -899,7 +899,13 @@ def is_terminal(self) -> bool: if self._force_terminal is not None: return self._force_terminal isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None) - return False if isatty is None else isatty() + try: + return False if isatty is None else isatty() + except ValueError: + # in some situation (at the end of a pytest run for example) isatty() can raise + # ValueError: I/O operation on closed file + # return False because we aren't in a terminal anymore + return False @property def is_dumb_terminal(self) -> bool: diff --git a/tests/test_console.py b/tests/test_console.py index 061cbd7faf..0f88436ca8 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -698,3 +698,14 @@ def test_print_newline_start(): result = console.end_capture() assert result == "Foo\n\nFoo\nbar\n\n" + + +def test_is_terminal_broken_file(): + console = Console() + + def _mock_isatty(): + raise ValueError() + + console.file.isatty = _mock_isatty + + assert console.is_terminal == False From 998c7dbeaf8815abfe792024e6442b7fdfebc151 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Wed, 13 Oct 2021 22:15:43 +0530 Subject: [PATCH 021/287] added example for export --- examples/export.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/export.py diff --git a/examples/export.py b/examples/export.py new file mode 100644 index 0000000000..1e81c74d0e --- /dev/null +++ b/examples/export.py @@ -0,0 +1,44 @@ +""" +Demonstrates export console output +""" + +from rich.console import Console +from rich.table import Table + +console = Console(record=True) + + +def print_table(): + table = Table(title="Star Wars Movies") + + table.add_column("Released", style="cyan", no_wrap=True) + table.add_column("Title", style="magenta") + table.add_column("Box Office", justify="right", style="green") + + table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$952,110,690") + table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") + table.add_row("Dec 15, 2017", "Star Wars Ep. V111: The Last Jedi", "$1,332,539,889") + table.add_row("Dec 16, 2016", "Rogue One: A Star Wars Story", "$1,332,439,889") + + console.print(table, justify="center") + + +# Prints table +print_table() + +# Get console output as text +text = console.export_text() + +# Calling print_table again because export_text() +# by default console output buffer is flushed once export function is called +print_table() + +# Get console output as html +# use clear=False so output is not flushed after export +html = console.export_html(clear=False) + +# Export text output to table_export.txt +console.save_text("table_export.txt", clear=False) + +# Export html output to table_export.html +console.save_html("table_export.html") From 2eed45e62757e08f1305afaee028b254dbc156b0 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Wed, 13 Oct 2021 22:19:29 +0530 Subject: [PATCH 022/287] updated comments --- examples/export.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/export.py b/examples/export.py index 1e81c74d0e..77ac0fb8a6 100644 --- a/examples/export.py +++ b/examples/export.py @@ -29,8 +29,8 @@ def print_table(): # Get console output as text text = console.export_text() -# Calling print_table again because export_text() -# by default console output buffer is flushed once export function is called +# Calling print_table again because console output buffer +# is flushed once export function is called print_table() # Get console output as html From 6f5ced7db567f49075ff9d1ddc769beb17f538a5 Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Wed, 13 Oct 2021 12:48:34 -0700 Subject: [PATCH 023/287] Fixed incorrect justify default Changed incorrect DEFAULT_OVERFLOW to DEFAULT_JUSTIFY. This wasn't caught by mypy because self.justify was incorrectly cast to a JustifyMethod instead of Optional[JustifyMethod] which made mypy think the remaining or values could never be evaluated. The cast is unneeded for mypy so removed it entirely. --- rich/text.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rich/text.py b/rich/text.py index cce93274e3..eee446d12e 100644 --- a/rich/text.py +++ b/rich/text.py @@ -555,9 +555,7 @@ def __rich_console__( self, console: "Console", options: "ConsoleOptions" ) -> Iterable[Segment]: tab_size: int = console.tab_size or self.tab_size or 8 - justify = ( - cast("JustifyMethod", self.justify) or options.justify or DEFAULT_OVERFLOW - ) + justify = self.justify or options.justify or DEFAULT_JUSTIFY overflow = ( cast("OverflowMethod", self.overflow) From 69f197c65fdef9e437c76347123f5e0e535b6ddc Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Wed, 13 Oct 2021 12:58:30 -0700 Subject: [PATCH 024/287] Remove wrong casts a la previous commit There were no new runtime bugs to find here, but they could conceal bugs in the future. Some type checkers will widen literals when assigning in an init, so we clarify we keep the self.justify/overflow as the string literals in order to keep type checking as strict as possible everywhere. --- rich/text.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/rich/text.py b/rich/text.py index eee446d12e..0ecdeae4b5 100644 --- a/rich/text.py +++ b/rich/text.py @@ -14,7 +14,6 @@ Optional, Tuple, Union, - cast, ) from ._loop import loop_last @@ -144,8 +143,8 @@ def __init__( ) -> None: self._text = [strip_control_codes(text)] self.style = style - self.justify = justify - self.overflow = overflow + self.justify: Optional["JustifyMethod"] = justify + self.overflow: Optional["OverflowMethod"] = overflow self.no_wrap = no_wrap self.end = end self.tab_size = tab_size @@ -557,11 +556,7 @@ def __rich_console__( tab_size: int = console.tab_size or self.tab_size or 8 justify = self.justify or options.justify or DEFAULT_JUSTIFY - overflow = ( - cast("OverflowMethod", self.overflow) - or options.overflow - or DEFAULT_OVERFLOW - ) + overflow = self.overflow or options.overflow or DEFAULT_OVERFLOW lines = self.wrap( console, @@ -1063,10 +1058,8 @@ def wrap( Returns: Lines: Number of lines. """ - wrap_justify = cast("JustifyMethod", justify or self.justify) or DEFAULT_JUSTIFY - wrap_overflow = ( - cast("OverflowMethod", overflow or self.overflow) or DEFAULT_OVERFLOW - ) + wrap_justify = justify or self.justify or DEFAULT_JUSTIFY + wrap_overflow = overflow or self.overflow or DEFAULT_OVERFLOW no_wrap = pick_bool(no_wrap, self.no_wrap, False) or overflow == "ignore" From 8d07aae7616de121c48c1dbc14b8bed01fd59a92 Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Wed, 13 Oct 2021 17:42:09 -0700 Subject: [PATCH 025/287] Support pyright-style literal treatment Not all typecheckers will assume a variable assigned to a literal type is a literal. In order to maintain the literal type as the code assumes this needs to be signposted by setting variables as literals. --- rich/columns.py | 2 +- rich/console.py | 2 +- rich/panel.py | 2 +- rich/pretty.py | 4 ++-- rich/progress.py | 2 +- rich/prompt.py | 4 +--- rich/table.py | 7 ++++--- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/rich/columns.py b/rich/columns.py index 4f29ca97b8..669a3a7074 100644 --- a/rich/columns.py +++ b/rich/columns.py @@ -48,7 +48,7 @@ def __init__( self.equal = equal self.column_first = column_first self.right_to_left = right_to_left - self.align = align + self.align: Optional[AlignMethod] = align self.title = title def add_renderable(self, renderable: RenderableType) -> None: diff --git a/rich/console.py b/rich/console.py index d314d9bd8b..66f091b340 100644 --- a/rich/console.py +++ b/rich/console.py @@ -666,7 +666,7 @@ def __init__( self.record = record self._markup = markup self._emoji = emoji - self._emoji_variant = emoji_variant + self._emoji_variant: Optional[EmojiVariant] = emoji_variant self._highlight = highlight self.legacy_windows: bool = ( (detect_legacy_windows() and not self.is_jupyter) diff --git a/rich/panel.py b/rich/panel.py index fcd1691764..151fe5f017 100644 --- a/rich/panel.py +++ b/rich/panel.py @@ -56,7 +56,7 @@ def __init__( self.renderable = renderable self.box = box self.title = title - self.title_align = title_align + self.title_align: AlignMethod = title_align self.subtitle = subtitle self.subtitle_align = subtitle_align self.safe_box = safe_box diff --git a/rich/pretty.py b/rich/pretty.py index 1a600a5d51..e37b766dd8 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -212,8 +212,8 @@ def __init__( self._object = _object self.highlighter = highlighter or ReprHighlighter() self.indent_size = indent_size - self.justify = justify - self.overflow = overflow + self.justify: Optional["JustifyMethod"] = justify + self.overflow: Optional["OverflowMethod"] = overflow self.no_wrap = no_wrap self.indent_guides = indent_guides self.max_length = max_length diff --git a/rich/progress.py b/rich/progress.py index 4eceea7352..8f2ec02660 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -271,7 +271,7 @@ def __init__( table_column: Optional[Column] = None, ) -> None: self.text_format = text_format - self.justify = justify + self.justify: JustifyMethod = justify self.style = style self.markup = markup self.highlighter = highlighter diff --git a/rich/prompt.py b/rich/prompt.py index daf76df855..c56071887a 100644 --- a/rich/prompt.py +++ b/rich/prompt.py @@ -330,11 +330,10 @@ class Confirm(PromptBase[bool]): response_type = bool validate_error_message = "[prompt.invalid]Please enter Y or N" - choices = ["y", "n"] + choices: List[str] = ["y", "n"] def render_default(self, default: DefaultType) -> Text: """Render the default as (y) or (n) rather than True/False.""" - assert self.choices is not None yes, no = self.choices return Text(f"({yes})" if default else f"({no})", style="prompt.default") @@ -343,7 +342,6 @@ def process_response(self, value: str) -> bool: value = value.strip().lower() if value not in self.choices: raise InvalidResponse(self.validate_error_message) - assert self.choices is not None return value == self.choices[0] diff --git a/rich/table.py b/rich/table.py index b6a9c1ae6e..8503908b6e 100644 --- a/rich/table.py +++ b/rich/table.py @@ -6,6 +6,7 @@ List, NamedTuple, Optional, + Sequence, Tuple, Union, ) @@ -201,10 +202,10 @@ def __init__( self.border_style = border_style self.title_style = title_style self.caption_style = caption_style - self.title_justify = title_justify - self.caption_justify = caption_justify + self.title_justify: "JustifyMethod" = title_justify + self.caption_justify: "JustifyMethod" = caption_justify self.highlight = highlight - self.row_styles = list(row_styles or []) + self.row_styles: Sequence[StyleType] = list(row_styles or []) append_column = self.columns.append for header in headers: if isinstance(header, str): From 2e2884da368c66afd993af482a9de409c4515e1a Mon Sep 17 00:00:00 2001 From: akettmann-e24 <50422880+akettmann-e24@users.noreply.github.com> Date: Thu, 14 Oct 2021 10:48:45 -0500 Subject: [PATCH 026/287] fix return type for `Table.expand()` return type for `Table.expand()` was `int` should be `bool` based on the type annotation for `expand` argument for `Table.__init__` --- rich/table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/table.py b/rich/table.py index b6a9c1ae6e..05bf3ab62b 100644 --- a/rich/table.py +++ b/rich/table.py @@ -247,7 +247,7 @@ def grid( ) @property - def expand(self) -> int: + def expand(self) -> bool: """Setting a non-None self.width implies expand.""" return self._expand or self.width is not None From 14e20ecea6e3584e9e5515bbba52e3dbc9fecd6c Mon Sep 17 00:00:00 2001 From: akettmann-e24 <50422880+akettmann-e24@users.noreply.github.com> Date: Thu, 14 Oct 2021 10:56:38 -0500 Subject: [PATCH 027/287] Update CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9b5f9b6c73..cd2eb646e9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,6 +8,7 @@ The following people have contributed to the development of Rich: - [Oleksis Fraga](https://github.com/oleksis) - [Finn Hughes](https://github.com/finnhughes) - [Josh Karpel](https://github.com/JoshKarpel) +- [Andrew Kettmann](https://github.com/akettmann) - [Hedy Li](https://github.com/hedythedev) - [Alexander Mancevice](https://github.com/amancevice) - [Will McGugan](https://github.com/willmcgugan) From 8cfd988cae6af85d2210ceb4d83ba770111a7cc4 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 15 Oct 2021 09:54:20 +0100 Subject: [PATCH 028/287] Added link to Italian Readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ae8cd10264..dabe67a4b3 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) Rich is a Python library for _rich_ text and beautiful formatting in the terminal. From b098f55af668284a79bb214af19ebc40e55e752c Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Fri, 15 Oct 2021 14:23:05 +0200 Subject: [PATCH 029/287] ref(tree): minor changes --- rich/tree.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/tree.py b/rich/tree.py index bf3dda28cf..7ea8cc5ddc 100644 --- a/rich/tree.py +++ b/rich/tree.py @@ -127,7 +127,7 @@ def make_guide(index: int, style: Style) -> Segment: guide_style = guide_style_stack.current + get_style(node.guide_style) style = style_stack.current + get_style(node.style) - prefix = levels[(1 if self.hide_root == False else 2) :] + prefix = levels[(2 if self.hide_root else 2) :] renderable_lines = console.render_lines( Styled(node.label, style), options.update( @@ -138,7 +138,7 @@ def make_guide(index: int, style: Style) -> Segment: ), ) - if not (depth == 0 and self.hide_root == True): + if not (depth == 0 and self.hide_root): for first, line in loop_first(renderable_lines): if prefix: yield from _Segment.apply_style( From 1015379fe386fcabc70ab188d276bc96c4e5406e Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Fri, 15 Oct 2021 15:18:24 +0200 Subject: [PATCH 030/287] fix(tree): tree not shows root guide --- rich/tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/tree.py b/rich/tree.py index 7ea8cc5ddc..66203e693e 100644 --- a/rich/tree.py +++ b/rich/tree.py @@ -127,7 +127,7 @@ def make_guide(index: int, style: Style) -> Segment: guide_style = guide_style_stack.current + get_style(node.guide_style) style = style_stack.current + get_style(node.style) - prefix = levels[(2 if self.hide_root else 2) :] + prefix = levels[(2 if self.hide_root else 1) :] renderable_lines = console.render_lines( Styled(node.label, style), options.update( From f2a8a0ebc8740ad0b191be3895386833eb913992 Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Fri, 15 Oct 2021 15:49:22 +0200 Subject: [PATCH 031/287] tests(tree): add tree render with hide_root flag --- tests/test_tree.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_tree.py b/tests/test_tree.py index babcc3cf27..4dd01a4aaa 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -93,6 +93,39 @@ def test_render_tree_win32(): expected = "foo \n├── \x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[44m│ \x1b[0m\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[44m│ \x1b[0m\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\n└── egg \n" assert result == expected +@pytest.mark.skipif(sys.platform == "win32", reason="different on Windows") +def test_render_tree_hide_root_non_win32(): + tree = Tree("foo", hide_root=True) + tree.add("bar", style="italic") + baz_tree = tree.add("baz", guide_style="bold red", style="on blue") + baz_tree.add("1") + baz_tree.add("2") + tree.add("egg") + + console = Console(width=20, force_terminal=True, color_system="standard") + console.begin_capture() + console.print(tree) + result = console.end_capture() + print(repr(result)) + expected = "\x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\negg \n" + assert result == expected + +@pytest.mark.skipif(sys.platform != "win32", reason="Windows specific") +def test_render_tree_hide_root_win32(): + tree = Tree("foo", hide_root=True) + tree.add("bar", style="italic") + baz_tree = tree.add("baz", guide_style="bold red", style="on blue") + baz_tree.add("1") + baz_tree.add("2") + tree.add("egg") + + console = Console(width=20, force_terminal=True, color_system="standard") + console.begin_capture() + console.print(tree) + result = console.end_capture() + print(repr(result)) + expected = "\x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\negg \n" + assert result == expected def test_tree_measure(): tree = Tree("foo") From 3bcbbb5d9e8dcb2eda929eeee6ffe1c28f783e9c Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Fri, 15 Oct 2021 15:54:03 +0200 Subject: [PATCH 032/287] ref: black format --- tests/test_tree.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_tree.py b/tests/test_tree.py index 4dd01a4aaa..8fc070d3f3 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -93,6 +93,7 @@ def test_render_tree_win32(): expected = "foo \n├── \x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[44m│ \x1b[0m\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[44m│ \x1b[0m\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\n└── egg \n" assert result == expected + @pytest.mark.skipif(sys.platform == "win32", reason="different on Windows") def test_render_tree_hide_root_non_win32(): tree = Tree("foo", hide_root=True) @@ -110,6 +111,7 @@ def test_render_tree_hide_root_non_win32(): expected = "\x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\negg \n" assert result == expected + @pytest.mark.skipif(sys.platform != "win32", reason="Windows specific") def test_render_tree_hide_root_win32(): tree = Tree("foo", hide_root=True) @@ -127,6 +129,7 @@ def test_render_tree_hide_root_win32(): expected = "\x1b[3mbar\x1b[0m\x1b[3m \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m \x1b[0m\n\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m \x1b[0m\negg \n" assert result == expected + def test_tree_measure(): tree = Tree("foo") tree.add("bar") From 215efa6f79f7ee7a54df170b6b589974d734effc Mon Sep 17 00:00:00 2001 From: v0lp3 Date: Fri, 15 Oct 2021 17:19:53 +0200 Subject: [PATCH 033/287] fix(codespell): include README.it.md to codespell exclusions --- .github/workflows/codespell.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 95daf9d31b..28db4fc2c9 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -7,4 +7,4 @@ jobs: - uses: actions/checkout@v2 - run: python3 -m pip install codespell - run: codespell --ignore-words-list="ba,fo,hel,revered,womens" - --skip="./README.de.md,./README.es.md,./README.sv.md,./README.fr.md,./README.de-ch.md,./README.hi.md,./README.pt-br.md,*.svg" + --skip="./README.de.md,./README.es.md,./README.sv.md,./README.fr.md,./README.de-ch.md,./README.hi.md,./README.pt-br.md,./README.it.md,*.svg" From 110cee24fa07aeb31a07908a0ba49da27d1afb7f Mon Sep 17 00:00:00 2001 From: jz4o <26317360+jz4o@users.noreply.github.com> Date: Sat, 16 Oct 2021 01:51:09 +0900 Subject: [PATCH 034/287] Fix markdown syntax in README.ja.md --- README.ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.ja.md b/README.ja.md index b1a047a502..a71b36ff69 100644 --- a/README.ja.md +++ b/README.ja.md @@ -19,7 +19,7 @@ • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) -Richは、_リッチ_なテキストや美しい書式設定をターミナルで行うためのPythonライブラリです。 +Richは、 _リッチ_ なテキストや美しい書式設定をターミナルで行うためのPythonライブラリです。 [Rich API](https://rich.readthedocs.io/en/latest/)を使用すると、ターミナルの出力に色やスタイルを簡単に追加することができます。 Richはきれいなテーブル、プログレスバー、マークダウン、シンタックスハイライトされたソースコード、トレースバックなどをすぐに生成・表示することもできます。 From 54deb754cacaaf41181497c53ccabe40a34e7517 Mon Sep 17 00:00:00 2001 From: GBeauregard Date: Fri, 15 Oct 2021 13:05:34 -0700 Subject: [PATCH 035/287] avoid marking our exported API as private It is standard (see PEP 484 stub file section) to mark redundantly imported items as exported. This PR adds this redundant exporting to files that incidentally import part of their own API in their __main__ sections to avoid accidentally indicating they should be private to type checkers. --- rich/box.py | 2 +- rich/live.py | 2 +- rich/table.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rich/box.py b/rich/box.py index de79f05932..d37c6c81c0 100644 --- a/rich/box.py +++ b/rich/box.py @@ -435,7 +435,7 @@ def get_bottom(self, widths: Iterable[int]) -> str: from rich.columns import Columns from rich.panel import Panel - from . import box + from . import box as box from .console import Console from .table import Table from .text import Text diff --git a/rich/live.py b/rich/live.py index f2ba64a7eb..8097f7d2e6 100644 --- a/rich/live.py +++ b/rich/live.py @@ -276,7 +276,7 @@ def process_renderables( from .align import Align from .console import Console - from .live import Live + from .live import Live as Live from .panel import Panel from .rule import Rule from .syntax import Syntax diff --git a/rich/table.py b/rich/table.py index b6a9c1ae6e..5d63d543fe 100644 --- a/rich/table.py +++ b/rich/table.py @@ -845,7 +845,7 @@ def _render( if __name__ == "__main__": # pragma: no cover from rich.console import Console from rich.highlighter import ReprHighlighter - from rich.table import Table + from rich.table import Table as Table table = Table( title="Star Wars Movies", From c875b9c8342485b1648eb4c343b65b3cc73ec090 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sun, 19 Sep 2021 09:39:42 +0200 Subject: [PATCH 036/287] add example with dynamic group of progress bars --- docs/source/progress.rst | 2 +- examples/dynamic_progress.py | 107 +++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 examples/dynamic_progress.py diff --git a/docs/source/progress.rst b/docs/source/progress.rst index 5c70e329b6..364ad94ce8 100644 --- a/docs/source/progress.rst +++ b/docs/source/progress.rst @@ -192,7 +192,7 @@ If the :class:`~rich.progress.Progress` class doesn't offer exactly what you nee Multiple Progress ----------------- -You can't have different columns per task with a single Progress instance. However, you can have as many Progress instance as you like in a :ref:`live`. See `live_progress.py `_ for an example of using multiple Progress instances. +You can't have different columns per task with a single Progress instance. However, you can have as many Progress instance as you like in a :ref:`live`. See `live_progress.py `_ and `dynamic_progress.py `_ for examples of using multiple Progress instances. Example ------- diff --git a/examples/dynamic_progress.py b/examples/dynamic_progress.py new file mode 100644 index 0000000000..8001f29a9b --- /dev/null +++ b/examples/dynamic_progress.py @@ -0,0 +1,107 @@ +""" + +Demonstrates how to create a dynamic group of progress bars, +showing multi-level progress for multiple tasks (installing apps in the example), +each of which consisting of multiple steps. + +""" + +import time + +from rich.console import RenderGroup +from rich.live import Live +from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn + + +def run_steps(name, step_times, app_steps_task_id): + """Run steps for a single app, and update corresponding progress bars.""" + + for idx, step_time in enumerate(step_times): + # add progress bar for this step (time elapsed + spinner) + action = step_actions[idx] + step_task_id = step_progress.add_task("", action=action, name=name) + + # run steps, update progress + for _ in range(step_time): + time.sleep(1) + step_progress.update(step_task_id, advance=1) + + # stop and hide progress bar for this step when done + step_progress.stop_task(step_task_id) + step_progress.update(step_task_id, visible=False) + + # also update progress bar for current app when step is done + app_steps_progress.update(app_steps_task_id, advance=1) + + +# progress bar for current app showing only elapsed time, +# which will stay visible when app is installed +current_app_progress = Progress( + TimeElapsedColumn(), + TextColumn("{task.description}"), +) + +# progress bars for single app steps (will be hidden when step is done) +step_progress = Progress( + TextColumn(" "), + TimeElapsedColumn(), + TextColumn("[bold purple]{task.fields[action]}"), + SpinnerColumn("simpleDots"), +) +# progress bar for current app (progress in steps) +app_steps_progress = Progress( + TextColumn("[bold blue]Progress for app {task.fields[name]}: {task.percentage:.0f}%"), + BarColumn(), + TextColumn("({task.completed} of {task.total} steps done)"), +) +# overall progress bar +overall_progress = Progress( + TimeElapsedColumn(), + BarColumn(), + TextColumn("{task.description}") +) +# group of progress bars; +# some are always visible, others will disappear when progress is complete +group = RenderGroup( + current_app_progress, + step_progress, + app_steps_progress, + overall_progress +) + +# tuple specifies how long each step takes for that app +step_actions = ("downloading", "configuring", "building", "installing") +apps = [ + ("one", (3, 2, 5, 3)), + ("two", (2, 5, 10, 6)), + ("three", (5, 1, 5, 3)), +] + +# create overall progress bar +overall_task_id = overall_progress.add_task("", total=len(apps)) + +# use own live instance as context manager with group of progress bars, +# which allows for running multiple different progress bars in parallel, +# and dynamically showing/hiding them +with Live(group): + + for idx, (name, step_times) in enumerate(apps): + # update message on overall progress bar + top_descr = "[bold #AAAAAA](%d out of %d apps installed)" % (idx, len(apps)) + overall_progress.update(overall_task_id, description=top_descr) + + # add progress bar for steps of this app, and run the steps + current_task_id = current_app_progress.add_task("Installing app %s" % name) + app_steps_task_id = app_steps_progress.add_task("", total=len(step_times), name=name) + run_steps(name, step_times, app_steps_task_id) + + # stop and hide steps progress bar for this specific app + app_steps_progress.update(app_steps_task_id, visible=False) + current_app_progress.stop_task(current_task_id) + current_app_progress.update(current_task_id, description="[bold green]App %s installed!" % name) + + # increase overall progress now this task is done + overall_progress.update(overall_task_id, advance=1) + + # final update for message on overall progress bar + overall_progress.update(overall_task_id, description="[bold green]%s apps installed, done!" % len(apps)) From 5ecd4ad7741e22915704c2b80d403cefe93cd713 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sun, 19 Sep 2021 09:49:04 +0200 Subject: [PATCH 037/287] reformat dynamic_progress.py example with Black --- examples/dynamic_progress.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/examples/dynamic_progress.py b/examples/dynamic_progress.py index 8001f29a9b..0656eb6537 100644 --- a/examples/dynamic_progress.py +++ b/examples/dynamic_progress.py @@ -10,7 +10,13 @@ from rich.console import RenderGroup from rich.live import Live -from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn +from rich.progress import ( + BarColumn, + Progress, + SpinnerColumn, + TextColumn, + TimeElapsedColumn, +) def run_steps(name, step_times, app_steps_task_id): @@ -50,23 +56,20 @@ def run_steps(name, step_times, app_steps_task_id): ) # progress bar for current app (progress in steps) app_steps_progress = Progress( - TextColumn("[bold blue]Progress for app {task.fields[name]}: {task.percentage:.0f}%"), + TextColumn( + "[bold blue]Progress for app {task.fields[name]}: {task.percentage:.0f}%" + ), BarColumn(), TextColumn("({task.completed} of {task.total} steps done)"), ) # overall progress bar overall_progress = Progress( - TimeElapsedColumn(), - BarColumn(), - TextColumn("{task.description}") + TimeElapsedColumn(), BarColumn(), TextColumn("{task.description}") ) # group of progress bars; # some are always visible, others will disappear when progress is complete group = RenderGroup( - current_app_progress, - step_progress, - app_steps_progress, - overall_progress + current_app_progress, step_progress, app_steps_progress, overall_progress ) # tuple specifies how long each step takes for that app @@ -92,16 +95,22 @@ def run_steps(name, step_times, app_steps_task_id): # add progress bar for steps of this app, and run the steps current_task_id = current_app_progress.add_task("Installing app %s" % name) - app_steps_task_id = app_steps_progress.add_task("", total=len(step_times), name=name) + app_steps_task_id = app_steps_progress.add_task( + "", total=len(step_times), name=name + ) run_steps(name, step_times, app_steps_task_id) # stop and hide steps progress bar for this specific app app_steps_progress.update(app_steps_task_id, visible=False) current_app_progress.stop_task(current_task_id) - current_app_progress.update(current_task_id, description="[bold green]App %s installed!" % name) + current_app_progress.update( + current_task_id, description="[bold green]App %s installed!" % name + ) # increase overall progress now this task is done overall_progress.update(overall_task_id, advance=1) # final update for message on overall progress bar - overall_progress.update(overall_task_id, description="[bold green]%s apps installed, done!" % len(apps)) + overall_progress.update( + overall_task_id, description="[bold green]%s apps installed, done!" % len(apps) + ) From 58b71127aaeaf5776c658772d17012f60101feae Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sun, 19 Sep 2021 09:51:44 +0200 Subject: [PATCH 038/287] add @boegel to contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ad5147afc2..953348a21b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -7,6 +7,7 @@ The following people have contributed to the development of Rich: - [Gregory Beauregard](https://github.com/GBeauregard/pyffstream) - [Pete Davison](https://github.com/pd93) - [Oleksis Fraga](https://github.com/oleksis) +- [Kenneth Hoste](https://github.com/boegel) - [Finn Hughes](https://github.com/finnhughes) - [Josh Karpel](https://github.com/JoshKarpel) - [Andrew Kettmann](https://github.com/akettmann) From ab746e653737f43c1db8cb1d5857fa635b7246ce Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sun, 19 Sep 2021 09:51:51 +0200 Subject: [PATCH 039/287] udpate changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8f4baa10..9086beda82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [10.12.1] - unreleased +### Added + +- Added dynamic_progress.py to examples + ### Fixed - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run From b9af6f7d8f3aec471e4930a450be067e5b379559 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 16 Oct 2021 13:42:46 +0200 Subject: [PATCH 040/287] use Group since RenderGroup is sort of deprecated, rename 'group' to 'process_group' --- examples/dynamic_progress.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/dynamic_progress.py b/examples/dynamic_progress.py index 0656eb6537..d45bb3775e 100644 --- a/examples/dynamic_progress.py +++ b/examples/dynamic_progress.py @@ -8,7 +8,7 @@ import time -from rich.console import RenderGroup +from rich.console import Group from rich.live import Live from rich.progress import ( BarColumn, @@ -68,7 +68,7 @@ def run_steps(name, step_times, app_steps_task_id): ) # group of progress bars; # some are always visible, others will disappear when progress is complete -group = RenderGroup( +progress_group = Group( current_app_progress, step_progress, app_steps_progress, overall_progress ) @@ -86,7 +86,7 @@ def run_steps(name, step_times, app_steps_task_id): # use own live instance as context manager with group of progress bars, # which allows for running multiple different progress bars in parallel, # and dynamically showing/hiding them -with Live(group): +with Live(progress_group): for idx, (name, step_times) in enumerate(apps): # update message on overall progress bar From 8a1585f2cf88da8c51a80bde3114e1023539fb17 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 16 Oct 2021 13:48:36 +0200 Subject: [PATCH 041/287] put app progress in panel, speed things up --- examples/dynamic_progress.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/dynamic_progress.py b/examples/dynamic_progress.py index d45bb3775e..a1101928b2 100644 --- a/examples/dynamic_progress.py +++ b/examples/dynamic_progress.py @@ -9,6 +9,7 @@ import time from rich.console import Group +from rich.panel import Panel from rich.live import Live from rich.progress import ( BarColumn, @@ -29,7 +30,7 @@ def run_steps(name, step_times, app_steps_task_id): # run steps, update progress for _ in range(step_time): - time.sleep(1) + time.sleep(0.5) step_progress.update(step_task_id, advance=1) # stop and hide progress bar for this step when done @@ -69,15 +70,15 @@ def run_steps(name, step_times, app_steps_task_id): # group of progress bars; # some are always visible, others will disappear when progress is complete progress_group = Group( - current_app_progress, step_progress, app_steps_progress, overall_progress + Panel(Group(current_app_progress, step_progress, app_steps_progress)), overall_progress ) # tuple specifies how long each step takes for that app step_actions = ("downloading", "configuring", "building", "installing") apps = [ - ("one", (3, 2, 5, 3)), - ("two", (2, 5, 10, 6)), - ("three", (5, 1, 5, 3)), + ("one", (2, 1, 4, 2)), + ("two", (1, 3, 8, 4)), + ("three", (2, 1, 3, 2)), ] # create overall progress bar From 28a33cbcc38bb2b3f059c019dda44521dc7ed65e Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 16 Oct 2021 13:49:56 +0200 Subject: [PATCH 042/287] reformat with latest black (21.9b0) --- examples/dynamic_progress.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/dynamic_progress.py b/examples/dynamic_progress.py index a1101928b2..c38da2ebf0 100644 --- a/examples/dynamic_progress.py +++ b/examples/dynamic_progress.py @@ -70,7 +70,8 @@ def run_steps(name, step_times, app_steps_task_id): # group of progress bars; # some are always visible, others will disappear when progress is complete progress_group = Group( - Panel(Group(current_app_progress, step_progress, app_steps_progress)), overall_progress + Panel(Group(current_app_progress, step_progress, app_steps_progress)), + overall_progress, ) # tuple specifies how long each step takes for that app From 0cf528d9a88e33e7ad72a53b13c1d0302c78e18d Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Sat, 16 Oct 2021 19:04:34 +0530 Subject: [PATCH 043/287] added descriptive comments --- examples/export.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/export.py b/examples/export.py index 77ac0fb8a6..d16daa8692 100644 --- a/examples/export.py +++ b/examples/export.py @@ -24,21 +24,27 @@ def print_table(): # Prints table +print("print table to the console") print_table() # Get console output as text +print("geting console output as text") text = console.export_text() # Calling print_table again because console output buffer # is flushed once export function is called +print("print table to the console") print_table() # Get console output as html # use clear=False so output is not flushed after export +print("geting console output as html") html = console.export_html(clear=False) # Export text output to table_export.txt +print("exporting console output to table_export.txt") console.save_text("table_export.txt", clear=False) # Export html output to table_export.html +print("exporting console output to table_export.html") console.save_html("table_export.html") From ddde385389f7e4c4798491f142e0b8acfc7e4b23 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Sat, 16 Oct 2021 19:05:47 +0530 Subject: [PATCH 044/287] fix typo --- examples/export.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/export.py b/examples/export.py index d16daa8692..07387bc43e 100644 --- a/examples/export.py +++ b/examples/export.py @@ -28,7 +28,7 @@ def print_table(): print_table() # Get console output as text -print("geting console output as text") +print("getting console output as text") text = console.export_text() # Calling print_table again because console output buffer @@ -38,7 +38,7 @@ def print_table(): # Get console output as html # use clear=False so output is not flushed after export -print("geting console output as html") +print("getting console output as html") html = console.export_html(clear=False) # Export text output to table_export.txt From 8943924d007a6df67d85ccaa4ca9fc4ba69b7afb Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Sat, 16 Oct 2021 19:16:10 +0530 Subject: [PATCH 045/287] export captured console output --- examples/export.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/export.py b/examples/export.py index 07387bc43e..a9792707c6 100644 --- a/examples/export.py +++ b/examples/export.py @@ -24,27 +24,25 @@ def print_table(): # Prints table -print("print table to the console") print_table() # Get console output as text -print("getting console output as text") text = console.export_text() +with open("plaintext_export.txt", "w") as file: + file.write(text) # Calling print_table again because console output buffer # is flushed once export function is called -print("print table to the console") print_table() # Get console output as html # use clear=False so output is not flushed after export -print("getting console output as html") html = console.export_html(clear=False) +with open("html_export.html", "w") as file: + file.write(html) # Export text output to table_export.txt -print("exporting console output to table_export.txt") -console.save_text("table_export.txt", clear=False) +console.save_text("rich_export.txt", clear=False) # Export html output to table_export.html -print("exporting console output to table_export.html") -console.save_html("table_export.html") +console.save_html("rich_export.html") From 5dddadb98340fec6afda80fd1a8ee1eda907b60a Mon Sep 17 00:00:00 2001 From: Suresh Kumar Date: Sat, 16 Oct 2021 22:04:45 +0530 Subject: [PATCH 046/287] print exports to terminal --- examples/export.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/examples/export.py b/examples/export.py index a9792707c6..dada493d80 100644 --- a/examples/export.py +++ b/examples/export.py @@ -20,16 +20,18 @@ def print_table(): table.add_row("Dec 15, 2017", "Star Wars Ep. V111: The Last Jedi", "$1,332,539,889") table.add_row("Dec 16, 2016", "Rogue One: A Star Wars Story", "$1,332,439,889") - console.print(table, justify="center") + console.print(table) # Prints table print_table() # Get console output as text +file1 = "table_export_plaintext.txt" text = console.export_text() -with open("plaintext_export.txt", "w") as file: +with open(file1, "w") as file: file.write(text) +print(f"Exported console output as plain text to {file1}") # Calling print_table again because console output buffer # is flushed once export function is called @@ -37,12 +39,18 @@ def print_table(): # Get console output as html # use clear=False so output is not flushed after export +file2 = "table_export_html.html" html = console.export_html(clear=False) -with open("html_export.html", "w") as file: +with open(file2, "w") as file: file.write(html) +print(f"Exported console output as html to {file2}") # Export text output to table_export.txt -console.save_text("rich_export.txt", clear=False) +file3 = "table_export_plaintext2.txt" +console.save_text(file3, clear=False) +print(f"Exported console output as plain text to {file3}") # Export html output to table_export.html -console.save_html("rich_export.html") +file4 = "table_export_html2.html" +console.save_html(file4) +print(f"Exported console output as html to {file4}") From 5876f5cacc4251997d5b1472386a696755d8b1e3 Mon Sep 17 00:00:00 2001 From: Tim Savage Date: Fri, 22 Oct 2021 12:24:38 +1100 Subject: [PATCH 047/287] Add a test case to simulate pythonw related to issue #1619 --- tests/test_logging.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_logging.py b/tests/test_logging.py index 59d2ecb25f..a1acc00222 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -1,6 +1,8 @@ import io import os import logging +from typing import Optional + import pytest from rich.console import Console @@ -89,6 +91,37 @@ def test_exception_with_extra_lines(): assert "division by zero" in render +def test_stderr_and_stdout_are_none(monkeypatch): + # This test is specifically to handle cases when using pythonw on + # windows an stderr and stdout are set to None. + # See https://bugs.python.org/issue13807 + + monkeypatch.setattr("sys.stdout", None) + monkeypatch.setattr("sys.stderr", None) + + console = Console(_environ={}) + target_handler = RichHandler(console=console) + actual_record: Optional[logging.LogRecord] = None + + def mock_handle_error(record): + nonlocal actual_record + actual_record = record + + target_handler.handleError = mock_handle_error + log.addHandler(target_handler) + + try: + 1 / 0 + except ZeroDivisionError: + log.exception("message") + + finally: + log.removeHandler(target_handler) + + assert actual_record is not None + assert "message" in actual_record.msg + + if __name__ == "__main__": render = make_log() print(render) From 137adbabf8845b4a49072e656480cd258d464c9c Mon Sep 17 00:00:00 2001 From: Tim Savage Date: Fri, 22 Oct 2021 12:25:43 +1100 Subject: [PATCH 048/287] Put an exception handler around console.print This is to handle any failures in the print method and defer exception handling to the Handler.handleErrors method. --- rich/logging.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rich/logging.py b/rich/logging.py index c193ee5a2f..47ca7d42de 100644 --- a/rich/logging.py +++ b/rich/logging.py @@ -150,7 +150,10 @@ def emit(self, record: LogRecord) -> None: log_renderable = self.render( record=record, traceback=traceback, message_renderable=message_renderable ) - self.console.print(log_renderable) + try: + self.console.print(log_renderable) + except Exception: + self.handleError(record) def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable": """Render message text in to Text. From 35fdd5912807ed2428a2674944e084264e601c09 Mon Sep 17 00:00:00 2001 From: Tim Savage Date: Fri, 22 Oct 2021 12:31:03 +1100 Subject: [PATCH 049/287] Updated CHANGELOG.md and CONTRIBUTORS.md --- CHANGELOG.md | 1 + CONTRIBUTORS.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8f4baa10..e235f948e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run +- Fixed a bug where logging handler raises an exception when running with pythonw (related to https://bugs.python.org/issue13807) ## [10.12.0] - 2021-10-06 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ad5147afc2..a1590fa620 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,4 +20,5 @@ The following people have contributed to the development of Rich: - [Kyle Pollina](https://github.com/kylepollina) - [Clément Robert](https://github.com/neutrinoceros) - [Tushar Sadhwani](https://github.com/tusharsadhwani) +- [Tim Savage](https://github.com/timsavage) - [Gabriele N. Tornetta](https://github.com/p403n1x87) From d429b02991afad36346d2454235eea064cffc4d6 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Thu, 28 Oct 2021 09:17:57 -0400 Subject: [PATCH 050/287] Remove extra space in Theme example --- docs/source/style.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/style.rst b/docs/source/style.rst index b01621502b..ee9eca5df0 100644 --- a/docs/source/style.rst +++ b/docs/source/style.rst @@ -115,7 +115,7 @@ To use a style theme, construct a :class:`~rich.theme.Theme` instance and pass i from rich.console import Console from rich.theme import Theme custom_theme = Theme({ - "info" : "dim cyan", + "info": "dim cyan", "warning": "magenta", "danger": "bold red" }) From 119ab778a3b18554c07ec86b250e8aa45b75f581 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Thu, 28 Oct 2021 14:50:29 -0400 Subject: [PATCH 051/287] Wrap LICENSE file at 80 characters --- LICENSE | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index 8d9e799c3d..4415505566 100644 --- a/LICENSE +++ b/LICENSE @@ -1,8 +1,19 @@ -Copyright 2020 Will McGugan +Copyright (c) 2020 Will McGugan -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 3949754c4333ce2759a4eb286c4411f440bbde7b Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:35:58 -0300 Subject: [PATCH 052/287] Add the sphinx.ext.intersphinx plugin --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 774871e3e0..34258eb496 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -43,6 +43,7 @@ "sphinx.ext.autodoc", "sphinx.ext.viewcode", "sphinx.ext.napoleon", + "sphinx.ext.intersphinx", "sphinx.ext.autosectionlabel", "sphinx_copybutton", ] From 3844ae817bbf3672926821d4323793c1c9f8b8db Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:36:52 -0300 Subject: [PATCH 053/287] Link to Python's builtin input() --- docs/source/console.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index 6ea6e09266..7e3a17079b 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -238,7 +238,7 @@ The :meth:`~rich.console.Console.print` method has a boolean ``crop`` argument. Input ----- -The console class has an :meth:`~rich.console.Console.input` which works in the same way as Python's builtin ``input()`` method, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: +The console class has an :meth:`~rich.console.Console.input` which works in the same way as Python's builtin :func:`input` method, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: from rich.console import Console console = Console() From 8f9131c586b0f09a93f2630f8deafc58b8e25418 Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:38:38 -0300 Subject: [PATCH 054/287] Distinguish input() method from function --- docs/source/console.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index 7e3a17079b..8c1e7520f2 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -238,7 +238,7 @@ The :meth:`~rich.console.Console.print` method has a boolean ``crop`` argument. Input ----- -The console class has an :meth:`~rich.console.Console.input` which works in the same way as Python's builtin :func:`input` method, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: +The console class has an :meth:`~rich.console.Console.input` method which works in the same way as Python's builtin :func:`input` function, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: from rich.console import Console console = Console() From eac0767676918d1e1debba1105c9c4a977fb3f1e Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:41:33 -0300 Subject: [PATCH 055/287] Mention Python's buitin readline module in the docs --- docs/source/console.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/console.rst b/docs/source/console.rst index 8c1e7520f2..2b26e3104e 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -244,6 +244,8 @@ The console class has an :meth:`~rich.console.Console.input` method which works console = Console() console.input("What is [i]your[/i] [bold red]name[/]? :smiley: ") +If Python's builtin :mod:`readline` module is previously loaded, elaborate line editing and history features will be available. + Exporting --------- From 313ee3fa9b7dbb764bb1fd1c221001962d535cb7 Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:53:51 -0300 Subject: [PATCH 056/287] Cross-link the console API from prompts --- docs/source/prompt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/prompt.rst b/docs/source/prompt.rst index fa256a0f64..088aa8e743 100644 --- a/docs/source/prompt.rst +++ b/docs/source/prompt.rst @@ -1,7 +1,7 @@ Prompt ====== -Rich has a number of :class:`~rich.prompt.Prompt` classes which ask a user for input and loop until a valid response is received. Here's a simple example:: +Rich has a number of :class:`~rich.prompt.Prompt` classes which ask a user for input and loop until a valid response is received (they all use the :ref:`Console API` internally). Here's a simple example:: >>> from rich.prompt import Prompt >>> name = Prompt.ask("Enter your name") From 747e55bd6fc31127aa4b266c1d9820f5e26e1d61 Mon Sep 17 00:00:00 2001 From: "Felipe S. S. Schneider" Date: Sun, 31 Oct 2021 12:58:42 -0300 Subject: [PATCH 057/287] Cross-link Python's builtin input() and readline from Console.input() --- rich/console.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rich/console.py b/rich/console.py index 7c4be7fcf8..de0a01b031 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1919,6 +1919,8 @@ def input( ) -> str: """Displays a prompt and waits for input from the user. The prompt may contain color / style. + It works in the same way as Python's builtin :func:`input` function and provides elaborate line editing and history features if Python's builtin :mod:`readline` module is previously loaded. + Args: prompt (Union[str, Text]): Text to render in the prompt. markup (bool, optional): Enable console markup (requires a str prompt). Defaults to True. From da3b1d99ebee9c2e190aa9579881ce08f2c288fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 13:03:45 +0000 Subject: [PATCH 058/287] Bump black from 21.9b0 to 21.10b0 Bumps [black](https://github.com/psf/black) from 21.9b0 to 21.10b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- poetry.lock | 123 ++++++++++++++++++++++++++++++++----------------- pyproject.toml | 2 +- 2 files changed, 82 insertions(+), 43 deletions(-) diff --git a/poetry.lock b/poetry.lock index 3374de9de0..ac178ccaa5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -62,7 +62,7 @@ python-versions = "*" [[package]] name = "black" -version = "21.9b0" +version = "21.10b0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -84,9 +84,9 @@ typing-extensions = [ [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] +d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -python2 = ["typed-ast (>=1.4.2)"] +python2 = ["typed-ast (>=1.4.3)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] @@ -146,7 +146,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "6.0" +version = "6.1.1" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -933,7 +933,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "0215d2db0f3d908a013cd733e8019891e208c9b6b733a05658d49e96a8be3108" +content-hash = "0434c898cb68444014e1d0f00cb88d10df9a26641016cd123da2d5c7cf3c014e" [metadata.files] appnope = [ @@ -970,8 +970,8 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] black = [ - {file = "black-21.9b0-py3-none-any.whl", hash = "sha256:380f1b5da05e5a1429225676655dddb96f5ae8c75bdf91e53d798871b902a115"}, - {file = "black-21.9b0.tar.gz", hash = "sha256:7de4cfc7eb6b710de325712d40125689101d21d25283eed7e9998722cf10eb91"}, + {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, + {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, ] bleach = [ {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, @@ -1037,41 +1037,55 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:3dfb23cc180b674a11a559183dff9655beb9da03088f3fe3c4f3a6d200c86f05"}, - {file = "coverage-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5dd5ae0a9cd55d71f1335c331e9625382239b8cede818fb62d8d2702336dbf8"}, - {file = "coverage-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8426fec5ad5a6e8217921716b504e9b6e1166dc147e8443b4855e329db686282"}, - {file = "coverage-6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aa5d4d43fa18cc9d0c6e02a83de0b9729b5451a9066574bd276481474f0a53ab"}, - {file = "coverage-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78dd3eeb8f5ff26d2113c41836bac04a9ea91be54c346826b54a373133c8c53"}, - {file = "coverage-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:581fddd2f883379bd5af51da9233e0396b6519f3d3eeae4fb88867473be6d56e"}, - {file = "coverage-6.0-cp310-cp310-win32.whl", hash = "sha256:43bada49697a62ffa0283c7f01bbc76aac562c37d4bb6c45d56dd008d841194e"}, - {file = "coverage-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa816e97cfe1f691423078dffa39a18106c176f28008db017b3ce3e947c34aa5"}, - {file = "coverage-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5c191e01b23e760338f19d8ba2470c0dad44c8b45e41ac043b2db84efc62f695"}, - {file = "coverage-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:274a612f67f931307706b60700f1e4cf80e1d79dff6c282fc9301e4565e78724"}, - {file = "coverage-6.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9dbfcbc56d8de5580483cf2caff6a59c64d3e88836cbe5fb5c20c05c29a8808"}, - {file = "coverage-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e63490e8a6675cee7a71393ee074586f7eeaf0e9341afd006c5d6f7eec7c16d7"}, - {file = "coverage-6.0-cp36-cp36m-win32.whl", hash = "sha256:72f8c99f1527c5a8ee77c890ea810e26b39fd0b4c2dffc062e20a05b2cca60ef"}, - {file = "coverage-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:88f1810eb942e7063d051d87aaaa113eb5fd5a7fd2cda03a972de57695b8bb1a"}, - {file = "coverage-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:befb5ffa9faabef6dadc42622c73de168001425258f0b7e402a2934574e7a04b"}, - {file = "coverage-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7dbda34e8e26bd86606ba8a9c13ccb114802e01758a3d0a75652ffc59a573220"}, - {file = "coverage-6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b4ee5815c776dfa3958ba71c7cd4cdd8eb40d79358a18352feb19562fe4408c4"}, - {file = "coverage-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d82cbef1220703ce56822be7fbddb40736fc1a928ac893472df8aff7421ae0aa"}, - {file = "coverage-6.0-cp37-cp37m-win32.whl", hash = "sha256:d795a2c92fe8cb31f6e9cd627ee4f39b64eb66bf47d89d8fcf7cb3d17031c887"}, - {file = "coverage-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6e216e4021c934246c308fd3e0d739d9fa8a3f4ea414f584ab90ef9c1592f282"}, - {file = "coverage-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8305e14112efb74d0b5fec4df6e41cafde615c2392a7e51c84013cafe945842c"}, - {file = "coverage-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4865dc4a7a566147cbdc2b2f033a6cccc99a7dcc89995137765c384f6c73110b"}, - {file = "coverage-6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:25df2bc53a954ba2ccf230fa274d1de341f6aa633d857d75e5731365f7181749"}, - {file = "coverage-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:08fd55d2e00dac4c18a2fa26281076035ec86e764acdc198b9185ce749ada58f"}, - {file = "coverage-6.0-cp38-cp38-win32.whl", hash = "sha256:11ce082eb0f7c2bbfe96f6c8bcc3a339daac57de4dc0f3186069ec5c58da911c"}, - {file = "coverage-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:7844a8c6a0fee401edbf578713c2473e020759267c40261b294036f9d3eb6a2d"}, - {file = "coverage-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bea681309bdd88dd1283a8ba834632c43da376d9bce05820826090aad80c0126"}, - {file = "coverage-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e735ab8547d8a1fe8e58dd765d6f27ac539b395f52160d767b7189f379f9be7a"}, - {file = "coverage-6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7593a49300489d064ebb6c58539f52cbbc4a2e6a4385de5e92cae1563f88a425"}, - {file = "coverage-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adb0f4c3c8ba8104378518a1954cbf3d891a22c13fd0e0bf135391835f44f288"}, - {file = "coverage-6.0-cp39-cp39-win32.whl", hash = "sha256:8da0c4a26a831b392deaba5fdd0cd7838d173b47ce2ec3d0f37be630cb09ef6e"}, - {file = "coverage-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:7af2f8e7bb54ace984de790e897f858e88068d8fbc46c9490b7c19c59cf51822"}, - {file = "coverage-6.0-pp36-none-any.whl", hash = "sha256:82b58d37c47d93a171be9b5744bcc96a0012cbf53d5622b29a49e6be2097edd7"}, - {file = "coverage-6.0-pp37-none-any.whl", hash = "sha256:fff04bfefb879edcf616f1ce5ea6f4a693b5976bdc5e163f8464f349c25b59f0"}, - {file = "coverage-6.0.tar.gz", hash = "sha256:17983f6ccc47f4864fd16d20ff677782b23d1207bf222d10e4d676e4636b0872"}, + {file = "coverage-6.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42a1fb5dee3355df90b635906bb99126faa7936d87dfc97eacc5293397618cb7"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a00284dbfb53b42e35c7dd99fc0e26ef89b4a34efff68078ed29d03ccb28402a"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:51a441011a30d693e71dea198b2a6f53ba029afc39f8e2aeb5b77245c1b282ef"}, + {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e76f017b6d4140a038c5ff12be1581183d7874e41f1c0af58ecf07748d36a336"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7833c872718dc913f18e51ee97ea0dece61d9930893a58b20b3daf09bb1af6b6"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8186b5a4730c896cbe1e4b645bdc524e62d874351ae50e1db7c3e9f5dc81dc26"}, + {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbca34dca5a2d60f81326d908d77313816fad23d11b6069031a3d6b8c97a54f9"}, + {file = "coverage-6.1.1-cp310-cp310-win32.whl", hash = "sha256:72bf437d54186d104388cbae73c9f2b0f8a3e11b6e8d7deb593bd14625c96026"}, + {file = "coverage-6.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:994ce5a7b3d20981b81d83618aa4882f955bfa573efdbef033d5632b58597ba9"}, + {file = "coverage-6.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ab6a0fe4c96f8058d41948ddf134420d3ef8c42d5508b5a341a440cce7a37a1d"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10ab138b153e4cc408b43792cb7f518f9ee02f4ff55cd1ab67ad6fd7e9905c7e"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7e083d32965d2eb6638a77e65b622be32a094fdc0250f28ce6039b0732fbcaa8"}, + {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:359a32515e94e398a5c0fa057e5887a42e647a9502d8e41165cf5cb8d3d1ca67"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:bf656cd74ff7b4ed7006cdb2a6728150aaad69c7242b42a2a532f77b63ea233f"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dc5023be1c2a8b0a0ab5e31389e62c28b2453eb31dd069f4b8d1a0f9814d951a"}, + {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:557594a50bfe3fb0b1b57460f6789affe8850ad19c1acf2d14a3e12b2757d489"}, + {file = "coverage-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:9eb0a1923354e0fdd1c8a6f53f5db2e6180d670e2b587914bf2e79fa8acfd003"}, + {file = "coverage-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:04a92a6cf9afd99f9979c61348ec79725a9f9342fb45e63c889e33c04610d97b"}, + {file = "coverage-6.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:479228e1b798d3c246ac89b09897ee706c51b3e5f8f8d778067f38db73ccc717"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78287731e3601ea5ce9d6468c82d88a12ef8fe625d6b7bdec9b45d96c1ad6533"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c95257aa2ccf75d3d91d772060538d5fea7f625e48157f8ca44594f94d41cb33"}, + {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9ad5895938a894c368d49d8470fe9f519909e5ebc6b8f8ea5190bd0df6aa4271"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:326d944aad0189603733d646e8d4a7d952f7145684da973c463ec2eefe1387c2"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e7d5606b9240ed4def9cbdf35be4308047d11e858b9c88a6c26974758d6225ce"}, + {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:572f917267f363101eec375c109c9c1118037c7cc98041440b5eabda3185ac7b"}, + {file = "coverage-6.1.1-cp37-cp37m-win32.whl", hash = "sha256:35cd2230e1ed76df7d0081a997f0fe705be1f7d8696264eb508076e0d0b5a685"}, + {file = "coverage-6.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:65ad3ff837c89a229d626b8004f0ee32110f9bfdb6a88b76a80df36ccc60d926"}, + {file = "coverage-6.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:977ce557d79577a3dd510844904d5d968bfef9489f512be65e2882e1c6eed7d8"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62512c0ec5d307f56d86504c58eace11c1bc2afcdf44e3ff20de8ca427ca1d0e"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2e5b9c17a56b8bf0c0a9477fcd30d357deb486e4e1b389ed154f608f18556c8a"}, + {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:666c6b32b69e56221ad1551d377f718ed00e6167c7a1b9257f780b105a101271"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fb2fa2f6506c03c48ca42e3fe5a692d7470d290c047ee6de7c0f3e5fa7639ac9"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f0f80e323a17af63eac6a9db0c9188c10f1fd815c3ab299727150cc0eb92c7a4"}, + {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:738e823a746841248b56f0f3bd6abf3b73af191d1fd65e4c723b9c456216f0ad"}, + {file = "coverage-6.1.1-cp38-cp38-win32.whl", hash = "sha256:8605add58e6a960729aa40c0fd9a20a55909dd9b586d3e8104cc7f45869e4c6b"}, + {file = "coverage-6.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:6e994003e719458420e14ffb43c08f4c14990e20d9e077cb5cad7a3e419bbb54"}, + {file = "coverage-6.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3c4f5211394cd0bf6874ac5d29684a495f9c374919833dcfff0bd6d37f96201"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e14bceb1f3ae8a14374be2b2d7bc12a59226872285f91d66d301e5f41705d4d6"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0147f7833c41927d84f5af9219d9b32f875c0689e5e74ac8ca3cb61e73a698f9"}, + {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1d0a1bce919de0dd8da5cff4e616b2d9e6ebf3bd1410ff645318c3dd615010a"}, + {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae6de0e41f44794e68d23644636544ed8003ce24845f213b24de097cbf44997f"}, + {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2797ed7a7e883b9ab76e8e778bb4c859fc2037d6fd0644d8675e64d58d1653"}, + {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c40966b683d92869b72ea3c11fd6b99a091fd30e12652727eca117273fc97366"}, + {file = "coverage-6.1.1-cp39-cp39-win32.whl", hash = "sha256:a11a2c019324fc111485e79d55907e7289e53d0031275a6c8daed30690bc50c0"}, + {file = "coverage-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4d8b453764b9b26b0dd2afb83086a7c3f9379134e340288d2a52f8a91592394b"}, + {file = "coverage-6.1.1-pp36-none-any.whl", hash = "sha256:3b270c6b48d3ff5a35deb3648028ba2643ad8434b07836782b1139cf9c66313f"}, + {file = "coverage-6.1.1-pp37-none-any.whl", hash = "sha256:ffa8fee2b1b9e60b531c4c27cf528d6b5d5da46b1730db1f4d6eee56ff282e07"}, + {file = "coverage-6.1.1-pp38-none-any.whl", hash = "sha256:4cd919057636f63ab299ccb86ea0e78b87812400c76abab245ca385f17d19fb5"}, + {file = "coverage-6.1.1.tar.gz", hash = "sha256:b8e4f15b672c9156c1154249a9c5746e86ac9ae9edc3799ee3afebc323d9d9e0"}, ] dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, @@ -1147,6 +1161,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, @@ -1158,6 +1175,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1169,6 +1189,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, @@ -1181,6 +1204,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1193,6 +1219,9 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1370,24 +1399,32 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1395,6 +1432,8 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, diff --git a/pyproject.toml b/pyproject.toml index 6d1d265b13..f207621ab1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ jupyter = ["ipywidgets"] [tool.poetry.dev-dependencies] pytest = "^6.2.5" -black = "^21.9b0" +black = "^21.10b0" mypy = "^0.910" pytest-cov = "^3.0.0" attrs = "^21.2.0" From e2b704f2034c2d8fbba651ef0b4d20b204a58dfa Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 1 Nov 2021 13:17:20 -0700 Subject: [PATCH 059/287] Have logger link to proper file line. Some terminal emulators like iterm2, support anchoring to the line number: https://iterm2.com/documentation-one-page.html see Anchor (OSC 8) section: Note: in iTerm2 version 3.4 and later, if the URL has the file scheme and a # fragment is present then the semantic history rules will apply for opening the file. It may optionally include a line number, like file:///tmp/file.txt#123 or line number and column number like file:///tmp/file.txt#123:45 This update the logic in the logger so that the line number links the the corresponding file on the same line. As I'm not sure whether all terminals support that, I let the clik on the file name point to the file itself w/o line numbers. And for discoverability and user friendliness the colon itself is unstyled so that it's easier to discover that click on the filename and line number are two different targets. --- rich/_log_render.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rich/_log_render.py b/rich/_log_render.py index 3a77f0c876..e8810100b3 100644 --- a/rich/_log_render.py +++ b/rich/_log_render.py @@ -75,7 +75,11 @@ def __call__( path, style=f"link file://{link_path}" if link_path else "" ) if line_no: - path_text.append(f":{line_no}") + path_text.append(":") + path_text.append( + f"{line_no}", + style=f"link file://{link_path}#{line_no}" if link_path else "", + ) row.append(path_text) output.add_row(*row) From e1c105b8f0ab182dae6814b632bc80acc5c6090f Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 10:26:02 +0000 Subject: [PATCH 060/287] fix detect color --- rich/console.py | 2 +- tests/test_console.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index 7c4be7fcf8..b188dc98e0 100644 --- a/rich/console.py +++ b/rich/console.py @@ -770,7 +770,7 @@ def _detect_color_system(self) -> Optional[ColorSystem]: if color_term in ("truecolor", "24bit"): return ColorSystem.TRUECOLOR term = self._environ.get("TERM", "").strip().lower() - _term_name, _hyphen, colors = term.partition("-") + _term_name, _hyphen, colors = term.rpartition("-") color_system = _TERM_COLORS.get(colors, ColorSystem.STANDARD) return color_system diff --git a/tests/test_console.py b/tests/test_console.py index 0f88436ca8..fe3ce5b0db 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -709,3 +709,9 @@ def _mock_isatty(): console.file.isatty = _mock_isatty assert console.is_terminal == False + + +@pytest.mark.skipif(sys.platform == "win32", reason="not relevant on Windows") +def test_detect_color_system(): + console = Console(_environ={"TERM": "rxvt-unicode-256color"}, force_terminal=True) + assert console._detect_color_system() == ColorSystem.EIGHT_BIT \ No newline at end of file From 470a52130b1b13720dad6dfe71e762c5c96bca2b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 10:55:10 +0000 Subject: [PATCH 061/287] Added json.dumps parameters --- CHANGELOG.md | 7 ++++++- pyproject.toml | 2 +- rich/__init__.py | 28 +++++++++++++++++++++++-- rich/console.py | 25 +++++++++++++++++++++- rich/json.py | 54 +++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 108 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8f4baa10..7e0012015f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,16 @@ 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.12.1] - unreleased +## [10.13.0] - unreleased + +### Added + +- Added json.dumps parameters to print_json https://github.com/willmcgugan/rich/issues/1638 ### Fixed - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run +- Fixed issue with TERM env vars that have more than one hyphen https://github.com/willmcgugan/rich/issues/1640 ## [10.12.0] - 2021-10-06 diff --git a/pyproject.toml b/pyproject.toml index 6d1d265b13..de5d216416 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.12.0" +version = "10.13.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/__init__.py b/rich/__init__.py index 604fa04cf5..ed11f5d7ea 100644 --- a/rich/__init__.py +++ b/rich/__init__.py @@ -1,7 +1,7 @@ """Rich text and beautiful formatting in the terminal.""" import os -from typing import IO, TYPE_CHECKING, Any, Optional +from typing import Callable, IO, TYPE_CHECKING, Any, Optional from ._extension import load_ipython_extension @@ -75,6 +75,12 @@ def print_json( data: Any = None, indent: int = 2, highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = True, + check_circular: bool = True, + allow_nan: bool = True, + default: Optional[Callable[[Any], Any]] = None, + sort_keys: bool = False, ) -> None: """Pretty prints JSON. Output will be valid JSON. @@ -83,9 +89,27 @@ def print_json( data (Any): If json is not supplied, then encode this data. indent (int, optional): Number of spaces to indent. Defaults to 2. highlight (bool, optional): Enable highlighting of output: Defaults to True. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. """ - get_console().print_json(json, data=data, indent=indent, highlight=highlight) + get_console().print_json( + json, + data=data, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) def inspect( diff --git a/rich/console.py b/rich/console.py index b188dc98e0..e903ab2541 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1627,6 +1627,12 @@ def print_json( data: Any = None, indent: int = 2, highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = True, + check_circular: bool = True, + allow_nan: bool = True, + default: Optional[Callable] = None, + sort_keys: bool = False, ) -> None: """Pretty prints JSON. Output will be valid JSON. @@ -1635,11 +1641,28 @@ def print_json( data (Any): If json is not supplied, then encode this data. indent (int, optional): Number of spaces to indent. Defaults to 2. highlight (bool, optional): Enable highlighting of output: Defaults to True. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. """ from rich.json import JSON if json is None: - json_renderable = JSON.from_data(data, indent=indent, highlight=highlight) + json_renderable = JSON.from_data( + data, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) else: if not isinstance(json, str): raise TypeError( diff --git a/rich/json.py b/rich/json.py index a63f1754d3..4f3199fd12 100644 --- a/rich/json.py +++ b/rich/json.py @@ -12,11 +12,38 @@ class JSON: json (str): JSON encoded data. indent (int, optional): Number of characters to indent by. Defaults to 2. highlight (bool, optional): Enable highlighting. Defaults to True. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. """ - def __init__(self, json: str, indent: int = 2, highlight: bool = True) -> None: + def __init__( + self, + json: str, + indent: int = 2, + highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = True, + check_circular: bool = True, + allow_nan: bool = True, + default: Optional[Callable[[Any], Any]] = None, + sort_keys: bool = False, + ) -> None: data = loads(json) - json = dumps(data, indent=indent) + json = dumps( + data, + indent=indent, + skipkeys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) highlighter = JSONHighlighter() if highlight else NullHighlighter() self.text = highlighter(json) self.text.no_wrap = True @@ -28,7 +55,12 @@ def from_data( data: Any, indent: int = 2, highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = True, + check_circular: bool = True, + allow_nan: bool = True, default: Optional[Callable[[Any], Any]] = None, + sort_keys: bool = False, ) -> "JSON": """Encodes a JSON object from arbitrary data. @@ -37,12 +69,28 @@ def from_data( indent (int, optional): Number of characters to indent by. Defaults to 2. highlight (bool, optional): Enable highlighting. Defaults to True. default (Callable, optional): Optional callable which will be called for objects that cannot be serialized. Defaults to None. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. Returns: JSON: New JSON object from the given data. """ json_instance: "JSON" = cls.__new__(cls) - json = dumps(data, indent=indent, default=default) + json = dumps( + data, + indent=indent, + skipkeys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) highlighter = JSONHighlighter() if highlight else NullHighlighter() json_instance.text = highlighter(json) json_instance.text.no_wrap = True From 856a6edb36ed3365e310352b2c6b2937b4d4caa3 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 10:56:46 +0000 Subject: [PATCH 062/287] typing --- rich/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index e903ab2541..6edd7c8afd 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1631,7 +1631,7 @@ def print_json( ensure_ascii: bool = True, check_circular: bool = True, allow_nan: bool = True, - default: Optional[Callable] = None, + default: Optional[Callable[[Any], Any]] = None, sort_keys: bool = False, ) -> None: """Pretty prints JSON. Output will be valid JSON. From 8cf9b684f3d2ea2553f5cd98fb642a221968e5f5 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 10:59:01 +0000 Subject: [PATCH 063/287] formatting --- tests/test_console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_console.py b/tests/test_console.py index fe3ce5b0db..202ad0a550 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -714,4 +714,4 @@ def _mock_isatty(): @pytest.mark.skipif(sys.platform == "win32", reason="not relevant on Windows") def test_detect_color_system(): console = Console(_environ={"TERM": "rxvt-unicode-256color"}, force_terminal=True) - assert console._detect_color_system() == ColorSystem.EIGHT_BIT \ No newline at end of file + assert console._detect_color_system() == ColorSystem.EIGHT_BIT From 5d601fabc3eac968c9b6962f0690e7bb4b0de74e Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 11:09:03 +0000 Subject: [PATCH 064/287] pass dumps params --- rich/console.py | 12 +++++++++++- tests/test_console.py | 9 +++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index 6edd7c8afd..8abc382fed 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1668,7 +1668,17 @@ def print_json( raise TypeError( f"json must be str. Did you mean print_json(data={json!r}) ?" ) - json_renderable = JSON(json, indent=indent, highlight=highlight) + json_renderable = JSON( + json, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) self.print(json_renderable) def update_screen( diff --git a/tests/test_console.py b/tests/test_console.py index 202ad0a550..6660ec9d17 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -141,6 +141,15 @@ def test_print_json_data(): assert result == expected +def test_print_json_ensure_ascii(): + console = Console(file=io.StringIO(), color_system="truecolor") + console.print_json(data={"foo": "💩"}, ensure_ascii=False) + result = console.file.getvalue() + print(repr(result)) + expected = '\x1b[1m{\x1b[0m\n \x1b[1;34m"foo"\x1b[0m: \x1b[32m"💩"\x1b[0m\n\x1b[1m}\x1b[0m\n' + assert result == expected + + def test_log(): console = Console( file=io.StringIO(), From d598f3717429b59c84acd6bd78951396f1e27d0f Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 5 Nov 2021 16:58:04 +0000 Subject: [PATCH 065/287] fix line endings --- rich/__main__.py | 4 ++-- rich/console.py | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/rich/__main__.py b/rich/__main__.py index 66ae166ba4..df084b69a2 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -231,8 +231,8 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: text = console.file.getvalue() # https://bugs.python.org/issue37871 - for line in text.splitlines(): - print(line) + for line in text.splitlines(True): + print(line, end="") print(f"rendered in {taken}ms") diff --git a/rich/console.py b/rich/console.py index 8abc382fed..ac1d34c465 100644 --- a/rich/console.py +++ b/rich/console.py @@ -941,7 +941,7 @@ def size(self) -> ConsoleDimensions: """ if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width, self._height) + return ConsoleDimensions(self._width - self.legacy_windows, self._height) if self.is_dumb_terminal: return ConsoleDimensions(80, 25) @@ -963,7 +963,7 @@ def size(self) -> ConsoleDimensions: width = width or 80 height = height or 25 return ConsoleDimensions( - (width - self.legacy_windows) if self._width is None else self._width, + (width if self._width is None else self._width) - self.legacy_windows, height if self._height is None else self._height, ) @@ -1904,9 +1904,7 @@ def _check_buffer(self) -> None: try: if WINDOWS: # pragma: no cover # https://bugs.python.org/issue37871 - write = self.file.write - for line in text.splitlines(True): - write(line) + self.file.writelines(text.splitlines(True)) else: self.file.write(text) self.file.flush() From dff665e33c8184d4129e44974ded279a13f7154e Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 6 Nov 2021 12:16:21 +0000 Subject: [PATCH 066/287] allow disable pprint --- CHANGELOG.md | 1 + rich/pretty.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e0012015f..aac8e88349 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run - Fixed issue with TERM env vars that have more than one hyphen https://github.com/willmcgugan/rich/issues/1640 +- Fixed exception in IPython when disabling pprint with %pprint https://github.com/willmcgugan/rich/issues/1646 ## [10.12.0] - 2021-10-06 diff --git a/rich/pretty.py b/rich/pretty.py index e37b766dd8..bf7e55f4ca 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -166,9 +166,17 @@ def ipy_display_hook(value: Any) -> None: # pragma: no cover ip = get_ipython() # type: ignore from IPython.core.formatters import BaseFormatter + class RichFormatter(BaseFormatter): + pprint: bool = True + + def __call__(self, value: Any) -> Any: + if self.pprint: + return ipy_display_hook(value) + else: + return repr(value) + # replace plain text formatter with rich formatter - rich_formatter = BaseFormatter() - rich_formatter.for_type(object, func=ipy_display_hook) + rich_formatter = RichFormatter() ip.display_formatter.formatters["text/plain"] = rich_formatter except Exception: sys.displayhook = display_hook From f5f67a9ebb494dd65ad3eeb3437567e9da44d559 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 6 Nov 2021 12:27:32 +0000 Subject: [PATCH 067/287] fix for missing newline --- CHANGELOG.md | 1 + rich/live.py | 2 ++ tests/test_live.py | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e0012015f..933a703dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run - Fixed issue with TERM env vars that have more than one hyphen https://github.com/willmcgugan/rich/issues/1640 +- Fixed missing new line after progress bar when terminal is not interactive https://github.com/willmcgugan/rich/issues/1606 ## [10.12.0] - 2021-10-06 diff --git a/rich/live.py b/rich/live.py index 8097f7d2e6..cb36ddb8d7 100644 --- a/rich/live.py +++ b/rich/live.py @@ -159,6 +159,8 @@ def stop(self) -> None: # jupyter last refresh must occur after console pop render hook # i am not sure why this is needed self.refresh() + if not self.console.is_interactive: + return self.console.print() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) diff --git a/tests/test_live.py b/tests/test_live.py index 0c732f63ba..80002e549b 100644 --- a/tests/test_live.py +++ b/tests/test_live.py @@ -158,7 +158,7 @@ def test_growing_display_file_console() -> None: output = console.end_capture() assert ( output - == "Step 0\nStep 1\nStep 2\nStep 3\nStep 4\nStep 5\nStep 6\nStep 7\nStep 8\nStep 9\n" + == "Step 0\nStep 1\nStep 2\nStep 3\nStep 4\nStep 5\nStep 6\nStep 7\nStep 8\nStep 9\n\n" ) From 9ba8c70257ee16e3528f1fef91463e8ac2bee765 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 6 Nov 2021 12:31:23 +0000 Subject: [PATCH 068/287] fix typing --- rich/pretty.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/pretty.py b/rich/pretty.py index bf7e55f4ca..650a886a8a 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -166,7 +166,7 @@ def ipy_display_hook(value: Any) -> None: # pragma: no cover ip = get_ipython() # type: ignore from IPython.core.formatters import BaseFormatter - class RichFormatter(BaseFormatter): + class RichFormatter(BaseFormatter): # type: ignore pprint: bool = True def __call__(self, value: Any) -> Any: From 25decd0f4aa4fec0e1e85e268ce9fac522f70848 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 6 Nov 2021 12:43:27 +0000 Subject: [PATCH 069/287] legacy windows fix --- rich/console.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/console.py b/rich/console.py index ac1d34c465..3b08e39497 100644 --- a/rich/console.py +++ b/rich/console.py @@ -941,7 +941,7 @@ def size(self) -> ConsoleDimensions: """ if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width - self.legacy_windows, self._height) + return ConsoleDimensions(self._width, self._height) if self.is_dumb_terminal: return ConsoleDimensions(80, 25) @@ -963,7 +963,7 @@ def size(self) -> ConsoleDimensions: width = width or 80 height = height or 25 return ConsoleDimensions( - (width if self._width is None else self._width) - self.legacy_windows, + ((width - self.legacy_windows) if self._width is None else self._width), height if self._height is None else self._height, ) From 6f5f9125e7c4a850b8fb3e664d0747c88dfc9dc1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Nov 2021 13:07:35 +0000 Subject: [PATCH 070/287] Bump types-dataclasses from 0.1.7 to 0.6.1 Bumps [types-dataclasses](https://github.com/python/typeshed) from 0.1.7 to 0.6.1. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-dataclasses dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 11 ++++------- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index ac178ccaa5..2e0c7d92d3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -874,7 +874,7 @@ python-versions = "*" [[package]] name = "types-dataclasses" -version = "0.1.7" +version = "0.6.1" description = "Typing stubs for dataclasses" category = "dev" optional = false @@ -933,7 +933,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "0434c898cb68444014e1d0f00cb88d10df9a26641016cd123da2d5c7cf3c014e" +content-hash = "8bdb5487831da15eafc51dcd67177f13cc7d498f8cac62b80c60988a85f75ce4" [metadata.files] appnope = [ @@ -1077,9 +1077,6 @@ coverage = [ {file = "coverage-6.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e14bceb1f3ae8a14374be2b2d7bc12a59226872285f91d66d301e5f41705d4d6"}, {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0147f7833c41927d84f5af9219d9b32f875c0689e5e74ac8ca3cb61e73a698f9"}, {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1d0a1bce919de0dd8da5cff4e616b2d9e6ebf3bd1410ff645318c3dd615010a"}, - {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae6de0e41f44794e68d23644636544ed8003ce24845f213b24de097cbf44997f"}, - {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2797ed7a7e883b9ab76e8e778bb4c859fc2037d6fd0644d8675e64d58d1653"}, - {file = "coverage-6.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c40966b683d92869b72ea3c11fd6b99a091fd30e12652727eca117273fc97366"}, {file = "coverage-6.1.1-cp39-cp39-win32.whl", hash = "sha256:a11a2c019324fc111485e79d55907e7289e53d0031275a6c8daed30690bc50c0"}, {file = "coverage-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4d8b453764b9b26b0dd2afb83086a7c3f9379134e340288d2a52f8a91592394b"}, {file = "coverage-6.1.1-pp36-none-any.whl", hash = "sha256:3b270c6b48d3ff5a35deb3648028ba2643ad8434b07836782b1139cf9c66313f"}, @@ -1589,8 +1586,8 @@ typed-ast = [ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] types-dataclasses = [ - {file = "types-dataclasses-0.1.7.tar.gz", hash = "sha256:248075d093d8f7c1541ce515594df7ae40233d1340afde11ce7125368c5209b8"}, - {file = "types_dataclasses-0.1.7-py3-none-any.whl", hash = "sha256:fc372bb68b878ac7a68fd04230d923d4a6303a137ecb0b9700b90630bdfcbfc9"}, + {file = "types-dataclasses-0.6.1.tar.gz", hash = "sha256:6568532fed11f854e4db2eb48063385b323b93ecadd09f10a215d56246c306d7"}, + {file = "types_dataclasses-0.6.1-py3-none-any.whl", hash = "sha256:aa45bb0dacdba09e3195a36ff8337bba45eac03b6f31c4645e87b4a2a47830dd"}, ] typing-extensions = [ {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, diff --git a/pyproject.toml b/pyproject.toml index 05d9ab86b4..b42f91a29f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ black = "^21.10b0" mypy = "^0.910" pytest-cov = "^3.0.0" attrs = "^21.2.0" -types-dataclasses = "^0.1.7" +types-dataclasses = "^0.6.1" [build-system] requires = ["poetry-core>=1.0.0"] From 316be7bf67715410ad64ea497688bf93b5e92b88 Mon Sep 17 00:00:00 2001 From: James Estevez Date: Sat, 6 Nov 2021 11:49:33 -0700 Subject: [PATCH 071/287] Values exceeding the console's width break print_json --- tests/test_rich_print.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_rich_print.py b/tests/test_rich_print.py index f6ea5110d8..a92b800022 100644 --- a/tests/test_rich_print.py +++ b/tests/test_rich_print.py @@ -1,4 +1,5 @@ import io +import json import rich from rich.console import Console @@ -38,6 +39,27 @@ def test_rich_print_json(): assert result == expected +def test_rich_print_json_round_trip(): + data = ["x" * 100, 2e128] + console = rich.get_console() + with console.capture() as capture: + rich.print_json(data=data, indent=4) + result = capture.get() + print(repr(result)) + result_data = json.loads(result) + assert result_data == data + + +def test_rich_print_json_no_truncation(): + console = rich.get_console() + with console.capture() as capture: + rich.print_json(f'["{"x" * 100}", {int(2e128)}]', indent=4) + result = capture.get() + print(repr(result)) + assert ("x" * 100) in result + assert str(int(2e128)) in result + + def test_rich_print_X(): console = rich.get_console() output = io.StringIO() From 3ee35156de58624fe9976eead3ab52d82f7205b2 Mon Sep 17 00:00:00 2001 From: James Estevez Date: Sat, 6 Nov 2021 11:51:24 -0700 Subject: [PATCH 072/287] Add soft_wrap=True to print_json This commit adds soft_wrap=True to the invocation of print in print_json. Without it, values wider than the console's width are truncated, and the output will not be valid JSON. --- rich/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index 3b08e39497..4764e0bd39 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1679,7 +1679,7 @@ def print_json( default=default, sort_keys=sort_keys, ) - self.print(json_renderable) + self.print(json_renderable, soft_wrap=True) def update_screen( self, From af9ff73612f05c80a03948db79fc8c04b10ff1f3 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Sat, 6 Nov 2021 12:12:23 -0700 Subject: [PATCH 073/287] fix test with line numbers --- tests/test_log.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/test_log.py b/tests/test_log.py index 84da7a4458..b78b58eafc 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -6,8 +6,7 @@ from rich.console import Console - -re_link_ids = re.compile(r"id=[\d\.\-]*?;.*?\x1b") +re_link_ids = re.compile(r"id=((\d+);(file:///(\w+\/)+(\w+\.py)(#\d+)?))\x1b") def replace_link_ids(render: str) -> str: @@ -15,7 +14,7 @@ def replace_link_ids(render: str) -> str: reproducible tests. """ - return re_link_ids.sub("id=0;foo\x1b", render) + return re_link_ids.sub("id=0;file:///path/to/source.py#00\x1b", render) test_data = [1, 2, 3] @@ -33,13 +32,11 @@ def render_log(): console.log() console.log("Hello from", console, "!") console.log(test_data, log_locals=True) - return replace_link_ids(console.file.getvalue()) + return replace_link_ids(console.file.getvalue()).replace('test_log.py','source.py') def test_log(): - expected = replace_link_ids( - "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2mtest_log.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:33\x1b[0m\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2mtest_log.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:34\x1b[0m\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2mtest_log.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:35\x1b[0m\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n" - ) + expected = replace_link_ids('\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m32\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n') rendered = render_log() print(repr(rendered)) assert rendered == expected From 07c6733027ef45dd1e2fef409522bfe7924bb7de Mon Sep 17 00:00:00 2001 From: James Estevez Date: Sat, 6 Nov 2021 12:02:16 -0700 Subject: [PATCH 074/287] Update changelog --- CHANGELOG.md | 1 + CONTRIBUTORS.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0dad5b3b..4d5c729dde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed issue with TERM env vars that have more than one hyphen https://github.com/willmcgugan/rich/issues/1640 - Fixed missing new line after progress bar when terminal is not interactive https://github.com/willmcgugan/rich/issues/1606 - Fixed exception in IPython when disabling pprint with %pprint https://github.com/willmcgugan/rich/issues/1646 +- Fixed issue where values longer than the console width produced invalid JSON https://github.com/willmcgugan/rich/issues/1653 ## [10.12.0] - 2021-10-06 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ad5147afc2..ba0c7d6713 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -6,6 +6,7 @@ The following people have contributed to the development of Rich: - [Gregory Beauregard](https://github.com/GBeauregard/pyffstream) - [Pete Davison](https://github.com/pd93) +- [James Estevez](https://github.com/jstvz) - [Oleksis Fraga](https://github.com/oleksis) - [Finn Hughes](https://github.com/finnhughes) - [Josh Karpel](https://github.com/JoshKarpel) From fcbeffcfa1cc3950fb63a01add0a1ad5a03ce25a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 15:02:39 +0000 Subject: [PATCH 075/287] formatting --- tests/test_log.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_log.py b/tests/test_log.py index b78b58eafc..e0b4682e58 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -32,11 +32,13 @@ def render_log(): console.log() console.log("Hello from", console, "!") console.log(test_data, log_locals=True) - return replace_link_ids(console.file.getvalue()).replace('test_log.py','source.py') + return replace_link_ids(console.file.getvalue()).replace("test_log.py", "source.py") def test_log(): - expected = replace_link_ids('\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m32\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n') + expected = replace_link_ids( + "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m32\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n" + ) rendered = render_log() print(repr(rendered)) assert rendered == expected From 9762a2f1168182585c425a22a146f0d3bf68a5be Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 15:13:38 +0000 Subject: [PATCH 076/287] word wrap code blocks --- CHANGELOG.md | 4 ++++ rich/markdown.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97b6522478..fd5e4e843b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed exception in IPython when disabling pprint with %pprint https://github.com/willmcgugan/rich/issues/1646 - Fixed issue where values longer than the console width produced invalid JSON https://github.com/willmcgugan/rich/issues/1653 +## Changed + +- Markdown codeblocks now word-wrap https://github.com/willmcgugan/rich/issues/1515 + ## [10.12.0] - 2021-10-06 ### Updated diff --git a/rich/markdown.py b/rich/markdown.py index 35ac28c1c2..92d0d3c010 100644 --- a/rich/markdown.py +++ b/rich/markdown.py @@ -177,7 +177,7 @@ def __rich_console__( ) -> RenderResult: code = str(self.text).rstrip() syntax = Panel( - Syntax(code, self.lexer_name, theme=self.theme), + Syntax(code, self.lexer_name, theme=self.theme, word_wrap=True), border_style="dim", box=box.SQUARE, ) From 29b5c93a2d4a2f59a6c4cd950c4cc824504d20be Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 15:42:53 +0000 Subject: [PATCH 077/287] fix test --- tests/test_log.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_log.py b/tests/test_log.py index e0b4682e58..94a1f9e17b 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -6,7 +6,8 @@ from rich.console import Console -re_link_ids = re.compile(r"id=((\d+);(file:///(\w+\/)+(\w+\.py)(#\d+)?))\x1b") + +re_link_ids = re.compile(r"id=[\d\.\-]*?;.*?\x1b") def replace_link_ids(render: str) -> str: @@ -14,7 +15,7 @@ def replace_link_ids(render: str) -> str: reproducible tests. """ - return re_link_ids.sub("id=0;file:///path/to/source.py#00\x1b", render) + return re_link_ids.sub("id=0;foo\x1b", render) test_data = [1, 2, 3] @@ -37,7 +38,7 @@ def render_log(): def test_log(): expected = replace_link_ids( - "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m32\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;file:///path/to/foo.py#00\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n" + "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m35\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n" ) rendered = render_log() print(repr(rendered)) From 7657a8e8f90f8b4a1841fa7811d42d1fdd933af1 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 15:59:12 +0000 Subject: [PATCH 078/287] fix trailing comma --- CHANGELOG.md | 1 + rich/pretty.py | 2 +- tests/test_pretty.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd5e4e843b..935d00ae28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed missing new line after progress bar when terminal is not interactive https://github.com/willmcgugan/rich/issues/1606 - Fixed exception in IPython when disabling pprint with %pprint https://github.com/willmcgugan/rich/issues/1646 - Fixed issue where values longer than the console width produced invalid JSON https://github.com/willmcgugan/rich/issues/1653 +- Fixes trailing comma when pretty printing dataclass with last field repr=False https://github.com/willmcgugan/rich/issues/1599 ## Changed diff --git a/rich/pretty.py b/rich/pretty.py index 650a886a8a..0bf679461b 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -653,7 +653,7 @@ def iter_attrs() -> Iterable[ last=root, ) - for last, field in loop_last(fields(obj)): + for last, field in loop_last(field for field in fields(obj) if field.repr): if field.repr: child_node = _traverse(getattr(obj, field.name)) child_node.key_repr = field.name diff --git a/tests/test_pretty.py b/tests/test_pretty.py index faf276a1b7..9fd2bdd9d9 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -67,6 +67,7 @@ class ExampleDataclass: bar: str ignore: int = field(repr=False) baz: List[str] = field(default_factory=list) + last: int = field(default=1, repr=False) def test_pretty_dataclass(): From ac1a33da175972f895e894121df609d0cb1448fe Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 16:09:26 +0000 Subject: [PATCH 079/287] changelog bump --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935d00ae28..f05288274a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.13.0] - unreleased +## [10.13.0] - 2021-11-07 ### Added From 654f702ab7c1dbddc8ccca642fbdbdadf92b426b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 7 Nov 2021 16:26:11 +0000 Subject: [PATCH 080/287] remove superfluous test --- rich/pretty.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index 0bf679461b..7e916511a0 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -654,12 +654,11 @@ def iter_attrs() -> Iterable[ ) for last, field in loop_last(field for field in fields(obj) if field.repr): - if field.repr: - child_node = _traverse(getattr(obj, field.name)) - child_node.key_repr = field.name - child_node.last = last - child_node.key_separator = "=" - append(child_node) + child_node = _traverse(getattr(obj, field.name)) + child_node.key_repr = field.name + child_node.last = last + child_node.key_separator = "=" + append(child_node) pop_visited(obj_id) From a3f8e0467a7cf56feab59ee9e51b0b0369efc764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Sun, 7 Nov 2021 23:07:24 +0545 Subject: [PATCH 081/287] Make indent param in console.print_json compatible to json.dumps indent param --- rich/console.py | 4 ++-- rich/json.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/rich/console.py b/rich/console.py index ef3352f394..bae2f36a60 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1625,7 +1625,7 @@ def print_json( json: Optional[str] = None, *, data: Any = None, - indent: int = 2, + indent: Union[None, int, str] = 2, highlight: bool = True, skip_keys: bool = False, ensure_ascii: bool = True, @@ -1639,7 +1639,7 @@ def print_json( Args: json (Optional[str]): A string containing JSON. data (Any): If json is not supplied, then encode this data. - indent (int, optional): Number of spaces to indent. Defaults to 2. + indent (Union[None, int, str], optional): Number of spaces to indent. Defaults to 2. highlight (bool, optional): Enable highlighting of output: Defaults to True. skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. diff --git a/rich/json.py b/rich/json.py index 4f3199fd12..1fc115a952 100644 --- a/rich/json.py +++ b/rich/json.py @@ -1,5 +1,5 @@ from json import loads, dumps -from typing import Any, Callable, Optional +from typing import Any, Callable, Optional, Union from .text import Text from .highlighter import JSONHighlighter, NullHighlighter @@ -10,7 +10,7 @@ class JSON: Args: json (str): JSON encoded data. - indent (int, optional): Number of characters to indent by. Defaults to 2. + indent (Union[None, int, str], optional): Number of characters to indent by. Defaults to 2. highlight (bool, optional): Enable highlighting. Defaults to True. skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. @@ -24,7 +24,7 @@ class JSON: def __init__( self, json: str, - indent: int = 2, + indent: Union[None, int, str] = 2, highlight: bool = True, skip_keys: bool = False, ensure_ascii: bool = True, @@ -53,7 +53,7 @@ def __init__( def from_data( cls, data: Any, - indent: int = 2, + indent: Union[None, int, str] = 2, highlight: bool = True, skip_keys: bool = False, ensure_ascii: bool = True, @@ -66,7 +66,7 @@ def from_data( Args: data (Any): An object that may be encoded in to JSON - indent (int, optional): Number of characters to indent by. Defaults to 2. + indent (Union[None, int, str], optional): Number of characters to indent by. Defaults to 2. highlight (bool, optional): Enable highlighting. Defaults to True. default (Callable, optional): Optional callable which will be called for objects that cannot be serialized. Defaults to None. skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. From 59d351168e81506eff5e7d8f5746699d1e100044 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 16:30:25 +0000 Subject: [PATCH 082/287] new lines fixes --- CHANGELOG.md | 7 +++++++ rich/live.py | 2 -- rich/progress.py | 4 +++- tests/test_live.py | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f05288274a..804769d411 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ 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.13.1] - Unreleased + +### Fixed + +- Fixed progress speed not updating when total doesn't change +- Fixed superfluous new line in Status https://github.com/willmcgugan/rich/issues/1662 + ## [10.13.0] - 2021-11-07 ### Added diff --git a/rich/live.py b/rich/live.py index cb36ddb8d7..8097f7d2e6 100644 --- a/rich/live.py +++ b/rich/live.py @@ -159,8 +159,6 @@ def stop(self) -> None: # jupyter last refresh must occur after console pop render hook # i am not sure why this is needed self.refresh() - if not self.console.is_interactive: - return self.console.print() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) diff --git a/rich/progress.py b/rich/progress.py index 8f2ec02660..1f670db438 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -645,6 +645,8 @@ def start(self) -> None: def stop(self) -> None: """Stop the progress display.""" self.live.stop() + if not self.console.is_interactive: + self.console.print() def __enter__(self) -> "Progress": self.start() @@ -764,7 +766,7 @@ def update( task = self._tasks[task_id] completed_start = task.completed - if total is not None: + if total is not None and total != task.total: task.total = total task._reset() if advance is not None: diff --git a/tests/test_live.py b/tests/test_live.py index 80002e549b..0c732f63ba 100644 --- a/tests/test_live.py +++ b/tests/test_live.py @@ -158,7 +158,7 @@ def test_growing_display_file_console() -> None: output = console.end_capture() assert ( output - == "Step 0\nStep 1\nStep 2\nStep 3\nStep 4\nStep 5\nStep 6\nStep 7\nStep 8\nStep 9\n\n" + == "Step 0\nStep 1\nStep 2\nStep 3\nStep 4\nStep 5\nStep 6\nStep 7\nStep 8\nStep 9\n" ) From 2c09d7f1a2d69bc369d22c8dee19a8aa8d859cd6 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 16:46:15 +0000 Subject: [PATCH 083/287] win width fix --- rich/console.py | 5 +++-- rich/measure.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rich/console.py b/rich/console.py index bae2f36a60..e4335f98a5 100644 --- a/rich/console.py +++ b/rich/console.py @@ -941,13 +941,14 @@ def size(self) -> ConsoleDimensions: """ if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width, self._height) + return ConsoleDimensions(self._width - self.legacy_windows, self._height) if self.is_dumb_terminal: return ConsoleDimensions(80, 25) width: Optional[int] = None height: Optional[int] = None + if WINDOWS: # pragma: no cover width, height = shutil.get_terminal_size() else: @@ -963,7 +964,7 @@ def size(self) -> ConsoleDimensions: width = width or 80 height = height or 25 return ConsoleDimensions( - ((width - self.legacy_windows) if self._width is None else self._width), + (width if self._width is None else self._width) - self.legacy_windows, height if self._height is None else self._height, ) diff --git a/rich/measure.py b/rich/measure.py index b57aa9c85e..db54f294b0 100644 --- a/rich/measure.py +++ b/rich/measure.py @@ -130,12 +130,12 @@ def measure_renderables( Args: console (~rich.console.Console): Console instance. + options (~rich.console.ConsoleOptions): Console options. renderables (Iterable[RenderableType]): One or more renderable objects. - max_width (int): The maximum width available. Returns: Measurement: Measurement object containing range of character widths required to - contain all given renderables. + contain all given renderables. """ if not renderables: return Measurement(0, 0) From 77158a57ee33d740650e35307608ff8d1ee02c54 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 16:59:50 +0000 Subject: [PATCH 084/287] another width fix --- rich/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index bae2f36a60..74d6b66589 100644 --- a/rich/console.py +++ b/rich/console.py @@ -941,7 +941,7 @@ def size(self) -> ConsoleDimensions: """ if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width, self._height) + return ConsoleDimensions(self._width - self.legacy_windows, self._height) if self.is_dumb_terminal: return ConsoleDimensions(80, 25) From 743e649885ebd0cd4525dbafe0eec7c7ec315b01 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 17:03:02 +0000 Subject: [PATCH 085/287] verison bump --- CHANGELOG.md | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 804769d411..6ddd4b3f5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,13 @@ 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.13.1] - Unreleased +## [10.13.1] - 2021-11-09 ### Fixed - Fixed progress speed not updating when total doesn't change - Fixed superfluous new line in Status https://github.com/willmcgugan/rich/issues/1662 +- Fixed Windows legacy width again ## [10.13.0] - 2021-11-07 diff --git a/pyproject.toml b/pyproject.toml index b42f91a29f..9291b5a444 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.13.0" +version = "10.13.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From 84faaa898af831ddc1fef4d2da1556e44446911a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 17:36:50 +0000 Subject: [PATCH 086/287] subtract only auto-detect --- rich/console.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/rich/console.py b/rich/console.py index e4335f98a5..13ce84b359 100644 --- a/rich/console.py +++ b/rich/console.py @@ -650,18 +650,6 @@ def __init__( width = width or 93 height = height or 100 - if width is None: - columns = self._environ.get("COLUMNS") - if columns is not None and columns.isdigit(): - width = int(columns) - if height is None: - lines = self._environ.get("LINES") - if lines is not None and lines.isdigit(): - height = int(lines) - - self.soft_wrap = soft_wrap - self._width = width - self._height = height self.tab_size = tab_size self.record = record self._markup = markup @@ -673,6 +661,18 @@ def __init__( if legacy_windows is None else legacy_windows ) + if width is None: + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) - self.legacy_windows + if height is None: + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + + self.soft_wrap = soft_wrap + self._width = width + self._height = height self._color_system: Optional[ColorSystem] self._force_terminal = force_terminal @@ -941,7 +941,7 @@ def size(self) -> ConsoleDimensions: """ if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width - self.legacy_windows, self._height) + return ConsoleDimensions(self._width, self._height) if self.is_dumb_terminal: return ConsoleDimensions(80, 25) @@ -964,7 +964,7 @@ def size(self) -> ConsoleDimensions: width = width or 80 height = height or 25 return ConsoleDimensions( - (width if self._width is None else self._width) - self.legacy_windows, + width - self.legacy_windows if self._width is None else self._width, height if self._height is None else self._height, ) From f60dcd168a076bcf7bb006fd14f9810b45ec686d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 9 Nov 2021 17:43:23 +0000 Subject: [PATCH 087/287] disable legacy windows --- tests/test_console.py | 10 +++++----- tests/test_screen.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_console.py b/tests/test_console.py index 6660ec9d17..7e5b003902 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -100,7 +100,7 @@ def test_size(): w, h = console.size assert console.width == w - console = Console(width=99, height=101) + console = Console(width=99, height=101, legacy_windows=False) w, h = console.size assert w == 99 and h == 101 @@ -607,13 +607,13 @@ def test_height(): def test_columns_env(): - console = Console(_environ={"COLUMNS": "314"}) + console = Console(_environ={"COLUMNS": "314"}, legacy_windows=False) assert console.width == 314 # width take precedence - console = Console(width=40, _environ={"COLUMNS": "314"}) + console = Console(width=40, _environ={"COLUMNS": "314"}, legacy_windows=False) assert console.width == 40 # Should not fail - console = Console(width=40, _environ={"COLUMNS": "broken"}) + console = Console(width=40, _environ={"COLUMNS": "broken"}, legacy_windows=False) def test_lines_env(): @@ -689,7 +689,7 @@ def test_print_width_zero(): def test_size_properties(): - console = Console(width=80, height=25) + console = Console(width=80, height=25, legacy_windows=False) assert console.size == ConsoleDimensions(80, 25) console.size = (10, 20) assert console.size == ConsoleDimensions(10, 20) diff --git a/tests/test_screen.py b/tests/test_screen.py index 7596c3a385..c571e037e0 100644 --- a/tests/test_screen.py +++ b/tests/test_screen.py @@ -3,7 +3,7 @@ def test_screen(): - console = Console(color_system=None, width=20, height=5) + console = Console(color_system=None, width=20, height=5, legacy_windows=False) with console.capture() as capture: console.print(Screen("foo\nbar\nbaz\nfoo\nbar\nbaz\foo")) result = capture.get() From 1206a44f4d7dbbd1457bf05102e473911c703783 Mon Sep 17 00:00:00 2001 From: Nicolas Simonds Date: Wed, 10 Nov 2021 12:22:08 -0800 Subject: [PATCH 088/287] Fix the text.Span.__repr__ method Use `repr` instead of `str` on nested objects, to improve clarity when debugging. Fixes Issue #1676 --- rich/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/text.py b/rich/text.py index 0ecdeae4b5..52ecd16042 100644 --- a/rich/text.py +++ b/rich/text.py @@ -57,7 +57,7 @@ def __repr__(self) -> str: return ( f"Span({self.start}, {self.end}, {self.style!r})" if (isinstance(self.style, Style) and self.style._meta) - else f"Span({self.start}, {self.end}, {str(self.style)!r})" + else f"Span({self.start}, {self.end}, {repr(self.style)})" ) def __bool__(self) -> bool: From 1fbdef7fe2172c73b1e0a013b56a80ff37b598b2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 11 Nov 2021 22:32:57 +0100 Subject: [PATCH 089/287] Proofread Swiss German readme --- README.de-ch.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.de-ch.md b/README.de-ch.md index 0cd9ff6a19..b265745f15 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -31,13 +31,13 @@ Lueg was [anderi öber Rich säged](https://www.willmcgugan.com/blog/pages/post/ ## Kompatibilität -Rich funktioniert mit Linux, OSX ond Windows. True color / emoji funktioniert mit em neue Windows Törminäl, s klassische Törminäl isch of 16 Farbe limitiärt. Rich brucht Pzthon 3.6.1 oder neuer. +Rich funktioniert mit Linux, OSX ond Windows. True color / emoji funktioniert mit em neue Windows Törminäl, s klassische Törminäl isch of 16 Farbe limitiärt. Rich brucht Python 3.6.1 oder neuer. Rich funktioniert mit [Jupyter notebooks](https://jupyter.org/) ohni irgendwelchä zuäsätzloche konfiguration. ## Installation -Installation mit `pip` oder mit dim liäblings PyPi Päckli-Mangager. +Installation mit `pip` oder mit dim liäblings PyPI Päckli-Mangager. ``` pip install rich @@ -124,7 +124,7 @@ Rich hät e [inspect](https://rich.readthedocs.io/en/latest/reference/init.html? Lueg do d [inspect Dokumentation](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) für d Details a. -# Rich Library +# Rich-Bibliothek Rich häd ä Aazahl vo integriäte _renderables_ wo du chasch verwende zum eleganti Usgobe i dinner e CLI generiäre ond der hälfed bim debugge vo dim Code. @@ -133,7 +133,7 @@ Drock of di folgende Öberschrifte für d Details:
Log -S Console Objekt hät e `log()` Methode wo verglichbar zu de `print()` Schnittstell isch aber zuäsätzloch no e Spaltä för di aktuäll Zitt und d Datai mit de Zille wo de Ufruäf macht us git. Standartmässig tuät Rich es Syntax Highlighting für Python Strukturä sowiä repr Text machä. Went e Collection (wiä zum Bispiil dict oder list) loggsch wird Rich das hübsch Usgeh so dass es i de verfüägbari Platz ine passt. Do es Bispiil für e paar vo dene Funktionä. +S Console Objekt hät e `log()` Methode wo verglichbar zu de `print()` Schnittstell isch aber zuäsätzloch no e Spaltä för di aktuäll Zitt und d Datai mit de Zille wo de Ufruäf macht us git. Standardmässig tuät Rich es Syntax Highlighting für Python Strukturä sowiä repr Text machä. Went e Collection (wiä zum Bispiil dict oder list) loggsch wird Rich das hübsch Usgeh so dass es i de verfüägbari Platz ine passt. Do es Bispiil für e paar vo dene Funktionä. ```python from rich.console import Console @@ -197,9 +197,9 @@ Rich cha flexiibäl [Tabelle](https://rich.readthedocs.io/en/latest/tables.html) ![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) -D Animation obe isch mit [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) us em Bispiil Ordner erstellt worde. +D Animation obe isch mit [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) us em Bispiil-Ordner erstellt worde. -Do es eifachs Tabelle Bispiil: +Do es eifachs Tabelle-Bispiil: ```python from rich.console import Console @@ -298,7 +298,7 @@ D Spinner Animatione sind vo [cli-spinners](https://www.npmjs.com/package/cli-sp python -m rich.spinner ``` -De Befehlt obe generiärt di folgändi Usgob im Törminäl: +De Befehl obe generiärt di folgändi Usgob im Törminäl: ![spinners](https://github.com/willmcgugan/rich/raw/master/imgs/spinners.gif) @@ -324,9 +324,9 @@ Lueg s Bispiil Script [tree.py](https://github.com/willmcgugan/rich/blob/master/
-Columns +Spaltene -Rich can render content in neat [columns](https://rich.readthedocs.io/en/latest/columns.html) with equal or optimal width. Here's a very basic clone of the (MacOS / Linux) `ls` command which displays a directory listing in columns: +Rich cha Inhalt i hübsche [Spaltene](https://rich.readthedocs.io/en/latest/columns.html) darstelle mit glichä oder optimale Breiti. Do isch e ganz eifachi kopii vom (MacOS / Linux) `ls` Befehl wo Ordner in Columns darstellt ```python import os @@ -339,7 +339,7 @@ directory = os.listdir(sys.argv[1]) print(Columns(directory)) ``` -De folgend Screenshot isch d Usgob vom [columns example](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) Bispiil, wo Date vonnere API hollt ond in Colums darstellt: +De folgend Screenshot isch d Usgob vom [Spalte-Bispiil](https://github.com/willmcgugan/rich/blob/master/examples/columns.py), wo Date vonnere API hollt ond in Colums darstellt: ![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) @@ -350,7 +350,7 @@ De folgend Screenshot isch d Usgob vom [columns example](https://github.com/will Rich cha [markdown](https://rich.readthedocs.io/en/latest/markdown.html) übersetze ond leistet vernünftigi Ärbät bim formatiärige is Törminäl z übersetze. -Zum Markdonw z übersetze importier d Klass `Markdown` und instanzier es mitem Markdown Text. Nocher gid mos uf de Konsolä us. Do es Bispiil: +Zum Markdown z übersetze importier d Klass `Markdown` und instanzier es mitem Markdown Text. Nocher gid mos uf de Konsolä us. Do es Bispiil: ```python from rich.console import Console @@ -406,7 +406,7 @@ Das wird d Usgob ungefär wie s Folgende geh:
Tracebacks -Rich cha [wunderschöni Tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) generiäre wo eifach zum läse sind und meh Code als de standart Python Traceback darstellt. Du chasch Rich als default Traceback Handler setzä ond alli nöd abfangene Exceptions werded mit Rich dargstellt. +Rich cha [wunderschöni Tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) generiäre wo eifach zum läse sind und meh Code als de Standard Python-Traceback darstellt. Du chasch Rich als default Traceback Handler setzä ond alli nöd abfangene Exceptions werded mit Rich dargstellt. So gsiets ungefär ufemen OSX (ähnloch uf Linux) us: @@ -414,7 +414,7 @@ So gsiets ungefär ufemen OSX (ähnloch uf Linux) us:
-Alli Rich Renderables bruched s [Console Protokoll](https://rich.readthedocs.io/en/latest/protocol.html), wo mo au für d eige entwicklig vo Rich Inhalt cha bruche. +Alli Rich Renderables bruched s [Console-Protokoll](https://rich.readthedocs.io/en/latest/protocol.html), wo mo au für d eige Entwicklig vo Rich-Inhalt cha bruche. # Rich für Ondernemä @@ -450,6 +450,6 @@ Do es paar Projekt wo Rich verwended: Lightweight Python library for adding real-time 2D object tracking to any detector. - [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint checks playbooks for practices and behaviour that could potentially be improved - [ansible-community/molecule](https://github.com/ansible-community/molecule) Ansible Molecule testing framework -- +[Many more](https://github.com/willmcgugan/rich/network/dependents)! +- +[Vieli meh](https://github.com/willmcgugan/rich/network/dependents)! From 8a74a97563dad3437ce537ed07dc72e031c54638 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 13 Nov 2021 09:04:12 +0000 Subject: [PATCH 090/287] fix infinite loop --- CHANGELOG.md | 1 + rich/cells.py | 6 ++++-- tests/test_cells.py | 12 ++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 804769d411..34ac496559 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed progress speed not updating when total doesn't change - Fixed superfluous new line in Status https://github.com/willmcgugan/rich/issues/1662 +- Fixed infinite loop in set_cell_size https://github.com/willmcgugan/rich/issues/1682 ## [10.13.0] - 2021-11-07 diff --git a/rich/cells.py b/rich/cells.py index 7f9c0c16c9..b02f4b8681 100644 --- a/rich/cells.py +++ b/rich/cells.py @@ -74,6 +74,8 @@ def _get_codepoint_cell_size(codepoint: int) -> int: def set_cell_size(text: str, total: int) -> str: """Set the length of a string to fit within given number of cells.""" + if not total: + return "" cell_size = cell_len(text) if cell_size == total: return text @@ -81,12 +83,12 @@ def set_cell_size(text: str, total: int) -> str: return text + " " * (total - cell_size) start = 0 - end = cell_size + end = len(text) # Binary search until we find the right size while True: pos = (start + end) // 2 - before = text[:pos] + before = text[: pos + 1] before_len = cell_len(before) if before_len == total + 1 and cell_len(before[-1]) == 2: return before[:-1] + " " diff --git a/tests/test_cells.py b/tests/test_cells.py index 06de437202..7633944ba1 100644 --- a/tests/test_cells.py +++ b/tests/test_cells.py @@ -9,3 +9,15 @@ def test_set_cell_size(): assert cells.set_cell_size("😽😽", 3) == "😽 " assert cells.set_cell_size("😽😽", 2) == "😽" assert cells.set_cell_size("😽😽", 1) == " " + + +def test_set_cell_size_infinite(): + for size in range(38): + assert ( + cells.cell_len( + cells.set_cell_size( + "เป็นเกมที่ต้องมีความอดทนมากที่สุดตั้งเเต่เคยเล่นมา", size + ) + ) + == size + ) From 3645de66c4bb9e0fa96b10741219b917a3d4ad1d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 13 Nov 2021 09:07:42 +0000 Subject: [PATCH 091/287] tests for 0 size --- tests/test_cells.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_cells.py b/tests/test_cells.py index 7633944ba1..c332f2a541 100644 --- a/tests/test_cells.py +++ b/tests/test_cells.py @@ -2,6 +2,10 @@ def test_set_cell_size(): + assert cells.set_cell_size("foo", 0) == "" + assert cells.set_cell_size("f", 0) == "" + assert cells.set_cell_size("", 0) == "" + assert cells.set_cell_size("😽😽", 0) == "" assert cells.set_cell_size("foo", 2) == "fo" assert cells.set_cell_size("foo", 3) == "foo" assert cells.set_cell_size("foo", 4) == "foo " From 53372f65db1c9c60ddd90dca795a3c2094532142 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 13 Nov 2021 09:12:38 +0000 Subject: [PATCH 092/287] added file --- CHANGELOG.md | 4 ++++ rich/highlighter.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ac496559..f039614db5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed superfluous new line in Status https://github.com/willmcgugan/rich/issues/1662 - Fixed infinite loop in set_cell_size https://github.com/willmcgugan/rich/issues/1682 +### Added + +- Added file protocol to URL highlighter https://github.com/willmcgugan/rich/issues/1681 + ## [10.13.0] - 2021-11-07 ### Added diff --git a/rich/highlighter.py b/rich/highlighter.py index 9e71d00531..8afdd017b6 100644 --- a/rich/highlighter.py +++ b/rich/highlighter.py @@ -96,7 +96,7 @@ class ReprHighlighter(RegexHighlighter): r"(?P\B(\/[\w\.\-\_\+]+)*\/)(?P[\w\.\-\_\+]*)?", r"(?b?\'\'\'.*?(?[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(https|http|ws|wss):\/\/[0-9a-zA-Z\$\-\_\+\!`\(\)\,\.\?\/\;\:\&\=\%\#]*)", + r"(?P(file|https|http|ws|wss):\/\/[0-9a-zA-Z\$\-\_\+\!`\(\)\,\.\?\/\;\:\&\=\%\#]*)", ), ] From 200cca8d732d830a805c6bfd0c0160d400fcad8f Mon Sep 17 00:00:00 2001 From: Raphael Borun Das Gupta Date: Sat, 13 Nov 2021 12:18:02 +0100 Subject: [PATCH 093/287] add LF at EOF --- docs/source/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 464ebdd65a..3ab6e084f3 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -103,4 +103,4 @@ Rich has an :meth:`~rich.inspect` function which can generate a report on any Py >>> from rich import inspect >>> from rich.color import Color >>> color = Color.parse("red") - >>> inspect(color, methods=True) \ No newline at end of file + >>> inspect(color, methods=True) From e1c4628ffe5d1c1ec03884206f044fc5b9a88e83 Mon Sep 17 00:00:00 2001 From: Raphael Borun Das Gupta Date: Sat, 13 Nov 2021 12:19:11 +0100 Subject: [PATCH 094/287] capizalize "PyPI" correctly --- CHANGELOG.md | 2 +- README.cn.md | 2 +- README.de-ch.md | 2 +- README.de.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.it.md | 2 +- README.ja.md | 2 +- README.kr.md | 2 +- README.md | 2 +- README.pt-br.md | 2 +- README.sv.md | 2 +- docs/source/introduction.rst | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f039614db5..63e31e8c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1481,7 +1481,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr ### Fixed -- Readme links in Pypi +- Readme links in PyPI ## [0.4.0] - 2020-02-22 diff --git a/README.cn.md b/README.cn.md index 070c9fd319..f7cb2768e4 100644 --- a/README.cn.md +++ b/README.cn.md @@ -37,7 +37,7 @@ Rich 还可以与[Jupyter 笔记本](https://jupyter.org/)一起使用,而无 ## 安装说明 -使用`pip`或其他 PyPi 软件包管理器进行安装。 +使用`pip`或其他 PyPI 软件包管理器进行安装。 ``` pip install rich diff --git a/README.de-ch.md b/README.de-ch.md index 0cd9ff6a19..3abc161a1b 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -37,7 +37,7 @@ Rich funktioniert mit [Jupyter notebooks](https://jupyter.org/) ohni irgendwelch ## Installation -Installation mit `pip` oder mit dim liäblings PyPi Päckli-Mangager. +Installation mit `pip` oder mit dim liäblings PyPI Päckli-Mangager. ``` pip install rich diff --git a/README.de.md b/README.de.md index a0f90034e9..3e419ae6ea 100644 --- a/README.de.md +++ b/README.de.md @@ -37,7 +37,7 @@ Rich funktioniert ohne zusätzliche Konfiguration mit [Jupyter Notebooks](https: ## Installation -Installation mit `pip` oder deinem bevorzugten PyPi-Paketmanager. +Installation mit `pip` oder deinem bevorzugten PyPI-Paketmanager. ``` python -m rich diff --git a/README.es.md b/README.es.md index 9021f94620..5edad6900b 100644 --- a/README.es.md +++ b/README.es.md @@ -37,7 +37,7 @@ Rich funciona con [Jupyter notebooks](https://jupyter.org/) sin necesidad de con ## Instalación -Instale con `pip` o su administrador de paquetes PyPi favorito. +Instale con `pip` o su administrador de paquetes PyPI favorito. ``` pip install rich diff --git a/README.fr.md b/README.fr.md index ee4566f738..13da865010 100644 --- a/README.fr.md +++ b/README.fr.md @@ -37,7 +37,7 @@ Rich fonctionne avec les notebooks Jupyter sans configuration supplémentaire. ## Installation -Installez avec `pip` ou votre gestionnaire de paquets Pypi préféré. +Installez avec `pip` ou votre gestionnaire de paquets PyPI préféré. ``` pip install rich diff --git a/README.it.md b/README.it.md index a2434201b8..738f8b5fe3 100644 --- a/README.it.md +++ b/README.it.md @@ -37,7 +37,7 @@ Rich funziona con i [Jupyter notebooks](https://jupyter.org/) senza configurazio ## Installazione -Installa con `pip` o il tuo PyPi package manager preferito. +Installa con `pip` o il tuo PyPI package manager preferito. ```shell pip install rich diff --git a/README.ja.md b/README.ja.md index a71b36ff69..93c87c954f 100644 --- a/README.ja.md +++ b/README.ja.md @@ -37,7 +37,7 @@ Richは追加の設定を行わずとも、[Jupyter notebooks](https://jupyter.o ## インストール -`pip` や、あなたのお気に入りのPyPiパッケージマネージャを使ってインストールしてください。 +`pip` や、あなたのお気に入りのPyPIパッケージマネージャを使ってインストールしてください。 ``` pip install rich diff --git a/README.kr.md b/README.kr.md index 2b09c9f076..b0a3508ba7 100644 --- a/README.kr.md +++ b/README.kr.md @@ -37,7 +37,7 @@ Rich는 [Jupyter notebooks](https://jupyter.org/)에서 별도의 설정없이 ## 설치 -`pip` 또는 좋아하는 Pypi 패키지 매니저로 설치하세요. +`pip` 또는 좋아하는 PyPI 패키지 매니저로 설치하세요. ``` pip install rich diff --git a/README.md b/README.md index dabe67a4b3..ecd7a65c16 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Rich works with [Jupyter notebooks](https://jupyter.org/) with no additional con ## Installing -Install with `pip` or your favorite PyPi package manager. +Install with `pip` or your favorite PyPI package manager. ``` pip install rich diff --git a/README.pt-br.md b/README.pt-br.md index 1e0451822b..677f078251 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -36,7 +36,7 @@ Rich funciona com [Jupyter notebooks](https://jupyter.org/) sem a necessidade de ## Instalação -Instale usando `pip` ou seu gerenciador de pacotes PyPi favorito. +Instale usando `pip` ou seu gerenciador de pacotes PyPI favorito. ``` pip install rich diff --git a/README.sv.md b/README.sv.md index d6cf99681f..e14e520790 100644 --- a/README.sv.md +++ b/README.sv.md @@ -36,7 +36,7 @@ Rich funkar med [Jupyter notebooks](https://jupyter.org/) utan någon ytterligar ## Installering -Installera med `pip` eller din favorita PyPi packet hanterare. +Installera med `pip` eller din favorita PyPI packet hanterare. ``` pip install rich diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 3ab6e084f3..bcbe906ea8 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -20,7 +20,7 @@ Rich requires Python 3.6.1 and above. Note that Python 3.6.0 is *not* supported Installation ------------ -You can install Rich from PyPi with `pip` or your favorite package manager:: +You can install Rich from PyPI with `pip` or your favorite package manager:: pip install rich From b54b1da3e427c13cd23899652b1b2fac013c804b Mon Sep 17 00:00:00 2001 From: "Paulo S. Costa" Date: Sat, 13 Nov 2021 15:41:27 -0800 Subject: [PATCH 095/287] Fix broken pager reference --- rich/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index 74d6b66589..5d51334f08 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1042,7 +1042,7 @@ def pager( is defined by the system and will typically support at least pressing a key to scroll. Args: - pager (Pager, optional): A pager object, or None to use :class:~rich.pager.SystemPager`. Defaults to None. + pager (Pager, optional): A pager object, or None to use :class:`~rich.pager.SystemPager`. Defaults to None. styles (bool, optional): Show styles in pager. Defaults to False. links (bool, optional): Show links in pager. Defaults to False. From 23502b44ff10c35a3f557b612657f1e8e5cae7cd Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 15 Nov 2021 15:13:59 +0000 Subject: [PATCH 096/287] change to env var --- rich/console.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/rich/console.py b/rich/console.py index bae2f36a60..9c9eb96cfd 100644 --- a/rich/console.py +++ b/rich/console.py @@ -650,14 +650,14 @@ def __init__( width = width or 93 height = height or 100 - if width is None: - columns = self._environ.get("COLUMNS") - if columns is not None and columns.isdigit(): - width = int(columns) - if height is None: - lines = self._environ.get("LINES") - if lines is not None and lines.isdigit(): - height = int(lines) + # if width is None: + # columns = self._environ.get("COLUMNS") + # if columns is not None and columns.isdigit(): + # width = int(columns) + # if height is None: + # lines = self._environ.get("LINES") + # if lines is not None and lines.isdigit(): + # height = int(lines) self.soft_wrap = soft_wrap self._width = width @@ -949,7 +949,7 @@ def size(self) -> ConsoleDimensions: width: Optional[int] = None height: Optional[int] = None if WINDOWS: # pragma: no cover - width, height = shutil.get_terminal_size() + width, height = os.get_terminal_size() else: try: width, height = os.get_terminal_size(sys.__stdin__.fileno()) @@ -959,6 +959,13 @@ def size(self) -> ConsoleDimensions: except (AttributeError, ValueError, OSError): pass + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + # get_terminal_size can report 0, 0 if run from pseudo-terminal width = width or 80 height = height or 25 @@ -1904,7 +1911,9 @@ def _check_buffer(self) -> None: try: if WINDOWS: # pragma: no cover # https://bugs.python.org/issue37871 - self.file.writelines(text.splitlines(True)) + write = self.file.write + for line in text.splitlines(True): + write(line) else: self.file.write(text) self.file.flush() From 278402f25af28df503a84af779eaf8ace27ac61c Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 15 Nov 2021 15:24:09 +0000 Subject: [PATCH 097/287] handle error --- rich/console.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rich/console.py b/rich/console.py index 8a880b6ab0..de983e91aa 100644 --- a/rich/console.py +++ b/rich/console.py @@ -953,7 +953,10 @@ def size(self) -> ConsoleDimensions: height: Optional[int] = None if WINDOWS: # pragma: no cover - width, height = os.get_terminal_size() + try: + width, height = os.get_terminal_size() + except OSError: # Probably not a terminal + pass else: try: width, height = os.get_terminal_size(sys.__stdin__.fileno()) From 428613cd38e0324cd97c26e60547ffc34a2cf031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 15:45:22 +0000 Subject: [PATCH 098/287] Bump sphinx from 4.2.0 to 4.3.0 Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.2.0...v4.3.0) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 273656e9f2..02be340721 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ alabaster==0.7.12 -Sphinx==4.2.0 +Sphinx==4.3.0 sphinx-rtd-theme==1.0.0 sphinx-copybutton==0.4.0 From 20b27d53e4229b6f9f9b9411dc25e5a76228388f Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 16 Nov 2021 12:58:41 +0000 Subject: [PATCH 099/287] added rich cast to protocol --- CHANGELOG.md | 7 ++++++- rich/console.py | 16 +++++----------- rich/measure.py | 5 ++--- rich/protocol.py | 34 +++++++++++++++++++++++++++++++++- tests/test_protocol.py | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9553495b13..c60d6bb523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.13.1] - 2021-11-09 +## [10.14.0] - Unreleased ### Fixed @@ -17,6 +17,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added file protocol to URL highlighter https://github.com/willmcgugan/rich/issues/1681 +- Added rich.protocol.rich_cast + +### Changed + +- Allowed `__rich__` to work recursively ## [10.13.0] - 2021-11-07 diff --git a/rich/console.py b/rich/console.py index 0f07ca03c5..2a8a735cfa 100644 --- a/rich/console.py +++ b/rich/console.py @@ -25,6 +25,7 @@ Mapping, NamedTuple, Optional, + Set, TextIO, Tuple, Type, @@ -53,6 +54,7 @@ from .measure import Measurement, measure_renderables from .pager import Pager, SystemPager from .pretty import Pretty, is_expandable +from .protocol import rich_cast from .region import Region from .scope import render_scope from .screen import Screen @@ -1220,8 +1222,8 @@ def render( # No space to render anything. This prevents potential recursion errors. return render_iterable: RenderResult - if hasattr(renderable, "__rich__") and not isclass(renderable): - renderable = renderable.__rich__() # type: ignore + + renderable = rich_cast(renderable) if hasattr(renderable, "__rich_console__") and not isclass(renderable): render_iterable = renderable.__rich_console__(self, _options) # type: ignore elif isinstance(renderable, str): @@ -1439,15 +1441,7 @@ def check_text() -> None: del text[:] for renderable in objects: - # I promise this is sane - # This detects an object which claims to have all attributes, such as MagicMock.mock_calls - if hasattr( - renderable, "jwevpw_eors4dfo6mwo345ermk7kdnfnwerwer" - ): # pragma: no cover - renderable = repr(renderable) - rich_cast = getattr(renderable, "__rich__", None) - if rich_cast: - renderable = rich_cast() + renderable = rich_cast(renderable) if isinstance(renderable, str): append_text( self.render_str( diff --git a/rich/measure.py b/rich/measure.py index db54f294b0..aea238df93 100644 --- a/rich/measure.py +++ b/rich/measure.py @@ -2,7 +2,7 @@ from typing import Callable, Iterable, NamedTuple, Optional, TYPE_CHECKING from . import errors -from .protocol import is_renderable +from .protocol import is_renderable, rich_cast if TYPE_CHECKING: from .console import Console, ConsoleOptions, RenderableType @@ -97,8 +97,7 @@ def get( return Measurement(0, 0) if isinstance(renderable, str): renderable = console.render_str(renderable, markup=options.markup) - if hasattr(renderable, "__rich__"): - renderable = renderable.__rich__() # type: ignore + renderable = rich_cast(renderable) if is_renderable(renderable): get_console_width: Optional[ Callable[["Console", "ConsoleOptions"], "Measurement"] diff --git a/rich/protocol.py b/rich/protocol.py index 711b31b6a5..1d64ff3ddd 100644 --- a/rich/protocol.py +++ b/rich/protocol.py @@ -1,4 +1,10 @@ -from typing import Any +from typing import Any, Callable, cast, Set, TYPE_CHECKING +from inspect import isclass + +if TYPE_CHECKING: + from rich.console import RenderableType + +_GIBBERISH = """aihwerij235234ljsdnp34ksodfipwoe234234jlskjdf""" def is_renderable(check_object: Any) -> bool: @@ -8,3 +14,29 @@ def is_renderable(check_object: Any) -> bool: or hasattr(check_object, "__rich__") or hasattr(check_object, "__rich_console__") ) + + +def rich_cast(renderable: object) -> "RenderableType": + """Cast an object to a renderable by calling __rich__ if present. + + Args: + renderable (object): A potentially renderable object + + Returns: + object: The result of recursively calling __rich__. + """ + from rich.console import RenderableType + + rich_visited_set: Set[type] = set() # Prevent potential infinite loop + while hasattr(renderable, "__rich__") and not isclass(renderable): + # Detect object which claim to have all the attributes + if hasattr(renderable, _GIBBERISH): + return repr(renderable) + cast_method = getattr(renderable, "__rich__") + renderable = cast_method() + renderable_type = type(renderable) + if renderable_type in rich_visited_set: + break + rich_visited_set.add(renderable_type) + + return cast(RenderableType, renderable) \ No newline at end of file diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 310b994d3a..50d129a716 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -33,3 +33,37 @@ def test_abc(): assert not isinstance(foo, str) assert not isinstance("foo", RichRenderable) assert not isinstance([], RichRenderable) + + +def test_cast_deep(): + class B: + def __rich__(self) -> Foo: + return Foo() + + class A: + def __rich__(self) -> B: + return B() + + console = Console(file=io.StringIO()) + console.print(A()) + assert console.file.getvalue() == "Foo\n" + + +def test_cast_recursive(): + class B: + def __rich__(self) -> "A": + return A() + + def __repr__(self) -> str: + return "" + + class A: + def __rich__(self) -> B: + return B() + + def __repr__(self) -> str: + return "" + + console = Console(file=io.StringIO()) + console.print(A()) + assert console.file.getvalue() == "\n" From d22a78fdb63b4afeba3cfe2b950bdf43c662af67 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 16 Nov 2021 13:11:23 +0000 Subject: [PATCH 100/287] update typing extensions --- poetry.lock | 472 +++++++++++++++++++++++-------------------------- pyproject.toml | 2 +- 2 files changed, 222 insertions(+), 252 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2e0c7d92d3..e1bc7213f6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -104,7 +104,7 @@ webencodings = "*" [[package]] name = "cffi" -version = "1.14.6" +version = "1.15.0" description = "Foreign Function Interface for Python calling C code." category = "main" optional = true @@ -115,7 +115,7 @@ pycparser = "*" [[package]] name = "click" -version = "8.0.1" +version = "8.0.3" description = "Composable command line interface toolkit" category = "dev" optional = false @@ -146,7 +146,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "6.1.1" +version = "6.1.2" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -192,7 +192,7 @@ python-versions = ">=2.7" [[package]] name = "importlib-metadata" -version = "4.8.1" +version = "4.8.2" description = "Read metadata from Python packages" category = "main" optional = false @@ -205,7 +205,7 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -217,7 +217,7 @@ python-versions = "*" [[package]] name = "ipykernel" -version = "5.5.5" +version = "5.5.6" description = "IPython Kernel for Jupyter" category = "main" optional = true @@ -226,6 +226,7 @@ python-versions = ">=3.5" [package.dependencies] appnope = {version = "*", markers = "platform_system == \"Darwin\""} ipython = ">=5.0.0" +ipython-genutils = "*" jupyter-client = "*" tornado = ">=4.2" traitlets = ">=4.1.0" @@ -309,7 +310,7 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"] [[package]] name = "jinja2" -version = "3.0.2" +version = "3.0.3" description = "A very fast and expressive template engine." category = "main" optional = true @@ -361,7 +362,7 @@ test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-comm [[package]] name = "jupyter-core" -version = "4.8.1" +version = "4.9.1" description = "Jupyter core package. A base package on which Jupyter projects rely." category = "main" optional = true @@ -434,7 +435,7 @@ python-versions = "*" [[package]] name = "nbclient" -version = "0.5.4" +version = "0.5.8" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." category = "main" optional = true @@ -448,9 +449,9 @@ nest-asyncio = "*" traitlets = ">=4.2" [package.extras] -dev = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "bumpversion", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] +dev = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] sphinx = ["Sphinx (>=1.7)", "sphinx-book-theme", "mock", "moto", "myst-parser"] -test = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "bumpversion", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] +test = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] [[package]] name = "nbconvert" @@ -510,7 +511,7 @@ python-versions = ">=3.5" [[package]] name = "notebook" -version = "6.4.4" +version = "6.4.5" description = "A web-based notebook environment for interactive computing" category = "main" optional = true @@ -539,14 +540,14 @@ test = ["pytest", "coverage", "requests", "nbval", "selenium", "pytest-cov", "re [[package]] name = "packaging" -version = "21.0" +version = "21.2" description = "Core utilities for Python packages" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2" +pyparsing = ">=2.0.2,<3" [[package]] name = "pandocfilters" @@ -624,7 +625,7 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prometheus-client" -version = "0.11.0" +version = "0.12.0" description = "Python client for the Prometheus monitoring system." category = "main" optional = true @@ -635,7 +636,7 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.20" +version = "3.0.22" description = "Library for building powerful interactive command lines in Python" category = "main" optional = true @@ -654,15 +655,15 @@ python-versions = "*" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = true @@ -742,7 +743,7 @@ six = ">=1.5" [[package]] name = "pywin32" -version = "301" +version = "302" description = "Python for Window Extensions" category = "main" optional = true @@ -750,7 +751,7 @@ python-versions = "*" [[package]] name = "pywinpty" -version = "1.1.4" +version = "1.1.6" description = "Pseudo terminal support for Windows from Python." category = "main" optional = true @@ -770,7 +771,7 @@ py = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "regex" -version = "2021.9.30" +version = "2021.11.10" description = "Alternative regular expression module, to replace re." category = "dev" optional = false @@ -834,7 +835,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.1" +version = "1.2.2" description = "A lil' TOML parser" category = "dev" optional = false @@ -882,11 +883,11 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" +version = "4.0.0" +description = "Backported and Experimental Type Hints for Python 3.6+" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "wcwidth" @@ -906,7 +907,7 @@ python-versions = "*" [[package]] name = "widgetsnbextension" -version = "3.5.1" +version = "3.5.2" description = "IPython HTML widgets for Jupyter" category = "main" optional = true @@ -933,7 +934,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "8bdb5487831da15eafc51dcd67177f13cc7d498f8cac62b80c60988a85f75ce4" +content-hash = "3b57479f41dfc0f68349be778c31f954f6f2c6dff1d23178e2ee000e45ea67ca" [metadata.files] appnope = [ @@ -978,55 +979,60 @@ bleach = [ {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"}, ] cffi = [ - {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, - {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, - {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"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, - {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, - {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, - {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, - {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, - {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, - {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, - {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, - {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, - {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, - {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, - {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, - {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, + {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, + {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, + {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, + {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, + {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, + {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, + {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, + {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, + {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, + {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, + {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, + {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, + {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, + {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, + {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, + {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, + {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] click = [ - {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, - {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, + {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, + {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -1037,52 +1043,53 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42a1fb5dee3355df90b635906bb99126faa7936d87dfc97eacc5293397618cb7"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a00284dbfb53b42e35c7dd99fc0e26ef89b4a34efff68078ed29d03ccb28402a"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:51a441011a30d693e71dea198b2a6f53ba029afc39f8e2aeb5b77245c1b282ef"}, - {file = "coverage-6.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e76f017b6d4140a038c5ff12be1581183d7874e41f1c0af58ecf07748d36a336"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7833c872718dc913f18e51ee97ea0dece61d9930893a58b20b3daf09bb1af6b6"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8186b5a4730c896cbe1e4b645bdc524e62d874351ae50e1db7c3e9f5dc81dc26"}, - {file = "coverage-6.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbca34dca5a2d60f81326d908d77313816fad23d11b6069031a3d6b8c97a54f9"}, - {file = "coverage-6.1.1-cp310-cp310-win32.whl", hash = "sha256:72bf437d54186d104388cbae73c9f2b0f8a3e11b6e8d7deb593bd14625c96026"}, - {file = "coverage-6.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:994ce5a7b3d20981b81d83618aa4882f955bfa573efdbef033d5632b58597ba9"}, - {file = "coverage-6.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ab6a0fe4c96f8058d41948ddf134420d3ef8c42d5508b5a341a440cce7a37a1d"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10ab138b153e4cc408b43792cb7f518f9ee02f4ff55cd1ab67ad6fd7e9905c7e"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7e083d32965d2eb6638a77e65b622be32a094fdc0250f28ce6039b0732fbcaa8"}, - {file = "coverage-6.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:359a32515e94e398a5c0fa057e5887a42e647a9502d8e41165cf5cb8d3d1ca67"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:bf656cd74ff7b4ed7006cdb2a6728150aaad69c7242b42a2a532f77b63ea233f"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dc5023be1c2a8b0a0ab5e31389e62c28b2453eb31dd069f4b8d1a0f9814d951a"}, - {file = "coverage-6.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:557594a50bfe3fb0b1b57460f6789affe8850ad19c1acf2d14a3e12b2757d489"}, - {file = "coverage-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:9eb0a1923354e0fdd1c8a6f53f5db2e6180d670e2b587914bf2e79fa8acfd003"}, - {file = "coverage-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:04a92a6cf9afd99f9979c61348ec79725a9f9342fb45e63c889e33c04610d97b"}, - {file = "coverage-6.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:479228e1b798d3c246ac89b09897ee706c51b3e5f8f8d778067f38db73ccc717"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78287731e3601ea5ce9d6468c82d88a12ef8fe625d6b7bdec9b45d96c1ad6533"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c95257aa2ccf75d3d91d772060538d5fea7f625e48157f8ca44594f94d41cb33"}, - {file = "coverage-6.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9ad5895938a894c368d49d8470fe9f519909e5ebc6b8f8ea5190bd0df6aa4271"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:326d944aad0189603733d646e8d4a7d952f7145684da973c463ec2eefe1387c2"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e7d5606b9240ed4def9cbdf35be4308047d11e858b9c88a6c26974758d6225ce"}, - {file = "coverage-6.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:572f917267f363101eec375c109c9c1118037c7cc98041440b5eabda3185ac7b"}, - {file = "coverage-6.1.1-cp37-cp37m-win32.whl", hash = "sha256:35cd2230e1ed76df7d0081a997f0fe705be1f7d8696264eb508076e0d0b5a685"}, - {file = "coverage-6.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:65ad3ff837c89a229d626b8004f0ee32110f9bfdb6a88b76a80df36ccc60d926"}, - {file = "coverage-6.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:977ce557d79577a3dd510844904d5d968bfef9489f512be65e2882e1c6eed7d8"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62512c0ec5d307f56d86504c58eace11c1bc2afcdf44e3ff20de8ca427ca1d0e"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2e5b9c17a56b8bf0c0a9477fcd30d357deb486e4e1b389ed154f608f18556c8a"}, - {file = "coverage-6.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:666c6b32b69e56221ad1551d377f718ed00e6167c7a1b9257f780b105a101271"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fb2fa2f6506c03c48ca42e3fe5a692d7470d290c047ee6de7c0f3e5fa7639ac9"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f0f80e323a17af63eac6a9db0c9188c10f1fd815c3ab299727150cc0eb92c7a4"}, - {file = "coverage-6.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:738e823a746841248b56f0f3bd6abf3b73af191d1fd65e4c723b9c456216f0ad"}, - {file = "coverage-6.1.1-cp38-cp38-win32.whl", hash = "sha256:8605add58e6a960729aa40c0fd9a20a55909dd9b586d3e8104cc7f45869e4c6b"}, - {file = "coverage-6.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:6e994003e719458420e14ffb43c08f4c14990e20d9e077cb5cad7a3e419bbb54"}, - {file = "coverage-6.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e3c4f5211394cd0bf6874ac5d29684a495f9c374919833dcfff0bd6d37f96201"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e14bceb1f3ae8a14374be2b2d7bc12a59226872285f91d66d301e5f41705d4d6"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0147f7833c41927d84f5af9219d9b32f875c0689e5e74ac8ca3cb61e73a698f9"}, - {file = "coverage-6.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1d0a1bce919de0dd8da5cff4e616b2d9e6ebf3bd1410ff645318c3dd615010a"}, - {file = "coverage-6.1.1-cp39-cp39-win32.whl", hash = "sha256:a11a2c019324fc111485e79d55907e7289e53d0031275a6c8daed30690bc50c0"}, - {file = "coverage-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4d8b453764b9b26b0dd2afb83086a7c3f9379134e340288d2a52f8a91592394b"}, - {file = "coverage-6.1.1-pp36-none-any.whl", hash = "sha256:3b270c6b48d3ff5a35deb3648028ba2643ad8434b07836782b1139cf9c66313f"}, - {file = "coverage-6.1.1-pp37-none-any.whl", hash = "sha256:ffa8fee2b1b9e60b531c4c27cf528d6b5d5da46b1730db1f4d6eee56ff282e07"}, - {file = "coverage-6.1.1-pp38-none-any.whl", hash = "sha256:4cd919057636f63ab299ccb86ea0e78b87812400c76abab245ca385f17d19fb5"}, - {file = "coverage-6.1.1.tar.gz", hash = "sha256:b8e4f15b672c9156c1154249a9c5746e86ac9ae9edc3799ee3afebc323d9d9e0"}, + {file = "coverage-6.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:675adb3b3380967806b3cbb9c5b00ceb29b1c472692100a338730c1d3e59c8b9"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95a58336aa111af54baa451c33266a8774780242cab3704b7698d5e514840758"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d0a595a781f8e186580ff8e3352dd4953b1944289bec7705377c80c7e36c4d6c"}, + {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d3c5f49ce6af61154060640ad3b3281dbc46e2e0ef2fe78414d7f8a324f0b649"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:310c40bed6b626fd1f463e5a83dba19a61c4eb74e1ac0d07d454ebbdf9047e9d"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a4d48e42e17d3de212f9af44f81ab73b9378a4b2b8413fd708d0d9023f2bbde4"}, + {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ffa545230ca2ad921ad066bf8fd627e7be43716b6e0fcf8e32af1b8188ccb0ab"}, + {file = "coverage-6.1.2-cp310-cp310-win32.whl", hash = "sha256:cd2d11a59afa5001ff28073ceca24ae4c506da4355aba30d1e7dd2bd0d2206dc"}, + {file = "coverage-6.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:96129e41405887a53a9cc564f960d7f853cc63d178f3a182fdd302e4cab2745b"}, + {file = "coverage-6.1.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1de9c6f5039ee2b1860b7bad2c7bc3651fbeb9368e4c4d93e98a76358cdcb052"}, + {file = "coverage-6.1.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:80cb70264e9a1d04b519cdba3cd0dc42847bf8e982a4d55c769b9b0ee7cdce1e"}, + {file = "coverage-6.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:ba6125d4e55c0b8e913dad27b22722eac7abdcb1f3eab1bd090eee9105660266"}, + {file = "coverage-6.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8492d37acdc07a6eac6489f6c1954026f2260a85a4c2bb1e343fe3d35f5ee21a"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66af99c7f7b64d050d37e795baadf515b4561124f25aae6e1baa482438ecc388"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ebcc03e1acef4ff44f37f3c61df478d6e469a573aa688e5a162f85d7e4c3860d"}, + {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d44a8136eebbf544ad91fef5bd2b20ef0c9b459c65a833c923d9aa4546b204"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c18725f3cffe96732ef96f3de1939d81215fd6d7d64900dcc4acfe514ea4fcbf"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c8e9c4bcaaaa932be581b3d8b88b677489975f845f7714efc8cce77568b6711c"}, + {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:06d009e8a29483cbc0520665bc46035ffe9ae0e7484a49f9782c2a716e37d0a0"}, + {file = "coverage-6.1.2-cp36-cp36m-win32.whl", hash = "sha256:e5432d9c329b11c27be45ee5f62cf20a33065d482c8dec1941d6670622a6fb8f"}, + {file = "coverage-6.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:82fdcb64bf08aa5db881db061d96db102c77397a570fbc112e21c48a4d9cb31b"}, + {file = "coverage-6.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:94f558f8555e79c48c422045f252ef41eb43becdd945e9c775b45ebfc0cbd78f"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:046647b96969fda1ae0605f61288635209dd69dcd27ba3ec0bf5148bc157f954"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cc799916b618ec9fd00135e576424165691fec4f70d7dc12cfaef09268a2478c"}, + {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62646d98cf0381ffda301a816d6ac6c35fc97aa81b09c4c52d66a15c4bef9d7c"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:27a3df08a855522dfef8b8635f58bab81341b2fb5f447819bc252da3aa4cf44c"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:610c0ba11da8de3a753dc4b1f71894f9f9debfdde6559599f303286e70aeb0c2"}, + {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:35b246ae3a2c042dc8f410c94bcb9754b18179cdb81ff9477a9089dbc9ecc186"}, + {file = "coverage-6.1.2-cp37-cp37m-win32.whl", hash = "sha256:0cde7d9fe2fb55ff68ebe7fb319ef188e9b88e0a3d1c9c5db7dd829cd93d2193"}, + {file = "coverage-6.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:958ac66272ff20e63d818627216e3d7412fdf68a2d25787b89a5c6f1eb7fdd93"}, + {file = "coverage-6.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a300b39c3d5905686c75a369d2a66e68fd01472ea42e16b38c948bd02b29e5bd"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d3855d5d26292539861f5ced2ed042fc2aa33a12f80e487053aed3bcb6ced13"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:586d38dfc7da4a87f5816b203ff06dd7c1bb5b16211ccaa0e9788a8da2b93696"}, + {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a34fccb45f7b2d890183a263578d60a392a1a218fdc12f5bce1477a6a68d4373"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bc1ee1318f703bc6c971da700d74466e9b86e0c443eb85983fb2a1bd20447263"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3f546f48d5d80a90a266769aa613bc0719cb3e9c2ef3529d53f463996dd15a9d"}, + {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd92ece726055e80d4e3f01fff3b91f54b18c9c357c48fcf6119e87e2461a091"}, + {file = "coverage-6.1.2-cp38-cp38-win32.whl", hash = "sha256:24ed38ec86754c4d5a706fbd5b52b057c3df87901a8610d7e5642a08ec07087e"}, + {file = "coverage-6.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:97ef6e9119bd39d60ef7b9cd5deea2b34869c9f0b9777450a7e3759c1ab09b9b"}, + {file = "coverage-6.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e5a8c947a2a89c56655ecbb789458a3a8e3b0cbf4c04250331df8f647b3de59"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a39590d1e6acf6a3c435c5d233f72f5d43b585f5be834cff1f21fec4afda225"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d2c2e3ce7b8cc932a2f918186964bd44de8c84e2f9ef72dc616f5bb8be22e71"}, + {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3348865798c077c695cae00da0924136bb5cc501f236cfd6b6d9f7a3c94e0ec4"}, + {file = "coverage-6.1.2-cp39-cp39-win32.whl", hash = "sha256:fae3fe111670e51f1ebbc475823899524e3459ea2db2cb88279bbfb2a0b8a3de"}, + {file = "coverage-6.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:af45eea024c0e3a25462fade161afab4f0d9d9e0d5a5d53e86149f74f0a35ecc"}, + {file = "coverage-6.1.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:eab14fdd410500dae50fd14ccc332e65543e7b39f6fc076fe90603a0e5d2f929"}, + {file = "coverage-6.1.2.tar.gz", hash = "sha256:d9a635114b88c0ab462e0355472d00a180a5fbfd8511e7f18e4ac32652e7d972"}, ] dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, @@ -1101,16 +1108,16 @@ entrypoints = [ {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, + {file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"}, + {file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] ipykernel = [ - {file = "ipykernel-5.5.5-py3-none-any.whl", hash = "sha256:29eee66548ee7c2edb7941de60c0ccf0a7a8dd957341db0a49c5e8e6a0fcb712"}, - {file = "ipykernel-5.5.5.tar.gz", hash = "sha256:e976751336b51082a89fc2099fb7f96ef20f535837c398df6eab1283c2070884"}, + {file = "ipykernel-5.5.6-py3-none-any.whl", hash = "sha256:66f824af1ef4650e1e2f6c42e1423074321440ef79ca3651a6cfd06a4e25e42f"}, + {file = "ipykernel-5.5.6.tar.gz", hash = "sha256:4ea44b90ae1f7c38987ad58ea0809562a17c2695a0499644326f334aecd369ec"}, ] ipython = [ {file = "ipython-7.16.1-py3-none-any.whl", hash = "sha256:2dbcc8c27ca7d3cfe4fcdff7f45b27f9a8d3edfa70ff8024a71c7a8eb5f09d64"}, @@ -1129,8 +1136,8 @@ jedi = [ {file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"}, ] jinja2 = [ - {file = "Jinja2-3.0.2-py3-none-any.whl", hash = "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c"}, - {file = "Jinja2-3.0.2.tar.gz", hash = "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45"}, + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, ] jsonschema = [ {file = "jsonschema-4.0.0-py3-none-any.whl", hash = "sha256:c773028c649441ab980015b5b622f4cd5134cf563daaf0235ca4b73cc3734f20"}, @@ -1141,8 +1148,8 @@ jupyter-client = [ {file = "jupyter_client-7.0.6.tar.gz", hash = "sha256:8b6e06000eb9399775e0a55c52df6c1be4766666209c22f90c2691ded0e338dc"}, ] jupyter-core = [ - {file = "jupyter_core-4.8.1-py3-none-any.whl", hash = "sha256:8dd262ec8afae95bd512518eb003bc546b76adbf34bf99410e9accdf4be9aa3a"}, - {file = "jupyter_core-4.8.1.tar.gz", hash = "sha256:ef210dcb4fca04de07f2ead4adf408776aca94d17151d6f750ad6ded0b91ea16"}, + {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"}, + {file = "jupyter_core-4.9.1.tar.gz", hash = "sha256:dce8a7499da5a53ae3afd5a9f4b02e5df1d57250cf48f3ad79da23b4778cd6fa"}, ] jupyterlab-pygments = [ {file = "jupyterlab_pygments-0.1.2-py2.py3-none-any.whl", hash = "sha256:abfb880fd1561987efaefcb2d2ac75145d2a5d0139b1876d5be806e32f630008"}, @@ -1153,28 +1160,12 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1183,27 +1174,14 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1213,12 +1191,6 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1257,8 +1229,8 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] nbclient = [ - {file = "nbclient-0.5.4-py3-none-any.whl", hash = "sha256:95a300c6fbe73721736cf13972a46d8d666f78794b832866ed7197a504269e11"}, - {file = "nbclient-0.5.4.tar.gz", hash = "sha256:6c8ad36a28edad4562580847f9f1636fe5316a51a323ed85a24a4ad37d4aefce"}, + {file = "nbclient-0.5.8-py3-none-any.whl", hash = "sha256:e85d4d6280d0a0237c1a6ec7a5e0757cf40a1fcb8c47253516b3a1f87f4ceae8"}, + {file = "nbclient-0.5.8.tar.gz", hash = "sha256:34f52cc9cb831a5d8ccd7031537e354c75dc61a24487f998712d1289de320a25"}, ] nbconvert = [ {file = "nbconvert-6.0.7-py3-none-any.whl", hash = "sha256:39e9f977920b203baea0be67eea59f7b37a761caa542abe80f5897ce3cf6311d"}, @@ -1273,12 +1245,12 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"}, ] notebook = [ - {file = "notebook-6.4.4-py3-none-any.whl", hash = "sha256:33488bdcc5cbef23c3cfa12cd51b0b5459a211945b5053d17405980611818149"}, - {file = "notebook-6.4.4.tar.gz", hash = "sha256:26b0095c568e307a310fd78818ad8ebade4f00462dada4c0e34cbad632b9085d"}, + {file = "notebook-6.4.5-py3-none-any.whl", hash = "sha256:f7b4362698fed34f44038de0517b2e5136c1e7c379797198c1736121d3d597bd"}, + {file = "notebook-6.4.5.tar.gz", hash = "sha256:872e20da9ae518bbcac3e4e0092d5bd35454e847dedb8cb9739e9f3b68406be0"}, ] packaging = [ - {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, - {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, + {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, + {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, ] pandocfilters = [ {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, @@ -1309,24 +1281,24 @@ pluggy = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] prometheus-client = [ - {file = "prometheus_client-0.11.0-py2.py3-none-any.whl", hash = "sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2"}, - {file = "prometheus_client-0.11.0.tar.gz", hash = "sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86"}, + {file = "prometheus_client-0.12.0-py2.py3-none-any.whl", hash = "sha256:317453ebabff0a1b02df7f708efbab21e3489e7072b61cb6957230dd004a0af0"}, + {file = "prometheus_client-0.12.0.tar.gz", hash = "sha256:1b12ba48cee33b9b0b9de64a1047cbd3c5f2d0ab6ebcead7ddda613a750ec3c5"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"}, - {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"}, + {file = "prompt_toolkit-3.0.22-py3-none-any.whl", hash = "sha256:48d85cdca8b6c4f16480c7ce03fd193666b62b0a21667ca56b4bb5ad679d1170"}, + {file = "prompt_toolkit-3.0.22.tar.gz", hash = "sha256:449f333dd120bd01f5d296a8ce1452114ba3a71fae7288d2f0ae2c918764fa72"}, ] ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pygments = [ {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, @@ -1372,23 +1344,24 @@ python-dateutil = [ {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"}, - {file = "pywin32-301-cp35-cp35m-win_amd64.whl", hash = "sha256:9635df6998a70282bd36e7ac2a5cef9ead1627b0a63b17c731312c7a0daebb72"}, - {file = "pywin32-301-cp36-cp36m-win32.whl", hash = "sha256:c866f04a182a8cb9b7855de065113bbd2e40524f570db73ef1ee99ff0a5cc2f0"}, - {file = "pywin32-301-cp36-cp36m-win_amd64.whl", hash = "sha256:dafa18e95bf2a92f298fe9c582b0e205aca45c55f989937c52c454ce65b93c78"}, - {file = "pywin32-301-cp37-cp37m-win32.whl", hash = "sha256:98f62a3f60aa64894a290fb7494bfa0bfa0a199e9e052e1ac293b2ad3cd2818b"}, - {file = "pywin32-301-cp37-cp37m-win_amd64.whl", hash = "sha256:fb3b4933e0382ba49305cc6cd3fb18525df7fd96aa434de19ce0878133bf8e4a"}, - {file = "pywin32-301-cp38-cp38-win32.whl", hash = "sha256:88981dd3cfb07432625b180f49bf4e179fb8cbb5704cd512e38dd63636af7a17"}, - {file = "pywin32-301-cp38-cp38-win_amd64.whl", hash = "sha256:8c9d33968aa7fcddf44e47750e18f3d034c3e443a707688a008a2e52bbef7e96"}, - {file = "pywin32-301-cp39-cp39-win32.whl", hash = "sha256:595d397df65f1b2e0beaca63a883ae6d8b6df1cdea85c16ae85f6d2e648133fe"}, - {file = "pywin32-301-cp39-cp39-win_amd64.whl", hash = "sha256:87604a4087434cd814ad8973bd47d6524bd1fa9e971ce428e76b62a5e0860fdf"}, + {file = "pywin32-302-cp310-cp310-win32.whl", hash = "sha256:251b7a9367355ccd1a4cd69cd8dd24bd57b29ad83edb2957cfa30f7ed9941efa"}, + {file = "pywin32-302-cp310-cp310-win_amd64.whl", hash = "sha256:79cf7e6ddaaf1cd47a9e50cc74b5d770801a9db6594464137b1b86aa91edafcc"}, + {file = "pywin32-302-cp36-cp36m-win32.whl", hash = "sha256:fe21c2fb332d03dac29de070f191bdbf14095167f8f2165fdc57db59b1ecc006"}, + {file = "pywin32-302-cp36-cp36m-win_amd64.whl", hash = "sha256:d3761ab4e8c5c2dbc156e2c9ccf38dd51f936dc77e58deb940ffbc4b82a30528"}, + {file = "pywin32-302-cp37-cp37m-win32.whl", hash = "sha256:48dd4e348f1ee9538dd4440bf201ea8c110ea6d9f3a5010d79452e9fa80480d9"}, + {file = "pywin32-302-cp37-cp37m-win_amd64.whl", hash = "sha256:496df89f10c054c9285cc99f9d509e243f4e14ec8dfc6d78c9f0bf147a893ab1"}, + {file = "pywin32-302-cp38-cp38-win32.whl", hash = "sha256:e372e477d938a49266136bff78279ed14445e00718b6c75543334351bf535259"}, + {file = "pywin32-302-cp38-cp38-win_amd64.whl", hash = "sha256:543552e66936378bd2d673c5a0a3d9903dba0b0a87235ef0c584f058ceef5872"}, + {file = "pywin32-302-cp39-cp39-win32.whl", hash = "sha256:2393c1a40dc4497fd6161b76801b8acd727c5610167762b7c3e9fd058ef4a6ab"}, + {file = "pywin32-302-cp39-cp39-win_amd64.whl", hash = "sha256:af5aea18167a31efcacc9f98a2ca932c6b6a6d91ebe31f007509e293dea12580"}, ] pywinpty = [ - {file = "pywinpty-1.1.4-cp36-none-win_amd64.whl", hash = "sha256:fb975976ad92be44801de95fdf2b0366747767cb0528478553aff85dd63ebb09"}, - {file = "pywinpty-1.1.4-cp37-none-win_amd64.whl", hash = "sha256:5d25b30a2f87105778bc2f57cb1271f58aaa25568921ef042faf001b3b0a7307"}, - {file = "pywinpty-1.1.4-cp38-none-win_amd64.whl", hash = "sha256:c5c3550100689632f6663f39865ef8716835dab1838a9eb9b472644af92673f8"}, - {file = "pywinpty-1.1.4-cp39-none-win_amd64.whl", hash = "sha256:ad60a336d92ac38e2159320db6d5999c4c2726a141c3ed3f9694021feb6a234e"}, - {file = "pywinpty-1.1.4.tar.gz", hash = "sha256:cc700c9d5a9fcebf677ac93a4943ca9a24db6e2f11a5f0e7e8e226184c5036f7"}, + {file = "pywinpty-1.1.6-cp310-none-win_amd64.whl", hash = "sha256:5f526f21b569b5610a61e3b6126259c76da979399598e5154498582df3736ade"}, + {file = "pywinpty-1.1.6-cp36-none-win_amd64.whl", hash = "sha256:7576e14f42b31fa98b62d24ded79754d2ea4625570c016b38eb347ce158a30f2"}, + {file = "pywinpty-1.1.6-cp37-none-win_amd64.whl", hash = "sha256:979ffdb9bdbe23db3f46fc7285fd6dbb86b80c12325a50582b211b3894072354"}, + {file = "pywinpty-1.1.6-cp38-none-win_amd64.whl", hash = "sha256:2308b1fc77545427610a705799d4ead5e7f00874af3fb148a03e202437456a7e"}, + {file = "pywinpty-1.1.6-cp39-none-win_amd64.whl", hash = "sha256:c703bf569a98ab7844b9daf37e88ab86f31862754ef6910a8b3824993a525c72"}, + {file = "pywinpty-1.1.6.tar.gz", hash = "sha256:8808f07350c709119cc4464144d6e749637f98e15acc1e5d3c37db1953d2eebc"}, ] pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, @@ -1396,32 +1369,24 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1429,8 +1394,6 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, @@ -1440,47 +1403,55 @@ pyzmq = [ {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, ] regex = [ - {file = "regex-2021.9.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66696c8336a1b5d1182464f3af3427cc760118f26d0b09a2ddc16a976a4d2637"}, - {file = "regex-2021.9.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d87459ad3ab40cd8493774f8a454b2e490d8e729e7e402a0625867a983e4e02"}, - {file = "regex-2021.9.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cf6a1e023caf5e9a982f5377414e1aeac55198831b852835732cfd0a0ca5ff"}, - {file = "regex-2021.9.30-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:255791523f80ea8e48e79af7120b4697ef3b74f6886995dcdb08c41f8e516be0"}, - {file = "regex-2021.9.30-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e502f8d4e5ef714bcc2c94d499684890c94239526d61fdf1096547db91ca6aa6"}, - {file = "regex-2021.9.30-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4907fb0f9b9309a5bded72343e675a252c2589a41871874feace9a05a540241e"}, - {file = "regex-2021.9.30-cp310-cp310-win32.whl", hash = "sha256:3be40f720af170a6b20ddd2ad7904c58b13d2b56f6734ee5d09bbdeed2fa4816"}, - {file = "regex-2021.9.30-cp310-cp310-win_amd64.whl", hash = "sha256:c2b180ed30856dfa70cfe927b0fd38e6b68198a03039abdbeb1f2029758d87e7"}, - {file = "regex-2021.9.30-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e6f2d2f93001801296fe3ca86515eb04915472b5380d4d8752f09f25f0b9b0ed"}, - {file = "regex-2021.9.30-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fa7ba9ab2eba7284e0d7d94f61df7af86015b0398e123331362270d71fab0b9"}, - {file = "regex-2021.9.30-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28040e89a04b60d579c69095c509a4f6a1a5379cd865258e3a186b7105de72c6"}, - {file = "regex-2021.9.30-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f588209d3e4797882cd238195c175290dbc501973b10a581086b5c6bcd095ffb"}, - {file = "regex-2021.9.30-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42952d325439ef223e4e9db7ee6d9087b5c68c5c15b1f9de68e990837682fc7b"}, - {file = "regex-2021.9.30-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cae4099031d80703954c39680323dabd87a69b21262303160776aa0e55970ca0"}, - {file = "regex-2021.9.30-cp36-cp36m-win32.whl", hash = "sha256:0de8ad66b08c3e673b61981b9e3626f8784d5564f8c3928e2ad408c0eb5ac38c"}, - {file = "regex-2021.9.30-cp36-cp36m-win_amd64.whl", hash = "sha256:b345ecde37c86dd7084c62954468a4a655fd2d24fd9b237949dd07a4d0dd6f4c"}, - {file = "regex-2021.9.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6f08187136f11e430638c2c66e1db091105d7c2e9902489f0dbc69b44c222b4"}, - {file = "regex-2021.9.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b55442650f541d195a535ccec33078c78a9521973fb960923da7515e9ed78fa6"}, - {file = "regex-2021.9.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87e9c489aa98f50f367fb26cc9c8908d668e9228d327644d7aa568d47e456f47"}, - {file = "regex-2021.9.30-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e2cb7d4909ed16ed35729d38af585673f1f0833e73dfdf0c18e5be0061107b99"}, - {file = "regex-2021.9.30-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0861e7f6325e821d5c40514c551fd538b292f8cc3960086e73491b9c5d8291d"}, - {file = "regex-2021.9.30-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:81fdc90f999b2147fc62e303440c424c47e5573a9b615ed5d43a5b832efcca9e"}, - {file = "regex-2021.9.30-cp37-cp37m-win32.whl", hash = "sha256:8c1ad61fa024195136a6b7b89538030bd00df15f90ac177ca278df9b2386c96f"}, - {file = "regex-2021.9.30-cp37-cp37m-win_amd64.whl", hash = "sha256:e3770781353a4886b68ef10cec31c1f61e8e3a0be5f213c2bb15a86efd999bc4"}, - {file = "regex-2021.9.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9c065d95a514a06b92a5026766d72ac91bfabf581adb5b29bc5c91d4b3ee9b83"}, - {file = "regex-2021.9.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9925985be05d54b3d25fd6c1ea8e50ff1f7c2744c75bdc4d3b45c790afa2bcb3"}, - {file = "regex-2021.9.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470f2c882f2672d8eeda8ab27992aec277c067d280b52541357e1acd7e606dae"}, - {file = "regex-2021.9.30-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad0517df22a97f1da20d8f1c8cb71a5d1997fa383326b81f9cf22c9dadfbdf34"}, - {file = "regex-2021.9.30-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e30838df7bfd20db6466fd309d9b580d32855f8e2c2e6d74cf9da27dcd9b63"}, - {file = "regex-2021.9.30-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b34d2335d6aedec7dcadd3f8283b9682fadad8b9b008da8788d2fce76125ebe"}, - {file = "regex-2021.9.30-cp38-cp38-win32.whl", hash = "sha256:e07049cece3462c626d650e8bf42ddbca3abf4aa08155002c28cb6d9a5a281e2"}, - {file = "regex-2021.9.30-cp38-cp38-win_amd64.whl", hash = "sha256:37868075eda024470bd0feab872c692ac4ee29db1e14baec103257bf6cc64346"}, - {file = "regex-2021.9.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d331f238a7accfbbe1c4cd1ba610d4c087b206353539331e32a8f05345c74aec"}, - {file = "regex-2021.9.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6348a7ab2a502cbdd0b7fd0496d614007489adb7361956b38044d1d588e66e04"}, - {file = "regex-2021.9.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b1cca6c23f19bee8dc40228d9c314d86d1e51996b86f924aca302fc8f8bf9"}, - {file = "regex-2021.9.30-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1f1125bc5172ab3a049bc6f4b9c0aae95a2a2001a77e6d6e4239fa3653e202b5"}, - {file = "regex-2021.9.30-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:638e98d069b14113e8afba6a54d1ca123f712c0d105e67c1f9211b2a825ef926"}, - {file = "regex-2021.9.30-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a0b0db6b49da7fa37ca8eddf9f40a8dbc599bad43e64f452284f37b6c34d91c"}, - {file = "regex-2021.9.30-cp39-cp39-win32.whl", hash = "sha256:9910869c472e5a6728680ca357b5846546cbbd2ab3ad5bef986ef0bc438d0aa6"}, - {file = "regex-2021.9.30-cp39-cp39-win_amd64.whl", hash = "sha256:3b71213ec3bad9a5a02e049f2ec86b3d7c3e350129ae0f4e2f99c12b5da919ed"}, - {file = "regex-2021.9.30.tar.gz", hash = "sha256:81e125d9ba54c34579e4539a967e976a3c56150796674aec318b1b2f49251be7"}, + {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, + {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, + {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, + {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, + {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, + {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, + {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, + {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, + {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, + {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, + {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, + {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, + {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, + {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, + {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, + {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, + {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, + {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, + {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, + {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, + {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, + {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, ] send2trash = [ {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, @@ -1503,8 +1474,8 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"}, - {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"}, + {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, + {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, ] tornado = [ {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, @@ -1590,9 +1561,8 @@ types-dataclasses = [ {file = "types_dataclasses-0.6.1-py3-none-any.whl", hash = "sha256:aa45bb0dacdba09e3195a36ff8337bba45eac03b6f31c4645e87b4a2a47830dd"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.0.0-py3-none-any.whl", hash = "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9"}, + {file = "typing_extensions-4.0.0.tar.gz", hash = "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, @@ -1603,8 +1573,8 @@ webencodings = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] widgetsnbextension = [ - {file = "widgetsnbextension-3.5.1-py2.py3-none-any.whl", hash = "sha256:bd314f8ceb488571a5ffea6cc5b9fc6cba0adaf88a9d2386b93a489751938bcd"}, - {file = "widgetsnbextension-3.5.1.tar.gz", hash = "sha256:079f87d87270bce047512400efd70238820751a11d2d8cb137a5a5bdbaf255c7"}, + {file = "widgetsnbextension-3.5.2-py2.py3-none-any.whl", hash = "sha256:763a9fdc836d141fa080005a886d63f66f73d56dba1fb5961afc239c77708569"}, + {file = "widgetsnbextension-3.5.2.tar.gz", hash = "sha256:e0731a60ba540cd19bbbefe771a9076dcd2dde90713a8f87f27f53f2d1db7727"}, ] zipp = [ {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, diff --git a/pyproject.toml b/pyproject.toml index 9291b5a444..c1eeca0b40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ include = ["rich/py.typed"] [tool.poetry.dependencies] python = "^3.6.2" -typing-extensions = { version = "^3.7.4", python = "<3.8" } +typing-extensions = { version = ">=3.7.4, <5.0", python = "<3.8" } dataclasses = { version = ">=0.7,<0.9", python = "<3.7" } pygments = "^2.6.0" commonmark = "^0.9.0" From 0349c2c581dd027f420233eb7f81fabc454c48d9 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 16 Nov 2021 13:19:16 +0000 Subject: [PATCH 101/287] formatting --- rich/protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/protocol.py b/rich/protocol.py index 1d64ff3ddd..ff69cc8b04 100644 --- a/rich/protocol.py +++ b/rich/protocol.py @@ -39,4 +39,4 @@ def rich_cast(renderable: object) -> "RenderableType": break rich_visited_set.add(renderable_type) - return cast(RenderableType, renderable) \ No newline at end of file + return cast(RenderableType, renderable) From 3c811afa9143c41d5decf392acb09260c243174b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 16 Nov 2021 14:41:30 +0000 Subject: [PATCH 102/287] special case for Text --- CHANGELOG.md | 1 + rich/console.py | 2 ++ tests/test_console.py | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c60d6bb523..5781588dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Allowed `__rich__` to work recursively +- Allowed Text classes to work with sep in print https://github.com/willmcgugan/rich/issues/1689 ## [10.13.0] - 2021-11-07 diff --git a/rich/console.py b/rich/console.py index 2a8a735cfa..1de49d7d5f 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1448,6 +1448,8 @@ def check_text() -> None: renderable, emoji=emoji, markup=markup, highlighter=_highlighter ) ) + elif isinstance(renderable, Text): + append_text(renderable) elif isinstance(renderable, ConsoleRenderable): check_text() append(renderable) diff --git a/tests/test_console.py b/tests/test_console.py index 7e5b003902..390e97be18 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -117,6 +117,24 @@ def test_print(): assert console.file.getvalue() == "foo\n" +def test_print_multiple(): + console = Console(file=io.StringIO(), color_system="truecolor") + console.print("foo", "bar") + assert console.file.getvalue() == "foo bar\n" + + +def test_print_text(): + console = Console(file=io.StringIO(), color_system="truecolor") + console.print(Text("foo", style="bold")) + assert console.file.getvalue() == "\x1B[1mfoo\x1B[0m\n" + + +def test_print_text_multiple(): + console = Console(file=io.StringIO(), color_system="truecolor") + console.print(Text("foo", style="bold"), Text("bar"), "baz") + assert console.file.getvalue() == "\x1B[1mfoo\x1B[0m bar baz\n" + + def test_print_json(): console = Console(file=io.StringIO(), color_system="truecolor") console.print_json('[false, true, null, "foo"]', indent=4) From 008854c40772f647dfcb873bc3489e8a1c02d598 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 16 Nov 2021 15:11:29 +0000 Subject: [PATCH 103/287] version bump --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5781588dbb..77dd5a0a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.14.0] - Unreleased +## [10.14.0] - 2021-11-16 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index c1eeca0b40..2ecc5ab682 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.13.1" +version = "10.14.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From caf52348c721dc01b4553e2f0e91a00941311af2 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Tue, 16 Nov 2021 11:09:47 -0500 Subject: [PATCH 104/287] Improve formatting of live command --- docs/source/live.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/live.rst b/docs/source/live.rst index f2c5cc76fc..51dd115d18 100644 --- a/docs/source/live.rst +++ b/docs/source/live.rst @@ -5,7 +5,7 @@ Live Display Progress bars and status indicators use a *live* display to animate parts of the terminal. You can build custom live displays with the :class:`~rich.live.Live` class. -For a demonstration of a live display, run the following command: +For a demonstration of a live display, run the following command:: python -m rich.live From 62ead7ededa8cc7da1c5098a192fb2f3191bbe84 Mon Sep 17 00:00:00 2001 From: Nicolas Simonds Date: Wed, 10 Nov 2021 09:10:03 -0800 Subject: [PATCH 105/287] Add a Text.from_ansi helper method Add a simple little helper to run `AnsiDecoder.decode_line` over "pre-cooked" inputs. Fixes issue: #1670 --- CHANGELOG.md | 4 ++++ CONTRIBUTORS.md | 1 + docs/source/text.rst | 5 +++++ rich/text.py | 34 ++++++++++++++++++++++++++++++++++ tests/test_text.py | 9 +++++++++ 5 files changed, 53 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77dd5a0a9b..2b1dc69d04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allowed `__rich__` to work recursively - Allowed Text classes to work with sep in print https://github.com/willmcgugan/rich/issues/1689 +### Added + +- Added a `rich.text.Text.from_ansi` helper method for handling pre-formatted input strings https://github.com/willmcgugan/rich/issues/1670 + ## [10.13.0] - 2021-11-07 ### Added diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 0e299be6e7..557f548e8d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -22,4 +22,5 @@ The following people have contributed to the development of Rich: - [Clément Robert](https://github.com/neutrinoceros) - [Tushar Sadhwani](https://github.com/tusharsadhwani) - [Tim Savage](https://github.com/timsavage) +- [Nicolas Simonds](https://github.com/0xDEC0DE) - [Gabriele N. Tornetta](https://github.com/p403n1x87) diff --git a/docs/source/text.rst b/docs/source/text.rst index b5f2eaf8f1..142b0639e1 100644 --- a/docs/source/text.rst +++ b/docs/source/text.rst @@ -26,6 +26,11 @@ Alternatively, you can construct styled text by calling :meth:`~rich.text.Text.a text.append(" World!") console.print(text) +If you would like to use text that is already formatted with ANSI codes, call :meth:`~rich.text.Text.from_ansi` to convert it to a ``Text`` object: + + text = Text.from_ansi("\033[1mHello, World!\033[0m") + console.print(text.spans) + Since building Text instances from parts is a common requirement, Rich offers :meth:`~rich.text.Text.assemble` which will combine strings or pairs of string and Style, and return a Text instance. The follow example is equivalent to the code above:: text = Text.assemble(("Hello", "bold magenta"), " World!") diff --git a/rich/text.py b/rich/text.py index 52ecd16042..c49e152b60 100644 --- a/rich/text.py +++ b/rich/text.py @@ -242,6 +242,40 @@ def from_markup( rendered_text.overflow = overflow return rendered_text + @classmethod + def from_ansi( + cls, + text: str, + *, + style: Union[str, Style] = "", + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + no_wrap: Optional[bool] = None, + end: str = "\n", + tab_size: Optional[int] = 8, + ) -> "Text": + """Create a Text object from pre-formatted ANSI. + + Args: + text (str): A string containing ANSI color codes. + style (Union[str, Style], optional): Base style for text. Defaults to "". + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + no_wrap (bool, optional): Disable text wrapping, or None for default. 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. + """ + from .ansi import AnsiDecoder + + decoded_text = AnsiDecoder().decode_line(text) + decoded_text.justify = justify + decoded_text.overflow = overflow + decoded_text.no_wrap = no_wrap + decoded_text.end = end + decoded_text.tab_size = tab_size + decoded_text.stylize(style) + return decoded_text + @classmethod def styled( cls, diff --git a/tests/test_text.py b/tests/test_text.py index 3727d1602c..6eecb9ee73 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -95,6 +95,15 @@ def test_from_markup(): assert text._spans == [Span(7, 13, "bold")] +def test_from_ansi(): + text = Text.from_ansi("Hello, \033[1mWorld!\033[0m") + text2 = Text.from_ansi("Hello, \033[1mWorld!\033[0m", style="red") + assert str(text) == "Hello, World!" + assert text._spans == [Span(7, 13, Style(bold=True))] + assert str(text2) == "Hello, World!" + assert text2._spans == [Span(7, 13, Style(bold=True)), Span(0, 13, "red")] + + def test_copy(): test = Text() test.append("Hello", "bold") From 52d91f764e04b9a5d34b09cf4d5c1e01b4572b75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Nov 2021 13:03:54 +0000 Subject: [PATCH 106/287] Bump black from 21.10b0 to 21.11b1 Bumps [black](https://github.com/psf/black) from 21.10b0 to 21.11b1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- poetry.lock | 57 ++++++++++++++++++++++++++++++++++++++++++++------ pyproject.toml | 2 +- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index e1bc7213f6..7992baa4af 100644 --- a/poetry.lock +++ b/poetry.lock @@ -62,7 +62,7 @@ python-versions = "*" [[package]] name = "black" -version = "21.10b0" +version = "21.11b1" description = "The uncompromising code formatter." category = "dev" optional = false @@ -74,9 +74,9 @@ dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" -regex = ">=2020.1.8" +regex = ">=2021.4.4" tomli = ">=0.2.6,<2.0.0" -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""} +typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = [ {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, @@ -934,7 +934,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "3b57479f41dfc0f68349be778c31f954f6f2c6dff1d23178e2ee000e45ea67ca" +content-hash = "8aa64ebd459c2f74eb6fa1e78eaf69e75e7a0599dfdd19bbeaa26de037ee2a1b" [metadata.files] appnope = [ @@ -971,8 +971,8 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] black = [ - {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, - {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, + {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"}, + {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"}, ] bleach = [ {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, @@ -1160,12 +1160,28 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1174,14 +1190,27 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1191,6 +1220,12 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1369,24 +1404,32 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1394,6 +1437,8 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, diff --git a/pyproject.toml b/pyproject.toml index 2ecc5ab682..6d906d8a94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ jupyter = ["ipywidgets"] [tool.poetry.dev-dependencies] pytest = "^6.2.5" -black = "^21.10b0" +black = "^21.11b1" mypy = "^0.910" pytest-cov = "^3.0.0" attrs = "^21.2.0" From 20b0195b7c4564f75bbe3de2391ed09c5c3771de Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 18 Nov 2021 14:13:36 +0100 Subject: [PATCH 107/287] Apply suggestions from code review Co-authored-by: Kim Thoenen Co-authored-by: Raphael Das Gupta --- README.de-ch.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.de-ch.md b/README.de-ch.md index b265745f15..4d33d22735 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -37,7 +37,7 @@ Rich funktioniert mit [Jupyter notebooks](https://jupyter.org/) ohni irgendwelch ## Installation -Installation mit `pip` oder mit dim liäblings PyPI Päckli-Mangager. +Installation mit `pip` oder mit dim liäblings PyPI Päckli-Manager. ``` pip install rich @@ -326,7 +326,7 @@ Lueg s Bispiil Script [tree.py](https://github.com/willmcgugan/rich/blob/master/
Spaltene -Rich cha Inhalt i hübsche [Spaltene](https://rich.readthedocs.io/en/latest/columns.html) darstelle mit glichä oder optimale Breiti. Do isch e ganz eifachi kopii vom (MacOS / Linux) `ls` Befehl wo Ordner in Columns darstellt +Rich cha Inhalt i hübsche [Spaltene](https://rich.readthedocs.io/en/latest/columns.html) darstelle mit glichä oder optimale Breiti. Do isch e ganz eifachi kopii vom (MacOS / Linux) `ls` Befehl wo Ordner in Spaltene darstellt ```python import os @@ -339,7 +339,7 @@ directory = os.listdir(sys.argv[1]) print(Columns(directory)) ``` -De folgend Screenshot isch d Usgob vom [Spalte-Bispiil](https://github.com/willmcgugan/rich/blob/master/examples/columns.py), wo Date vonnere API hollt ond in Colums darstellt: +De folgend Screenshot isch d Usgob vom [Spalte-Bispiil](https://github.com/willmcgugan/rich/blob/master/examples/columns.py), wo Date vonnere API hollt ond in Spaltene darstellt: ![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) @@ -406,7 +406,7 @@ Das wird d Usgob ungefär wie s Folgende geh:
Tracebacks -Rich cha [wunderschöni Tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) generiäre wo eifach zum läse sind und meh Code als de Standard Python-Traceback darstellt. Du chasch Rich als default Traceback Handler setzä ond alli nöd abfangene Exceptions werded mit Rich dargstellt. +Rich cha [wunderschöni Tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) generiäre wo eifach zum läse sind und meh Code als de Standard-Python-Traceback darstellt. Du chasch Rich als default Traceback Handler setzä ond alli nöd abfangene Exceptions werded mit Rich dargstellt. So gsiets ungefär ufemen OSX (ähnloch uf Linux) us: From 65f1b7ffc643f3901c8328d859b8444c79ff5e67 Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Thu, 18 Nov 2021 17:25:57 +0100 Subject: [PATCH 108/287] Update README.pt-br.md :kissing: --- README.pt-br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.pt-br.md b/README.pt-br.md index 677f078251..d4180467af 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -125,7 +125,7 @@ Confira a [documentação do inspect](https://rich.readthedocs.io/en/latest/refe # A biblioteca Rich -O Rich possui vários _renderizaveis_ nativos que podem ser usados para criar outputs elegantes no seu CLI e ajudar a debugar o código. +O Rich possui vários _renderizáveis_ nativos que podem ser usados para criar outputs elegantes no seu CLI e ajudar a debugar o código. Clique nos itens a seguir para expandir os detalhes: From ba5d0c2cfc35e929022dbe26c2edb4c210cb11ee Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 20 Nov 2021 10:53:06 +0000 Subject: [PATCH 109/287] changelog tweak --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c96b72def..637c5d852e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.15.0] - Unreleased + +### Added + +- Added dynamic_progress.py to examples + ## [10.14.0] - 2021-11-16 ### Fixed @@ -30,10 +36,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added json.dumps parameters to print_json https://github.com/willmcgugan/rich/issues/1638 -### Added - -- Added dynamic_progress.py to examples - ### Fixed - Fixed an edge case bug when console module try to detect if they are in a tty at the end of a pytest run From 55e11902ab7d1c959122baaee4f98966fd30209f Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 25 Nov 2021 20:47:09 +0000 Subject: [PATCH 110/287] optimizations --- CHANGELOG.md | 5 ++ poetry.lock | 52 +++++++------- pyproject.toml | 2 +- rich/__main__.py | 6 +- rich/cells.py | 40 +++++++---- rich/console.py | 16 ++++- rich/padding.py | 10 +-- rich/segment.py | 35 ++++++--- rich/table.py | 137 +++++++++++++++++++----------------- tests/test_console.py | 17 +++++ tests/test_segment.py | 1 + tools/stress_test_pretty.py | 6 +- 12 files changed, 202 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 637c5d852e..e460188389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added dynamic_progress.py to examples +- Added ConsoleOptions.update_height + +### Changed + +- Some optimizations for simple strings (with only single cell widths) ## [10.14.0] - 2021-11-16 diff --git a/poetry.lock b/poetry.lock index e1bc7213f6..ef59029593 100644 --- a/poetry.lock +++ b/poetry.lock @@ -62,7 +62,7 @@ python-versions = "*" [[package]] name = "black" -version = "21.10b0" +version = "21.11b1" description = "The uncompromising code formatter." category = "dev" optional = false @@ -74,9 +74,9 @@ dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" -regex = ">=2020.1.8" +regex = ">=2021.4.4" tomli = ">=0.2.6,<2.0.0" -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""} +typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = [ {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, @@ -295,7 +295,7 @@ test = ["pytest (>=3.6.0)", "pytest-cov", "mock"] [[package]] name = "jedi" -version = "0.18.0" +version = "0.18.1" description = "An autocompletion tool for Python that can be used for text editors." category = "main" optional = true @@ -306,7 +306,7 @@ parso = ">=0.8.0,<0.9.0" [package.extras] qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" @@ -435,7 +435,7 @@ python-versions = "*" [[package]] name = "nbclient" -version = "0.5.8" +version = "0.5.9" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." category = "main" optional = true @@ -511,7 +511,7 @@ python-versions = ">=3.5" [[package]] name = "notebook" -version = "6.4.5" +version = "6.4.6" description = "A web-based notebook environment for interactive computing" category = "main" optional = true @@ -526,9 +526,10 @@ jupyter-client = ">=5.3.4" jupyter-core = ">=4.6.1" nbconvert = "*" nbformat = "*" +nest-asyncio = ">=1.5" prometheus-client = "*" pyzmq = ">=17" -Send2Trash = ">=1.5.0" +Send2Trash = ">=1.8.0" terminado = ">=0.8.3" tornado = ">=6.1" traitlets = ">=4.2.1" @@ -540,14 +541,14 @@ test = ["pytest", "coverage", "requests", "nbval", "selenium", "pytest-cov", "re [[package]] name = "packaging" -version = "21.2" +version = "21.3" description = "Core utilities for Python packages" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2,<3" +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pandocfilters" @@ -679,11 +680,14 @@ python-versions = ">=3.5" [[package]] name = "pyparsing" -version = "2.4.7" +version = "3.0.6" description = "Python parsing module" category = "main" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyrsistent" @@ -971,8 +975,8 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] black = [ - {file = "black-21.10b0-py3-none-any.whl", hash = "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b"}, - {file = "black-21.10b0.tar.gz", hash = "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33"}, + {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"}, + {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"}, ] bleach = [ {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, @@ -1132,8 +1136,8 @@ ipywidgets = [ {file = "ipywidgets-7.6.5.tar.gz", hash = "sha256:00974f7cb4d5f8d494c19810fedb9fa9b64bffd3cda7c2be23c133a1ad3c99c5"}, ] jedi = [ - {file = "jedi-0.18.0-py2.py3-none-any.whl", hash = "sha256:18456d83f65f400ab0c2d3319e48520420ef43b23a086fdc05dff34132f0fb93"}, - {file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"}, + {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, + {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, ] jinja2 = [ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, @@ -1229,8 +1233,8 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] nbclient = [ - {file = "nbclient-0.5.8-py3-none-any.whl", hash = "sha256:e85d4d6280d0a0237c1a6ec7a5e0757cf40a1fcb8c47253516b3a1f87f4ceae8"}, - {file = "nbclient-0.5.8.tar.gz", hash = "sha256:34f52cc9cb831a5d8ccd7031537e354c75dc61a24487f998712d1289de320a25"}, + {file = "nbclient-0.5.9-py3-none-any.whl", hash = "sha256:8a307be4129cce5f70eb83a57c3edbe45656623c31de54e38bb6fdfbadc428b3"}, + {file = "nbclient-0.5.9.tar.gz", hash = "sha256:99e46ddafacd0b861293bf246fed8540a184adfa3aa7d641f89031ec070701e0"}, ] nbconvert = [ {file = "nbconvert-6.0.7-py3-none-any.whl", hash = "sha256:39e9f977920b203baea0be67eea59f7b37a761caa542abe80f5897ce3cf6311d"}, @@ -1245,12 +1249,12 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"}, ] notebook = [ - {file = "notebook-6.4.5-py3-none-any.whl", hash = "sha256:f7b4362698fed34f44038de0517b2e5136c1e7c379797198c1736121d3d597bd"}, - {file = "notebook-6.4.5.tar.gz", hash = "sha256:872e20da9ae518bbcac3e4e0092d5bd35454e847dedb8cb9739e9f3b68406be0"}, + {file = "notebook-6.4.6-py3-none-any.whl", hash = "sha256:5cad068fa82cd4fb98d341c052100ed50cd69fbfb4118cb9b8ab5a346ef27551"}, + {file = "notebook-6.4.6.tar.gz", hash = "sha256:7bcdf79bd1cda534735bd9830d2cbedab4ee34d8fe1df6e7b946b3aab0902ba3"}, ] packaging = [ - {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, - {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pandocfilters = [ {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, @@ -1305,8 +1309,8 @@ pygments = [ {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, ] pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, + {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, + {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, ] pyrsistent = [ {file = "pyrsistent-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f4c8cabb46ff8e5d61f56a037974228e978f26bfefce4f61a4b1ac0ba7a2ab72"}, diff --git a/pyproject.toml b/pyproject.toml index 2ecc5ab682..5d65e77d34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.14.0" +version = "10.15.0-alpha3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/__main__.py b/rich/__main__.py index df084b69a2..5d1abd10d5 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -222,7 +222,10 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: test_card = make_test_card() # Print once to warm cache + start = process_time() console.print(test_card) + pre_cache_taken = round((process_time() - start) * 1000.0, 1) + console.file = io.StringIO() start = process_time() @@ -234,7 +237,8 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: for line in text.splitlines(True): print(line, end="") - print(f"rendered in {taken}ms") + print(f"rendered in {pre_cache_taken}ms (cold cache)") + print(f"rendered in {taken}ms (warm cache)") from rich.panel import Panel diff --git a/rich/cells.py b/rich/cells.py index b02f4b8681..aa22a56e4c 100644 --- a/rich/cells.py +++ b/rich/cells.py @@ -1,9 +1,13 @@ from functools import lru_cache +import re from typing import Dict, List from ._cell_widths import CELL_WIDTHS from ._lru_cache import LRUCache +# Regex to match sequece of the most common character ranges +_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match + def cell_len(text: str, _cache: Dict[str, int] = LRUCache(1024 * 4)) -> int: """Get the number of cells required to display text. @@ -12,16 +16,19 @@ def cell_len(text: str, _cache: Dict[str, int] = LRUCache(1024 * 4)) -> int: text (str): Text to display. Returns: - int: Number of cells required to display the text. + int: Get the number of cells required to display text. """ - cached_result = _cache.get(text, None) - if cached_result is not None: - return cached_result - - _get_size = get_character_cell_size - total_size = sum(_get_size(character) for character in text) - if len(text) <= 64: - _cache[text] = total_size + + if _is_single_cell_widths(text): + return len(text) + else: + cached_result = _cache.get(text, None) + if cached_result is not None: + return cached_result + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + if len(text) <= 64: + _cache[text] = total_size return total_size @@ -35,12 +42,10 @@ def get_character_cell_size(character: str) -> int: Returns: int: Number of cells (0, 1 or 2) occupied by that character. """ - - codepoint = ord(character) - if 127 > codepoint > 31: - # Shortcut for ascii + if _is_single_cell_widths(character): return 1 - return _get_codepoint_cell_size(codepoint) + + return _get_codepoint_cell_size(ord(character)) @lru_cache(maxsize=4096) @@ -74,6 +79,13 @@ def _get_codepoint_cell_size(codepoint: int) -> int: def set_cell_size(text: str, total: int) -> str: """Set the length of a string to fit within given number of cells.""" + + if _is_single_cell_widths(text): + size = len(text) + if size < total: + return text + " " * (total - size) + return text[:total] + if not total: return "" cell_size = cell_len(text) diff --git a/rich/console.py b/rich/console.py index 1de49d7d5f..901d19e77f 100644 --- a/rich/console.py +++ b/rich/console.py @@ -212,6 +212,19 @@ def update_width(self, width: int) -> "ConsoleOptions": options.min_width = options.max_width = max(0, width) return options + def update_height(self, height: int) -> "ConsoleOptions": + """Update the height, and return a copy. + + Args: + height (int): New height + + Returns: + ~ConsoleOptions: New Console options instance. + """ + options = self.copy() + options.max_height = options.height = height + return options + def update_dimensions(self, width: int, height: int) -> "ConsoleOptions": """Update the width and height, and return a copy. @@ -224,8 +237,7 @@ def update_dimensions(self, width: int, height: int) -> "ConsoleOptions": """ options = self.copy() options.min_width = options.max_width = max(0, width) - options.height = height - options.max_height = height + options.height = options.max_height = height return options diff --git a/rich/padding.py b/rich/padding.py index da1eb3a8d6..1d1f4a553c 100644 --- a/rich/padding.py +++ b/rich/padding.py @@ -89,11 +89,13 @@ def __rich_console__( + self.right, options.max_width, ) + render_options = options.update_width(width - self.left - self.right) + if render_options.height is not None: + render_options = render_options.update_height( + height=render_options.height - self.top - self.bottom + ) lines = console.render_lines( - self.renderable, - options.update_width(width - self.left - self.right), - style=style, - pad=True, + self.renderable, render_options, style=style, pad=True ) _Segment = Segment diff --git a/rich/segment.py b/rich/segment.py index 97ddc8d0aa..c9bb4a494f 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -15,7 +15,12 @@ Union, ) -from .cells import cell_len, get_character_cell_size, set_cell_size +from .cells import ( + _is_single_cell_widths, + cell_len, + get_character_cell_size, + set_cell_size, +) from .repr import Result, rich_repr from .style import Style @@ -97,19 +102,14 @@ def _split_cells(cls, segment: "Segment", cut: int) -> Tuple["Segment", "Segment text, style, control = segment _Segment = Segment - if cut >= segment.cell_length: - return segment, _Segment("", style, control) - if len(text) == segment.cell_length: - # Fast path with all 1 cell characters - return ( - _Segment(text[:cut], style, control), - _Segment(text[cut:], style, control), - ) + cell_length = segment.cell_length + if cut >= cell_length: + return segment, _Segment("", style, control) cell_size = get_character_cell_size - pos = int((cut / segment.cell_length) * len(text)) + pos = int((cut / cell_length) * len(text)) before = text[:pos] cell_pos = cell_len(before) @@ -143,6 +143,17 @@ def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]: Returns: Tuple[Segment, Segment]: Two segments. """ + text, style, control = self + + if _is_single_cell_widths(text): + # Fast path with all 1 cell characters + if cut >= len(text): + return self, Segment("", style, control) + return ( + Segment(text[:cut], style, control), + Segment(text[cut:], style, control), + ) + return self._split_cells(self, cut) @classmethod @@ -341,7 +352,8 @@ def get_line_length(cls, line: List["Segment"]) -> int: Returns: int: The length of the line. """ - return sum(segment.cell_length for segment in line) + _cell_len = cell_len + return sum(_cell_len(segment.text) for segment in line) @classmethod def get_shape(cls, lines: List[List["Segment"]]) -> Tuple[int, int]: @@ -492,6 +504,7 @@ def divide( """ split_segments: List["Segment"] = [] add_segment = split_segments.append + iter_cuts = iter(cuts) while True: diff --git a/rich/table.py b/rich/table.py index 4b57f6e08d..24d7afbd26 100644 --- a/rich/table.py +++ b/rich/table.py @@ -848,72 +848,77 @@ def _render( from rich.highlighter import ReprHighlighter from rich.table import Table as Table - table = Table( - title="Star Wars Movies", - caption="Rich example table", - caption_justify="right", - ) + from ._timer import timer - table.add_column("Released", header_style="bright_cyan", style="cyan", no_wrap=True) - table.add_column("Title", style="magenta") - table.add_column("Box Office", justify="right", style="green") + with timer("Table render"): + table = Table( + title="Star Wars Movies", + caption="Rich example table", + caption_justify="right", + ) - table.add_row( - "Dec 20, 2019", - "Star Wars: The Rise of Skywalker", - "$952,110,690", - ) - table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") - table.add_row( - "Dec 15, 2017", - "Star Wars Ep. V111: The Last Jedi", - "$1,332,539,889", - style="on black", - end_section=True, - ) - table.add_row( - "Dec 16, 2016", - "Rogue One: A Star Wars Story", - "$1,332,439,889", - ) + table.add_column( + "Released", header_style="bright_cyan", style="cyan", no_wrap=True + ) + table.add_column("Title", style="magenta") + table.add_column("Box Office", justify="right", style="green") + + table.add_row( + "Dec 20, 2019", + "Star Wars: The Rise of Skywalker", + "$952,110,690", + ) + table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") + table.add_row( + "Dec 15, 2017", + "Star Wars Ep. V111: The Last Jedi", + "$1,332,539,889", + style="on black", + end_section=True, + ) + table.add_row( + "Dec 16, 2016", + "Rogue One: A Star Wars Story", + "$1,332,439,889", + ) - def header(text: str) -> None: - console.print() - console.rule(highlight(text)) - console.print() - - console = Console() - highlight = ReprHighlighter() - header("Example Table") - console.print(table, justify="center") - - table.expand = True - header("expand=True") - console.print(table) - - table.width = 50 - header("width=50") - - console.print(table, justify="center") - - table.width = None - table.expand = False - table.row_styles = ["dim", "none"] - header("row_styles=['dim', 'none']") - - console.print(table, justify="center") - - table.width = None - table.expand = False - table.row_styles = ["dim", "none"] - table.leading = 1 - header("leading=1, row_styles=['dim', 'none']") - console.print(table, justify="center") - - table.width = None - table.expand = False - table.row_styles = ["dim", "none"] - table.show_lines = True - table.leading = 0 - header("show_lines=True, row_styles=['dim', 'none']") - console.print(table, justify="center") + def header(text: str) -> None: + console.print() + console.rule(highlight(text)) + console.print() + + console = Console() + highlight = ReprHighlighter() + header("Example Table") + console.print(table, justify="center") + + table.expand = True + header("expand=True") + console.print(table) + + table.width = 50 + header("width=50") + + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + header("row_styles=['dim', 'none']") + + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + table.leading = 1 + header("leading=1, row_styles=['dim', 'none']") + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + table.show_lines = True + table.leading = 0 + header("show_lines=True, row_styles=['dim', 'none']") + console.print(table, justify="center") diff --git a/tests/test_console.py b/tests/test_console.py index 390e97be18..4b21e397e9 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -87,6 +87,23 @@ def test_console_options_update(): assert options_copy == options and options_copy is not options +def test_console_options_update_height(): + options = ConsoleOptions( + ConsoleDimensions(80, 25), + max_height=25, + legacy_windows=False, + min_width=10, + max_width=20, + is_terminal=False, + encoding="utf-8", + ) + assert options.height is None + render_options = options.update_height(12) + assert options.height is None + assert render_options.height == 12 + assert render_options.max_height == 12 + + def test_init(): console = Console(color_system=None) assert console._color_system == None diff --git a/tests/test_segment.py b/tests/test_segment.py index c3cb222c35..dcf7b218ce 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -223,6 +223,7 @@ def test_divide_edge_2(): @pytest.mark.parametrize( "text,split,result", [ + ("XX", 4, (Segment("XX"), Segment(""))), ("X", 1, (Segment("X"), Segment(""))), ("💩", 1, (Segment(" "), Segment(" "))), ("XY", 1, (Segment("X"), Segment("Y"))), diff --git a/tools/stress_test_pretty.py b/tools/stress_test_pretty.py index 4a945d1114..334f9cf544 100644 --- a/tools/stress_test_pretty.py +++ b/tools/stress_test_pretty.py @@ -1,6 +1,7 @@ from rich.console import Console from rich.panel import Panel from rich.pretty import Pretty +from rich._timer import timer DATA = { "foo": [1, 2, 3, (), {}, (1, 2, 3), {4, 5, 6, (7, 8, 9)}, "Hello, World"], @@ -15,5 +16,6 @@ }, } console = Console() -for w in range(130): - console.print(Panel(Pretty(DATA, indent_guides=True), width=w)) +with timer("Stress test"): + for w in range(130): + console.print(Panel(Pretty(DATA, indent_guides=True), width=w)) From 85771e2b0b003c1b1d02eb88f2670be516b11196 Mon Sep 17 00:00:00 2001 From: Paul Sanders Date: Sat, 27 Nov 2021 08:33:06 -0500 Subject: [PATCH 111/287] Fix failing codespell test --- rich/cells.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/cells.py b/rich/cells.py index aa22a56e4c..e824ea2a6d 100644 --- a/rich/cells.py +++ b/rich/cells.py @@ -5,7 +5,7 @@ from ._cell_widths import CELL_WIDTHS from ._lru_cache import LRUCache -# Regex to match sequece of the most common character ranges +# Regex to match sequence of the most common character ranges _is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match From 07d51ffc1aee6f16bd2e5a25b4e82850fb9ed778 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 27 Nov 2021 19:41:29 +0000 Subject: [PATCH 112/287] race condition and tests --- CHANGELOG.md | 5 +++++ rich/console.py | 11 ++++++++--- rich/file_proxy.py | 2 +- rich/live.py | 31 ++++++++++++++----------------- rich/pager.py | 2 +- rich/pretty.py | 2 +- tests/test_cells.py | 1 + tests/test_pretty.py | 13 +++++++++++++ tests/test_progress.py | 7 +++++++ tests/test_protocol.py | 15 +++++++++++++++ tests/test_repr.py | 10 ++++++++++ 11 files changed, 76 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e460188389..775a978a3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Some optimizations for simple strings (with only single cell widths) +### Fixed + +- Fixed issue with progress bar not rendering markup https://github.com/willmcgugan/rich/issues/1721 +- Fixed race condition when exiting Live https://github.com/willmcgugan/rich/issues/1530 + ## [10.14.0] - 2021-11-16 ### Fixed diff --git a/rich/console.py b/rich/console.py index 901d19e77f..fc340bc24e 100644 --- a/rich/console.py +++ b/rich/console.py @@ -825,20 +825,25 @@ def push_render_hook(self, hook: RenderHook) -> None: Args: hook (RenderHook): Render hook instance. """ - - self._render_hooks.append(hook) + with self._lock: + self._render_hooks.append(hook) def pop_render_hook(self) -> None: """Pop the last renderhook from the stack.""" - self._render_hooks.pop() + with self._lock: + self._render_hooks.pop() def __enter__(self) -> "Console": """Own context manager to enter buffer context.""" self._enter_buffer() + if self._live: + self._live._lock.acquire() return self def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: """Exit buffer context.""" + if self._live: + self._live._lock.release() self._exit_buffer() def begin_capture(self) -> None: diff --git a/rich/file_proxy.py b/rich/file_proxy.py index 99a6922cb4..3ec593a5a4 100644 --- a/rich/file_proxy.py +++ b/rich/file_proxy.py @@ -44,7 +44,7 @@ def write(self, text: str) -> int: output = Text("\n").join( self.__ansi_decoder.decode_line(line) for line in lines ) - console.print(output, markup=False, emoji=False, highlight=False) + console.print(output) return len(text) def flush(self) -> None: diff --git a/rich/live.py b/rich/live.py index 8097f7d2e6..c61f233ccd 100644 --- a/rich/live.py +++ b/rich/live.py @@ -133,12 +133,16 @@ def stop(self) -> None: try: if self.auto_refresh and self._refresh_thread is not None: self._refresh_thread.stop() + self._refresh_thread.join() # allow it to fully render on the last even if overflow self.vertical_overflow = "visible" if not self._alt_screen and not self.console.is_jupyter: self.refresh() finally: + if self._refresh_thread is not None: + self._refresh_thread = None + self._disable_redirect_io() self.console.pop_render_hook() if not self._alt_screen and self.console.is_terminal: @@ -147,18 +151,15 @@ def stop(self) -> None: if self._alt_screen: self.console.set_alt_screen(False) - if self._refresh_thread is not None: - self._refresh_thread.join() - self._refresh_thread = None - if self.transient and not self._alt_screen: - self.console.control(self._live_render.restore_cursor()) - if self.ipy_widget is not None: # pragma: no cover - if self.transient: - self.ipy_widget.close() - else: - # jupyter last refresh must occur after console pop render hook - # i am not sure why this is needed - self.refresh() + if self.transient and not self._alt_screen: + self.console.control(self._live_render.restore_cursor()) + if self.ipy_widget is not None: # pragma: no cover + if self.transient: + self.ipy_widget.close() + else: + # jupyter last refresh must occur after console pop render hook + # i am not sure why this is needed + self.refresh() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) @@ -255,11 +256,7 @@ def process_renderables( if self._alt_screen else self._live_render.position_cursor() ) - renderables = [ - reset, - *renderables, - self._live_render, - ] + renderables = [reset, *renderables, self._live_render] elif ( not self._started and not self.transient ): # if it is finished render the final output for files or dumb_terminals diff --git a/rich/pager.py b/rich/pager.py index ea9bdf08fa..dbfb973e36 100644 --- a/rich/pager.py +++ b/rich/pager.py @@ -17,7 +17,7 @@ def show(self, content: str) -> None: class SystemPager(Pager): """Uses the pager installed on the system.""" - def _pager(self, content: str) -> Any: + def _pager(self, content: str) -> Any: #  pragma: no cover return __import__("pydoc").pager(content) def show(self, content: str) -> None: diff --git a/rich/pretty.py b/rich/pretty.py index 7e916511a0..f705911210 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -78,7 +78,7 @@ def _is_dataclass_repr(obj: object) -> bool: # Catching all exceptions in case something is missing on a non CPython implementation try: return obj.__repr__.__code__.co_filename == dataclasses.__file__ - except Exception: + except Exception: # pragma: no coverage return False diff --git a/tests/test_cells.py b/tests/test_cells.py index c332f2a541..d64317f3ba 100644 --- a/tests/test_cells.py +++ b/tests/test_cells.py @@ -13,6 +13,7 @@ def test_set_cell_size(): assert cells.set_cell_size("😽😽", 3) == "😽 " assert cells.set_cell_size("😽😽", 2) == "😽" assert cells.set_cell_size("😽😽", 1) == " " + assert cells.set_cell_size("😽😽", 5) == "😽😽 " def test_set_cell_size_infinite(): diff --git a/tests/test_pretty.py b/tests/test_pretty.py index 9fd2bdd9d9..d2e8299637 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -108,6 +108,19 @@ def __repr__(self): assert result == expected +def test_broken_getattr(): + class BrokenAttr: + def __getattr__(self, name): + 1 / 0 + + def __repr__(self): + return "BrokenAttr()" + + test = BrokenAttr() + result = pretty_repr(test) + assert result == "BrokenAttr()" + + def test_recursive(): test = [] test.append(test) diff --git a/tests/test_progress.py b/tests/test_progress.py index 303c2e0871..2020f91ffb 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -68,6 +68,13 @@ def test_text_column(): assert text == Text("[b]bar") +def test_time_elapsed_column(): + column = TimeElapsedColumn() + task = Task(1, "test", 100, 20, _get_time=lambda: 1.0) + text = column.render(task) + assert str(text) == "-:--:--" + + def test_time_remaining_column(): class FakeTask(Task): time_remaining = 60 diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 50d129a716..6337ef5df6 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -18,6 +18,21 @@ def test_rich_cast(): assert console.file.getvalue() == "Foo\n" +class Fake: + def __getattr__(self, name): + return 12 + + def __repr__(self) -> str: + return "Fake()" + + +def test_rich_cast_fake(): + fake = Fake() + console = Console(file=io.StringIO()) + console.print(fake) + assert console.file.getvalue() == "Fake()\n" + + def test_rich_cast_container(): foo = Foo() console = Console(file=io.StringIO(), legacy_windows=False) diff --git a/tests/test_repr.py b/tests/test_repr.py index c4f8bd09aa..c47b76b12f 100644 --- a/tests/test_repr.py +++ b/tests/test_repr.py @@ -59,6 +59,16 @@ def test_rich_repr() -> None: assert (repr(Foo("hello", bar=3))) == "Foo('hello', 'hello', bar=3, egg=1)" +def test_rich_repr_positional_only() -> None: + @rich.repr.auto + class PosOnly: + def __init__(self, foo, /): + self.foo = 1 + + p = PosOnly(1) + assert repr(p) == "PosOnly(1)" + + def test_rich_angular() -> None: assert (repr(Bar("hello"))) == "" assert (repr(Bar("hello", bar=3))) == "" From 26509386bc8382e2283d3777e38a00e92b12f690 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 27 Nov 2021 19:52:39 +0000 Subject: [PATCH 113/287] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 775a978a3a..249e4f5143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added dynamic_progress.py to examples - Added ConsoleOptions.update_height +- Fixed Padding not respecting height ### Changed From 5eafdbcee2b5429dfaafba9a0ce762c3d2baa0e6 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 28 Nov 2021 12:44:58 +0000 Subject: [PATCH 114/287] version bump --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 249e4f5143..2835c32125 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.15.0] - Unreleased +## [10.15.0] - 2021-11-28 ### Added diff --git a/pyproject.toml b/pyproject.toml index 5d65e77d34..fa524360ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.15.0-alpha3" +version = "10.15.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From 1799d3ba0d29593235b32f21d259ddbb3b7d31c4 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 28 Nov 2021 13:05:03 +0000 Subject: [PATCH 115/287] conditional test --- tests/test_repr.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/tests/test_repr.py b/tests/test_repr.py index c47b76b12f..3c2f48a462 100644 --- a/tests/test_repr.py +++ b/tests/test_repr.py @@ -1,10 +1,22 @@ import pytest +import sys from typing import Optional from rich.console import Console import rich.repr +skip_py36 = pytest.mark.skipif( + sys.version_info.minor == 6 and sys.version_info.major == 3, + reason="rendered differently on py3.6", +) + +skip_py37 = pytest.mark.skipif( + sys.version_info.minor == 7 and sys.version_info.major == 3, + reason="rendered differently on py3.7", +) + + @rich.repr.auto class Foo: def __init__(self, foo: str, bar: Optional[int] = None, egg: int = 1): @@ -59,13 +71,21 @@ def test_rich_repr() -> None: assert (repr(Foo("hello", bar=3))) == "Foo('hello', 'hello', bar=3, egg=1)" +@skip_py36 +@skip_py37 def test_rich_repr_positional_only() -> None: - @rich.repr.auto - class PosOnly: - def __init__(self, foo, /): - self.foo = 1 - - p = PosOnly(1) + _locals = locals().copy() + exec( + """\ +@rich.repr.auto +class PosOnly: + def __init__(self, foo, /): + self.foo = 1 + """, + globals(), + _locals, + ) + p = _locals["PosOnly"](1) assert repr(p) == "PosOnly(1)" From aeac63da7a240400c9fc3c334a545f68f4cc9720 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 28 Nov 2021 13:09:08 +0000 Subject: [PATCH 116/287] conditional test --- tests/test_pretty.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_pretty.py b/tests/test_pretty.py index d2e8299637..3a4ea6c075 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -97,6 +97,7 @@ def test_small_width(): assert result == expected +@skip_py36 def test_broken_repr(): class BrokenRepr: def __repr__(self): From 86032f6354411f0088f8e691edd96bfbe4a101aa Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 28 Nov 2021 16:00:04 +0000 Subject: [PATCH 117/287] exclude 36 --- tests/test_pretty.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_pretty.py b/tests/test_pretty.py index 3a4ea6c075..ab83d930d1 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -109,6 +109,7 @@ def __repr__(self): assert result == expected +@skip_py36 def test_broken_getattr(): class BrokenAttr: def __getattr__(self, name): From 32eb5465ea4e2a5882308b2efe763c61705e1374 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 28 Nov 2021 16:22:51 +0000 Subject: [PATCH 118/287] from_ansi method --- rich/text.py | 24 ++++++++++++++---------- tests/test_text.py | 7 ++++--- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/rich/text.py b/rich/text.py index c49e152b60..288cb6d110 100644 --- a/rich/text.py +++ b/rich/text.py @@ -254,10 +254,10 @@ def from_ansi( end: str = "\n", tab_size: Optional[int] = 8, ) -> "Text": - """Create a Text object from pre-formatted ANSI. + """Create a Text object from a string containing ANSI escape codes. Args: - text (str): A string containing ANSI color codes. + text (str): A string containing escape codes. style (Union[str, Style], optional): Base style for text. Defaults to "". justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. @@ -267,14 +267,18 @@ def from_ansi( """ from .ansi import AnsiDecoder - decoded_text = AnsiDecoder().decode_line(text) - decoded_text.justify = justify - decoded_text.overflow = overflow - decoded_text.no_wrap = no_wrap - decoded_text.end = end - decoded_text.tab_size = tab_size - decoded_text.stylize(style) - return decoded_text + joiner = Text( + "\n", + justify=justify, + overflow=overflow, + no_wrap=no_wrap, + end=end, + tab_size=tab_size, + style=style, + ) + decoder = AnsiDecoder() + result = joiner.join(line for line in decoder.decode(text)) + return result @classmethod def styled( diff --git a/tests/test_text.py b/tests/test_text.py index 6eecb9ee73..63f128e52e 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -97,11 +97,12 @@ def test_from_markup(): def test_from_ansi(): text = Text.from_ansi("Hello, \033[1mWorld!\033[0m") - text2 = Text.from_ansi("Hello, \033[1mWorld!\033[0m", style="red") assert str(text) == "Hello, World!" assert text._spans == [Span(7, 13, Style(bold=True))] - assert str(text2) == "Hello, World!" - assert text2._spans == [Span(7, 13, Style(bold=True)), Span(0, 13, "red")] + + text = Text.from_ansi("Hello, \033[1m\nWorld!\033[0m") + assert str(text) == "Hello, \nWorld!" + assert text._spans == [Span(8, 14, Style(bold=True))] def test_copy(): From 0ff0a384daecefc0b9b01eee6086fd3e614df812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 29 Nov 2021 14:30:05 +0200 Subject: [PATCH 119/287] Fix missing reflinks from changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c9ecf60a8..bda3747226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed issue with progress bar not rendering markup https://github.com/willmcgugan/rich/issues/1721 - Fixed race condition when exiting Live https://github.com/willmcgugan/rich/issues/1530 +[10.15.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 + ## [10.14.0] - 2021-11-16 ### Fixed From fe96c32a8478c78b5e666ac3d12bb270b35bba33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 29 Nov 2021 14:45:36 +0200 Subject: [PATCH 120/287] Generate rest of the reflog --- CHANGELOG.md | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bda3747226..393cb76bc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1550,3 +1550,136 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr ### Added - First official release, API still to be stabilized + +[10.14.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 +[10.13.0]: https://github.com/willmcgugan/rich/compare/v10.13.0...v10.14.0 +[10.12.0]: https://github.com/willmcgugan/rich/compare/v10.12.0...v10.13.0 +[10.11.0]: https://github.com/willmcgugan/rich/compare/v10.11.0...v10.12.0 +[10.10.0]: https://github.com/willmcgugan/rich/compare/v10.10.0...v10.11.0 +[10.9.0]: https://github.com/willmcgugan/rich/compare/v10.9.0...v10.10.0 +[10.8.0]: https://github.com/willmcgugan/rich/compare/v10.8.0...v10.9.0 +[10.7.0]: https://github.com/willmcgugan/rich/compare/v10.7.0...v10.8.0 +[10.6.0]: https://github.com/willmcgugan/rich/compare/v10.6.0...v10.7.0 +[10.5.0]: https://github.com/willmcgugan/rich/compare/v10.5.0...v10.6.0 +[10.4.0]: https://github.com/willmcgugan/rich/compare/v10.4.0...v10.5.0 +[10.3.0]: https://github.com/willmcgugan/rich/compare/v10.3.0...v10.4.0 +[10.2.2]: https://github.com/willmcgugan/rich/compare/v10.2.2...v10.3.0 +[10.2.1]: https://github.com/willmcgugan/rich/compare/v10.2.1...v10.2.2 +[10.2.0]: https://github.com/willmcgugan/rich/compare/v10.2.0...v10.2.1 +[10.1.0]: https://github.com/willmcgugan/rich/compare/v10.1.0...v10.2.0 +[10.0.1]: https://github.com/willmcgugan/rich/compare/v10.0.1...v10.1.0 +[10.0.0]: https://github.com/willmcgugan/rich/compare/v10.0.0...v10.0.1 +[9.13.0]: https://github.com/willmcgugan/rich/compare/v9.13.0...v10.0.0 +[9.12.4]: https://github.com/willmcgugan/rich/compare/v9.12.4...v9.13.0 +[9.12.3]: https://github.com/willmcgugan/rich/compare/v9.12.3...v9.12.4 +[9.12.2]: https://github.com/willmcgugan/rich/compare/v9.12.2...v9.12.3 +[9.12.1]: https://github.com/willmcgugan/rich/compare/v9.12.1...v9.12.2 +[9.12.0]: https://github.com/willmcgugan/rich/compare/v9.12.0...v9.12.1 +[9.11.1]: https://github.com/willmcgugan/rich/compare/v9.11.1...v9.12.0 +[9.11.0]: https://github.com/willmcgugan/rich/compare/v9.11.0...v9.11.1 +[9.10.0]: https://github.com/willmcgugan/rich/compare/v9.10.0...v9.11.0 +[9.9.0]: https://github.com/willmcgugan/rich/compare/v9.9.0...v9.10.0 +[9.8.2]: https://github.com/willmcgugan/rich/compare/v9.8.2...v9.9.0 +[9.8.1]: https://github.com/willmcgugan/rich/compare/v9.8.1...v9.8.2 +[9.8.0]: https://github.com/willmcgugan/rich/compare/v9.8.0...v9.8.1 +[9.7.0]: https://github.com/willmcgugan/rich/compare/v9.7.0...v9.8.0 +[9.6.2]: https://github.com/willmcgugan/rich/compare/v9.6.2...v9.7.0 +[9.6.1]: https://github.com/willmcgugan/rich/compare/v9.6.1...v9.6.2 +[9.6.0]: https://github.com/willmcgugan/rich/compare/v9.6.0...v9.6.1 +[9.5.1]: https://github.com/willmcgugan/rich/compare/v9.5.1...v9.6.0 +[9.5.0]: https://github.com/willmcgugan/rich/compare/v9.5.0...v9.5.1 +[9.4.0]: https://github.com/willmcgugan/rich/compare/v9.4.0...v9.5.0 +[9.3.0]: https://github.com/willmcgugan/rich/compare/v9.3.0...v9.4.0 +[9.2.0]: https://github.com/willmcgugan/rich/compare/v9.2.0...v9.3.0 +[9.1.0]: https://github.com/willmcgugan/rich/compare/v9.1.0...v9.2.0 +[9.0.1]: https://github.com/willmcgugan/rich/compare/v9.0.1...v9.1.0 +[9.0.0]: https://github.com/willmcgugan/rich/compare/v9.0.0...v9.0.1 +[8.0.0]: https://github.com/willmcgugan/rich/compare/v8.0.0...v9.0.0 +[7.1.0]: https://github.com/willmcgugan/rich/compare/v7.1.0...v8.0.0 +[7.0.0]: https://github.com/willmcgugan/rich/compare/v7.0.0...v7.1.0 +[6.2.0]: https://github.com/willmcgugan/rich/compare/v6.2.0...v7.0.0 +[6.1.2]: https://github.com/willmcgugan/rich/compare/v6.1.2...v6.2.0 +[6.1.1]: https://github.com/willmcgugan/rich/compare/v6.1.1...v6.1.2 +[6.1.0]: https://github.com/willmcgugan/rich/compare/v6.1.0...v6.1.1 +[6.0.0]: https://github.com/willmcgugan/rich/compare/v6.0.0...v6.1.0 +[5.2.1]: https://github.com/willmcgugan/rich/compare/v5.2.1...v6.0.0 +[5.2.0]: https://github.com/willmcgugan/rich/compare/v5.2.0...v5.2.1 +[5.1.2]: https://github.com/willmcgugan/rich/compare/v5.1.2...v5.2.0 +[5.1.1]: https://github.com/willmcgugan/rich/compare/v5.1.1...v5.1.2 +[5.1.0]: https://github.com/willmcgugan/rich/compare/v5.1.0...v5.1.1 +[5.0.0]: https://github.com/willmcgugan/rich/compare/v5.0.0...v5.1.0 +[4.2.2]: https://github.com/willmcgugan/rich/compare/v4.2.2...v5.0.0 +[4.2.1]: https://github.com/willmcgugan/rich/compare/v4.2.1...v4.2.2 +[4.2.0]: https://github.com/willmcgugan/rich/compare/v4.2.0...v4.2.1 +[4.1.0]: https://github.com/willmcgugan/rich/compare/v4.1.0...v4.2.0 +[4.0.0]: https://github.com/willmcgugan/rich/compare/v4.0.0...v4.1.0 +[3.4.1]: https://github.com/willmcgugan/rich/compare/v3.4.1...v4.0.0 +[3.4.0]: https://github.com/willmcgugan/rich/compare/v3.4.0...v3.4.1 +[3.3.2]: https://github.com/willmcgugan/rich/compare/v3.3.2...v3.4.0 +[3.3.1]: https://github.com/willmcgugan/rich/compare/v3.3.1...v3.3.2 +[3.3.0]: https://github.com/willmcgugan/rich/compare/v3.3.0...v3.3.1 +[3.2.0]: https://github.com/willmcgugan/rich/compare/v3.2.0...v3.3.0 +[3.1.0]: https://github.com/willmcgugan/rich/compare/v3.1.0...v3.2.0 +[3.0.5]: https://github.com/willmcgugan/rich/compare/v3.0.5...v3.1.0 +[3.0.4]: https://github.com/willmcgugan/rich/compare/v3.0.4...v3.0.5 +[3.0.3]: https://github.com/willmcgugan/rich/compare/v3.0.3...v3.0.4 +[3.0.2]: https://github.com/willmcgugan/rich/compare/v3.0.2...v3.0.3 +[3.0.1]: https://github.com/willmcgugan/rich/compare/v3.0.1...v3.0.2 +[3.0.0]: https://github.com/willmcgugan/rich/compare/v3.0.0...v3.0.1 +[2.3.1]: https://github.com/willmcgugan/rich/compare/v2.3.1...v3.0.0 +[2.3.0]: https://github.com/willmcgugan/rich/compare/v2.3.0...v2.3.1 +[2.2.6]: https://github.com/willmcgugan/rich/compare/v2.2.6...v2.3.0 +[2.2.5]: https://github.com/willmcgugan/rich/compare/v2.2.5...v2.2.6 +[2.2.4]: https://github.com/willmcgugan/rich/compare/v2.2.4...v2.2.5 +[2.2.3]: https://github.com/willmcgugan/rich/compare/v2.2.3...v2.2.4 +[2.2.2]: https://github.com/willmcgugan/rich/compare/v2.2.2...v2.2.3 +[2.2.1]: https://github.com/willmcgugan/rich/compare/v2.2.1...v2.2.2 +[2.2.0]: https://github.com/willmcgugan/rich/compare/v2.2.0...v2.2.1 +[2.1.0]: https://github.com/willmcgugan/rich/compare/v2.1.0...v2.2.0 +[2.0.1]: https://github.com/willmcgugan/rich/compare/v2.0.1...v2.1.0 +[2.0.0]: https://github.com/willmcgugan/rich/compare/v2.0.0...v2.0.1 +[1.3.1]: https://github.com/willmcgugan/rich/compare/v1.3.1...v2.0.0 +[1.3.0]: https://github.com/willmcgugan/rich/compare/v1.3.0...v1.3.1 +[1.2.3]: https://github.com/willmcgugan/rich/compare/v1.2.3...v1.3.0 +[1.2.2]: https://github.com/willmcgugan/rich/compare/v1.2.2...v1.2.3 +[1.2.1]: https://github.com/willmcgugan/rich/compare/v1.2.1...v1.2.2 +[1.2.0]: https://github.com/willmcgugan/rich/compare/v1.2.0...v1.2.1 +[1.1.9]: https://github.com/willmcgugan/rich/compare/v1.1.9...v1.2.0 +[1.1.8]: https://github.com/willmcgugan/rich/compare/v1.1.8...v1.1.9 +[1.1.7]: https://github.com/willmcgugan/rich/compare/v1.1.7...v1.1.8 +[1.1.6]: https://github.com/willmcgugan/rich/compare/v1.1.6...v1.1.7 +[1.1.5]: https://github.com/willmcgugan/rich/compare/v1.1.5...v1.1.6 +[1.1.4]: https://github.com/willmcgugan/rich/compare/v1.1.4...v1.1.5 +[1.1.3]: https://github.com/willmcgugan/rich/compare/v1.1.3...v1.1.4 +[1.1.2]: https://github.com/willmcgugan/rich/compare/v1.1.2...v1.1.3 +[1.1.1]: https://github.com/willmcgugan/rich/compare/v1.1.1...v1.1.2 +[1.1.0]: https://github.com/willmcgugan/rich/compare/v1.1.0...v1.1.1 +[1.0.3]: https://github.com/willmcgugan/rich/compare/v1.0.3...v1.1.0 +[1.0.2]: https://github.com/willmcgugan/rich/compare/v1.0.2...v1.0.3 +[1.0.1]: https://github.com/willmcgugan/rich/compare/v1.0.1...v1.0.2 +[1.0.0]: https://github.com/willmcgugan/rich/compare/v1.0.0...v1.0.1 +[0.8.13]: https://github.com/willmcgugan/rich/compare/v0.8.13...v1.0.0 +[0.8.12]: https://github.com/willmcgugan/rich/compare/v0.8.12...v0.8.13 +[0.8.11]: https://github.com/willmcgugan/rich/compare/v0.8.11...v0.8.12 +[0.8.10]: https://github.com/willmcgugan/rich/compare/v0.8.10...v0.8.11 +[0.8.9]: https://github.com/willmcgugan/rich/compare/v0.8.9...v0.8.10 +[0.8.8]: https://github.com/willmcgugan/rich/compare/v0.8.8...v0.8.9 +[0.8.7]: https://github.com/willmcgugan/rich/compare/v0.8.7...v0.8.8 +[0.8.6]: https://github.com/willmcgugan/rich/compare/v0.8.6...v0.8.7 +[0.8.5]: https://github.com/willmcgugan/rich/compare/v0.8.5...v0.8.6 +[0.8.4]: https://github.com/willmcgugan/rich/compare/v0.8.4...v0.8.5 +[0.8.3]: https://github.com/willmcgugan/rich/compare/v0.8.3...v0.8.4 +[0.8.2]: https://github.com/willmcgugan/rich/compare/v0.8.2...v0.8.3 +[0.8.1]: https://github.com/willmcgugan/rich/compare/v0.8.1...v0.8.2 +[0.8.0]: https://github.com/willmcgugan/rich/compare/v0.8.0...v0.8.1 +[0.7.2]: https://github.com/willmcgugan/rich/compare/v0.7.2...v0.8.0 +[0.7.1]: https://github.com/willmcgugan/rich/compare/v0.7.1...v0.7.2 +[0.7.0]: https://github.com/willmcgugan/rich/compare/v0.7.0...v0.7.1 +[0.6.0]: https://github.com/willmcgugan/rich/compare/v0.6.0...v0.7.0 +[0.5.0]: https://github.com/willmcgugan/rich/compare/v0.5.0...v0.6.0 +[0.4.1]: https://github.com/willmcgugan/rich/compare/v0.4.1...v0.5.0 +[0.4.0]: https://github.com/willmcgugan/rich/compare/v0.4.0...v0.4.1 +[0.3.3]: https://github.com/willmcgugan/rich/compare/v0.3.3...v0.4.0 +[0.3.2]: https://github.com/willmcgugan/rich/compare/v0.3.2...v0.3.3 +[0.3.1]: https://github.com/willmcgugan/rich/compare/v0.3.1...v0.3.2 +[0.3.0]: https://github.com/willmcgugan/rich/compare/v0.3.0...v0.3.1 From 0f07f0a615ef7776c63fd2c2eb8ea62dbf030121 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Nov 2021 13:02:51 +0000 Subject: [PATCH 121/287] Bump sphinx from 4.3.0 to 4.3.1 Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.0...v4.3.1) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 02be340721..61da40a33d 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ alabaster==0.7.12 -Sphinx==4.3.0 +Sphinx==4.3.1 sphinx-rtd-theme==1.0.0 sphinx-copybutton==0.4.0 From 03f40a93d68d4518e2c2b7bc23b9a94ca2527ed0 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 29 Nov 2021 17:40:28 +0000 Subject: [PATCH 122/287] rever thread safety issue --- .github/ISSUE_TEMPLATE/bug_report.md | 15 +++---- CHANGELOG.md | 6 +++ rich/console.py | 20 ++++------ rich/live.py | 59 ++++++++++++++-------------- rich/live_render.py | 10 ++--- 5 files changed, 53 insertions(+), 57 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b19a15c10e..c72dc5ae81 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,19 +6,18 @@ labels: Needs triage assignees: "" --- -**Read the docs** -You might find a solution to your problem in the [docs](https://rich.readthedocs.io/en/latest/introduction.html) -- consider using the search function there. +You may find a solution to your problem in the [docs](https://rich.readthedocs.io/en/latest/introduction.html) or [issues](https://github.com/willmcgugan/rich/issues). **Describe the bug** -A clear and concise description of what the bug is. -**To Reproduce** -A minimal code example that reproduces the problem would be a big help if you can provide it. If the issue is visual in nature, consider posting a screenshot. +Edit this with a clear and concise description of what the bug. + +Provide a minimal code example that demonstrates the issue if you can. If the issue is visual in nature, consider posting a screenshot. **Platform** + What platform (Win/Linux/Mac) are you running on? What terminal software are you using? -**Diagnose** I may ask you to cut and paste the output of the following commands. It may save some time if you do it now. ``` @@ -26,7 +25,3 @@ python -m rich.diagnose python -m rich._windows pip freeze | grep rich ``` - -**Did I help?** - -If I was able to resolve your problem, consider [sponsoring](https://github.com/sponsors/willmcgugan) my work on Rich, or [buy me a coffee](https://ko-fi.com/willmcgugan) to say thanks. diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c9ecf60a8..21484dac06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.15.1] - 2021-11-29 + +### Fixed + +- Reverted thread-safety fix for Live that introduced deadlock potential + ## [10.15.0] - 2021-11-28 ### Added diff --git a/rich/console.py b/rich/console.py index fc340bc24e..b6a661061f 100644 --- a/rich/console.py +++ b/rich/console.py @@ -1,7 +1,6 @@ import inspect import os import platform -import shutil import sys import threading from abc import ABC, abstractmethod @@ -13,6 +12,7 @@ from inspect import isclass from itertools import islice from time import monotonic +from threading import RLock from types import FrameType, TracebackType, ModuleType from typing import ( IO, @@ -25,7 +25,6 @@ Mapping, NamedTuple, Optional, - Set, TextIO, Tuple, Type, @@ -836,14 +835,10 @@ def pop_render_hook(self) -> None: def __enter__(self) -> "Console": """Own context manager to enter buffer context.""" self._enter_buffer() - if self._live: - self._live._lock.acquire() return self def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: """Exit buffer context.""" - if self._live: - self._live._lock.release() self._exit_buffer() def begin_capture(self) -> None: @@ -1512,9 +1507,8 @@ def control(self, *control: Control) -> None: control_codes (str): Control codes, such as those that may move the cursor. """ if not self.is_dumb_terminal: - for _control in control: - self._buffer.append(_control.segment) - self._check_buffer() + with self: + self._buffer.extend(_control.segment for _control in control) def out( self, @@ -1596,7 +1590,7 @@ def print( if overflow is None: overflow = "ignore" crop = False - + render_hooks = self._render_hooks[:] with self: renderables = self._collect_renderables( objects, @@ -1607,7 +1601,7 @@ def print( markup=markup, highlight=highlight, ) - for hook in self._render_hooks: + for hook in render_hooks: renderables = hook.process_renderables(renderables) render_options = self.options.update( justify=justify, @@ -1864,6 +1858,8 @@ def log( if not objects: objects = (NewLine(),) + render_hooks = self._render_hooks[:] + with self: renderables = self._collect_renderables( objects, @@ -1898,7 +1894,7 @@ def log( link_path=link_path, ) ] - for hook in self._render_hooks: + for hook in render_hooks: renderables = hook.process_renderables(renderables) new_segments: List[Segment] = [] extend = new_segments.extend diff --git a/rich/live.py b/rich/live.py index c61f233ccd..59478dd97b 100644 --- a/rich/live.py +++ b/rich/live.py @@ -128,38 +128,37 @@ def stop(self) -> None: with self._lock: if not self._started: return - self.console.clear_live() self._started = False - try: - if self.auto_refresh and self._refresh_thread is not None: - self._refresh_thread.stop() - self._refresh_thread.join() - # allow it to fully render on the last even if overflow - self.vertical_overflow = "visible" - if not self._alt_screen and not self.console.is_jupyter: - self.refresh() - - finally: - if self._refresh_thread is not None: - self._refresh_thread = None - - self._disable_redirect_io() - self.console.pop_render_hook() - if not self._alt_screen and self.console.is_terminal: - self.console.line() - self.console.show_cursor(True) - if self._alt_screen: - self.console.set_alt_screen(False) - - if self.transient and not self._alt_screen: - self.console.control(self._live_render.restore_cursor()) - if self.ipy_widget is not None: # pragma: no cover - if self.transient: - self.ipy_widget.close() - else: - # jupyter last refresh must occur after console pop render hook - # i am not sure why this is needed + + if self.auto_refresh and self._refresh_thread is not None: + self._refresh_thread.stop() + self._refresh_thread.join() + self._refresh_thread = None + # allow it to fully render on the last even if overflow + self.vertical_overflow = "visible" + with self.console: + try: + if not self._alt_screen and not self.console.is_jupyter: self.refresh() + finally: + self._disable_redirect_io() + self.console.pop_render_hook() + if not self._alt_screen and self.console.is_terminal: + self.console.line() + self.console.show_cursor(True) + if self._alt_screen: + self.console.set_alt_screen(False) + + if self.transient and not self._alt_screen: + self.console.control(self._live_render.restore_cursor()) + if self.ipy_widget is not None: # pragma: no cover + if self.transient: + self.ipy_widget.close() + else: + # jupyter last refresh must occur after console pop render hook + # i am not sure why this is needed + self.refresh() + self.console.clear_live() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) diff --git a/rich/live_render.py b/rich/live_render.py index ca5ad23b2c..f6fa7b2daa 100644 --- a/rich/live_render.py +++ b/rich/live_render.py @@ -84,16 +84,15 @@ def __rich_console__( ) -> RenderResult: renderable = self.renderable - _Segment = Segment style = console.get_style(self.style) lines = console.render_lines(renderable, options, style=style, pad=False) - shape = _Segment.get_shape(lines) + shape = Segment.get_shape(lines) _, height = shape if height > options.size.height: if self.vertical_overflow == "crop": lines = lines[: options.size.height] - shape = _Segment.get_shape(lines) + shape = Segment.get_shape(lines) elif self.vertical_overflow == "ellipsis": lines = lines[: (options.size.height - 1)] overflow_text = Text( @@ -104,10 +103,11 @@ def __rich_console__( style="live.ellipsis", ) lines.append(list(console.render(overflow_text))) - shape = _Segment.get_shape(lines) + shape = Segment.get_shape(lines) self._shape = shape + new_line = Segment.line() for last, line in loop_last(lines): yield from line if not last: - yield _Segment.line() + yield new_line From 7015e5260b63b71e98da31f7cbdff214a205a4c3 Mon Sep 17 00:00:00 2001 From: Nathan Page Date: Mon, 29 Nov 2021 17:17:41 -0800 Subject: [PATCH 123/287] add rendering of the default styles --- rich/default_styles.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rich/default_styles.py b/rich/default_styles.py index 355f9df852..63290bcaba 100644 --- a/rich/default_styles.py +++ b/rich/default_styles.py @@ -157,3 +157,27 @@ "markdown.link": Style(color="bright_blue"), "markdown.link_url": Style(color="blue"), } + + +if __name__ == "__main__": # pragma: no cover + import argparse + import io + + from rich.console import Console + from rich.table import Table + from rich.text import Text + + parser = argparse.ArgumentParser() + parser.add_argument("--html", action="store_true", help="Export as HTML table") + args = parser.parse_args() + html: bool = args.html + console = Console(record=True, width=70, file=io.StringIO()) if html else Console() + + table = Table("Name", "Styling") + + for style_name, style in DEFAULT_STYLES.items(): + table.add_row(Text(style_name, style=style), str(style)) + + console.print(table) + if html: + print(console.export_html(inline_styles=True)) From b47150933e03794ef32bf1c17d959758ea470a9c Mon Sep 17 00:00:00 2001 From: Nathan Page Date: Mon, 29 Nov 2021 17:17:58 -0800 Subject: [PATCH 124/287] include default styles appendix table --- docs/source/appendix.rst | 1 + docs/source/appendix/default_styles.rst | 162 ++++++++++++++++++++++++ docs/source/style.rst | 2 +- 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 docs/source/appendix/default_styles.rst diff --git a/docs/source/appendix.rst b/docs/source/appendix.rst index 3ae7fa68b4..166ce7d6c8 100644 --- a/docs/source/appendix.rst +++ b/docs/source/appendix.rst @@ -6,4 +6,5 @@ Appendix appendix/box.rst appendix/colors.rst + appendix/default_styles.rst \ No newline at end of file diff --git a/docs/source/appendix/default_styles.rst b/docs/source/appendix/default_styles.rst new file mode 100644 index 0000000000..3057cb9ef2 --- /dev/null +++ b/docs/source/appendix/default_styles.rst @@ -0,0 +1,162 @@ +.. _appendix-styles: + +Default Styles +============== + +A list of all the available styles provided in the default Theme. + +You can also produce this table by running the following command:: + + python -m rich.default_styles + +.. raw:: html + +
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
+    ┃ Name                           Styling                            ┃
+    ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
+    │ none                          │ none                               │
+    │ reset                         │ not bold not dim not italic not    │
+    │                               │ underline not blink not blink2 not │
+    │                               │ reverse not conceal not strike     │
+    │                               │ default on default                 │
+    │ dim                           │ dim                                │
+    │ bright                        │ not dim                            │
+    │ bold                          │ bold                               │
+    │ strong                        │ bold                               │
+    │ code                          │ bold reverse                       │
+    │ italic                        │ italic                             │
+    │ emphasize                     │ italic                             │
+    │ underline                     │ underline                          │
+    │ blink                         │ blink                              │
+    │ blink2                        │ blink2                             │
+    │ reverse                       │ reverse                            │
+    │ strike                        │ strike                             │
+    │ black                         │ black                              │
+    │ red                           │ red                                │
+    │ green                         │ green                              │
+    │ yellow                        │ yellow                             │
+    │ magenta                       │ magenta                            │
+    │ cyan                          │ cyan                               │
+    │ white                         │ white                              │
+    │ inspect.attr                  │ italic yellow                      │
+    │ inspect.attr.dunder           │ dim italic yellow                  │
+    │ inspect.callable              │ bold red                           │
+    │ inspect.def                   │ italic bright_cyan                 │
+    │ inspect.error                 │ bold red                           │
+    │ inspect.equals                │ none                               │
+    │ inspect.help                  │ cyan                               │
+    │ inspect.doc                   │ dim                                │
+    │ inspect.value.border          │ green                              │
+    │ live.ellipsis                 │ bold red                           │
+    │ layout.tree.row               │ not dim red                        │
+    │ layout.tree.column            │ not dim blue                       │
+    │ logging.keyword               │ bold yellow                        │
+    │ logging.level.notset          │ dim                                │
+    │ logging.level.debug           │ green                              │
+    │ logging.level.info            │ blue                               │
+    │ logging.level.warning         │ red                                │
+    │ logging.level.error           │ bold red                           │
+    │ logging.level.critical        │ bold reverse red                   │
+    │ log.level                     │ none                               │
+    │ log.time                      │ dim cyan                           │
+    │ log.message                   │ none                               │
+    │ log.path                      │ dim                                │
+    │ repr.ellipsis                 │ yellow                             │
+    │ repr.indent                   │ dim green                          │
+    │ repr.error                    │ bold red                           │
+    │ repr.str                      │ not bold not italic green          │
+    │ repr.brace                    │ bold                               │
+    │ repr.comma                    │ bold                               │
+    │ repr.ipv4                     │ bold bright_green                  │
+    │ repr.ipv6                     │ bold bright_green                  │
+    │ repr.eui48                    │ bold bright_green                  │
+    │ repr.eui64                    │ bold bright_green                  │
+    │ repr.tag_start                │ bold                               │
+    │ repr.tag_name                 │ bold bright_magenta                │
+    │ repr.tag_contents             │ default                            │
+    │ repr.tag_end                  │ bold                               │
+    │ repr.attrib_name              │ not italic yellow                  │
+    │ repr.attrib_equal             │ bold                               │
+    │ repr.attrib_value             │ not italic magenta                 │
+    │ repr.number                   │ bold not italic cyan               │
+    │ repr.bool_true                │ italic bright_green                │
+    │ repr.bool_false               │ italic bright_red                  │
+    │ repr.none                     │ italic magenta                     │
+    │ repr.url                      │ not bold not italic underline      │
+    │                               │ bright_blue                        │
+    │ repr.uuid                     │ not bold bright_yellow             │
+    │ repr.call                     │ bold magenta                       │
+    │ repr.path                     │ magenta                            │
+    │ repr.filename                 │ bright_magenta                     │
+    │ rule.line                     │ bright_green                       │
+    │ rule.text                     │ none                               │
+    │ json.brace                    │ bold                               │
+    │ json.bool_true                │ italic bright_green                │
+    │ json.bool_false               │ italic bright_red                  │
+    │ json.null                     │ italic magenta                     │
+    │ json.number                   │ bold not italic cyan               │
+    │ json.str                      │ not bold not italic green          │
+    │ json.key                      │ bold blue                          │
+    │ prompt                        │ none                               │
+    │ prompt.choices                │ bold magenta                       │
+    │ prompt.default                │ bold cyan                          │
+    │ prompt.invalid                │ red                                │
+    │ prompt.invalid.choice         │ red                                │
+    │ pretty                        │ none                               │
+    │ scope.border                  │ blue                               │
+    │ scope.key                     │ italic yellow                      │
+    │ scope.key.special             │ dim italic yellow                  │
+    │ scope.equals                  │ red                                │
+    │ table.header                  │ bold                               │
+    │ table.footer                  │ bold                               │
+    │ table.cell                    │ none                               │
+    │ table.title                   │ italic                             │
+    │ table.caption                 │ dim italic                         │
+    │ traceback.error               │ italic red                         │
+    │ traceback.border.syntax_error │ bright_red                         │
+    │ traceback.border              │ red                                │
+    │ traceback.text                │ none                               │
+    │ traceback.title               │ bold red                           │
+    │ traceback.exc_type            │ bold bright_red                    │
+    │ traceback.exc_value           │ none                               │
+    │ traceback.offset              │ bold bright_red                    │
+    │ bar.back                      │ grey23                             │
+    │ bar.complete                  │ rgb(249,38,114)                    │
+    │ bar.finished                  │ rgb(114,156,31)                    │
+    │ bar.pulse                     │ rgb(249,38,114)                    │
+    │ progress.description          │ none                               │
+    │ progress.filesize             │ green                              │
+    │ progress.filesize.total       │ green                              │
+    │ progress.download             │ green                              │
+    │ progress.elapsed              │ yellow                             │
+    │ progress.percentage           │ magenta                            │
+    │ progress.remaining            │ cyan                               │
+    │ progress.data.speed           │ red                                │
+    │ progress.spinner              │ green                              │
+    │ status.spinner                │ green                              │
+    │ tree                          │ none                               │
+    │ tree.line                     │ none                               │
+    │ markdown.paragraph            │ none                               │
+    │ markdown.text                 │ none                               │
+    │ markdown.emph                 │ italic                             │
+    │ markdown.strong               │ bold                               │
+    │ markdown.code                 │ bright_white on black              │
+    │ markdown.code_block           │ dim cyan on black                  │
+    │ markdown.block_quote          │ magenta                            │
+    │ markdown.list                 │ cyan                               │
+    │ markdown.item                 │ none                               │
+    │ markdown.item.bullet          │ bold yellow                        │
+    │ markdown.item.number          │ bold yellow                        │
+    │ markdown.hr                   │ yellow                             │
+    │ markdown.h1.border            │ none                               │
+    │ markdown.h1                   │ bold                               │
+    │ markdown.h2                   │ bold underline                     │
+    │ markdown.h3                   │ bold                               │
+    │ markdown.h4                   │ bold dim                           │
+    │ markdown.h5                   │ underline                          │
+    │ markdown.h6                   │ italic                             │
+    │ markdown.h7                   │ dim italic                         │
+    │ markdown.link                 │ bright_blue                        │
+    │ markdown.link_url             │ blue                               │
+    └───────────────────────────────┴────────────────────────────────────┘
+    
diff --git a/docs/source/style.rst b/docs/source/style.rst index ee9eca5df0..e248be5d53 100644 --- a/docs/source/style.rst +++ b/docs/source/style.rst @@ -141,7 +141,7 @@ The Theme class will inherit the default styles builtin to Rich. If your custom You can disable inheriting the default theme by setting ``inherit=False`` on the :class:`rich.theme.Theme` constructor. -To see the default theme, run the following command:: +To see the default theme refer to :ref:`appendix-styles` or run the following command:: python -m rich.theme From eff8da619388b711bfb5e885bbd343e0d1ae1c32 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 30 Nov 2021 13:34:34 +0000 Subject: [PATCH 125/287] Diff for 10.15.1 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d09219eac2..974d14aaf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1557,6 +1557,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[10.15.1]: https://github.com/willmcgugan/rich/compare/v10.15.0...v10.15.1 [10.14.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 [10.13.0]: https://github.com/willmcgugan/rich/compare/v10.13.0...v10.14.0 [10.12.0]: https://github.com/willmcgugan/rich/compare/v10.12.0...v10.13.0 From 40dbc0a616839d634d64ec6212b9daeff1b94063 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 2 Dec 2021 13:46:10 +0000 Subject: [PATCH 126/287] fix for deadlock --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- rich/live.py | 3 +-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 974d14aaf3..037aa243ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.15.2] - 2021-12-02 + +### Fixed + +- Deadlock issue https://github.com/willmcgugan/rich/issues/1734 + ## [10.15.1] - 2021-11-29 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 4300beae91..4be770b13c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.15.0" +version = "10.15.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/live.py b/rich/live.py index 59478dd97b..4413f16da1 100644 --- a/rich/live.py +++ b/rich/live.py @@ -128,11 +128,11 @@ def stop(self) -> None: with self._lock: if not self._started: return + self.console.clear_live() self._started = False if self.auto_refresh and self._refresh_thread is not None: self._refresh_thread.stop() - self._refresh_thread.join() self._refresh_thread = None # allow it to fully render on the last even if overflow self.vertical_overflow = "visible" @@ -158,7 +158,6 @@ def stop(self) -> None: # jupyter last refresh must occur after console pop render hook # i am not sure why this is needed self.refresh() - self.console.clear_live() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) From 7d03118a9ebceb7882a83b0b0059bd0f6b8eacc2 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Thu, 9 Dec 2021 19:15:25 +0000 Subject: [PATCH 127/287] Add lexer parameter to Syntax --- rich/syntax.py | 11 +++++++++-- tests/test_syntax.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 05d41c993e..4ef751e84b 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -5,6 +5,7 @@ from abc import ABC, abstractmethod from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename from pygments.style import Style as PygmentsStyle from pygments.styles import get_style_by_name @@ -195,6 +196,7 @@ class Syntax(JupyterMixin): Args: code (str): Code to highlight. lexer_name (str): Lexer to use (see https://pygments.org/docs/lexers/) + lexer (Lexer): Lexer instance to use (see https://pygments.org/docs/lexers/) theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "monokai". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. @@ -226,8 +228,9 @@ def get_theme(cls, name: Union[str, SyntaxTheme]) -> SyntaxTheme: def __init__( self, code: str, - lexer_name: str, + lexer_name: Optional[str] = None, *, + lexer: Optional[Lexer] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -240,8 +243,12 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: + if all((lexer_name, lexer)): + raise ValueError("Cannot pass both lexer_name and lexer") + self.code = code self.lexer_name = lexer_name + self.lexer = lexer self.dedent = dedent self.line_numbers = line_numbers self.start_line = start_line @@ -374,7 +381,7 @@ def highlight( ) _get_theme_style = self._theme.get_style_for_token try: - lexer = get_lexer_by_name( + lexer = self.lexer or get_lexer_by_name( self.lexer_name, stripnl=False, ensurenl=True, diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 090d08d250..3f8e5d3d46 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -10,6 +10,8 @@ from rich.style import Style from rich.syntax import Syntax, ANSISyntaxTheme, PygmentsSyntaxTheme, Color, Console +from pygments.lexers import PythonLexer + CODE = '''\ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: @@ -27,6 +29,19 @@ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: yield first, True, previous_value''' +def test_cannot_pass_both_lexer_name_and_lexer(): + code = "\n\nimport this\n\n" + with pytest.raises(ValueError, match="Cannot pass both lexer_name and lexer"): + Syntax( + code, + lexer_name="python", + lexer=PythonLexer, + theme="ascii_light", + code_width=30, + line_numbers=True, + ) + + def test_blank_lines(): code = "\n\nimport this\n\n" syntax = Syntax( @@ -74,6 +89,21 @@ def test_python_render_simple(): assert rendered_syntax == expected +def test_python_render_simple_passing_lexer_instance(): + syntax = Syntax( + CODE, + lexer=PythonLexer(), + line_numbers=False, + theme="foo", + code_width=60, + word_wrap=False, + ) + rendered_syntax = render(syntax) + print(repr(rendered_syntax)) + expected = '\x1b[1;38;2;0;128;0;48;2;248;248;248mdef\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;255;48;2;248;248;248mloop_first_last\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mT\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m]\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m-\x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m>\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mTuple\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mb\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n' + assert rendered_syntax == expected + + def test_python_render_simple_indent_guides(): syntax = Syntax( CODE, From 0a27887ff1fe2feffba2d7d9aea88f651bb3ed7a Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Thu, 9 Dec 2021 19:17:09 +0000 Subject: [PATCH 128/287] Fix typing --- rich/syntax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 4ef751e84b..fe31a51d17 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -3,7 +3,7 @@ from rich.containers import Lines import textwrap from abc import ABC, abstractmethod -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, cast from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename @@ -382,7 +382,7 @@ def highlight( _get_theme_style = self._theme.get_style_for_token try: lexer = self.lexer or get_lexer_by_name( - self.lexer_name, + cast(str, self.lexer_name), stripnl=False, ensurenl=True, tabsize=self.tab_size, From e125fc909e569a6612bf2f967fffd86ce18f7e08 Mon Sep 17 00:00:00 2001 From: Paul Sanders Date: Fri, 10 Dec 2021 19:20:46 -0500 Subject: [PATCH 129/287] Update example url --- examples/downloader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/downloader.py b/examples/downloader.py index 15697a49d5..3671cee48b 100644 --- a/examples/downloader.py +++ b/examples/downloader.py @@ -73,7 +73,7 @@ def download(urls: Iterable[str], dest_dir: str): if __name__ == "__main__": - # Try with https://releases.ubuntu.com/20.04/ubuntu-20.04.2.0-desktop-amd64.iso + # Try with https://releases.ubuntu.com/20.04/ubuntu-20.04.3-desktop-amd64.iso if sys.argv[1:]: download(sys.argv[1:], "./") else: From 215597a3fc47415c31e6dc556d806d87bb32cc79 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 15:28:56 +0000 Subject: [PATCH 130/287] fix for double progress --- CHANGELOG.md | 6 + poetry.lock | 327 +++++++++++++++++++------------------------------ pyproject.toml | 2 +- rich/live.py | 11 +- 4 files changed, 136 insertions(+), 210 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 037aa243ca..3afff1b4f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.15.3] - 2021-12-11 + +### Fixed + +- Double print of progress bar in Jupyter + ## [10.15.2] - 2021-12-02 ### Fixed diff --git a/poetry.lock b/poetry.lock index ad0c349e1f..38d7131768 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,20 +8,37 @@ python-versions = "*" [[package]] name = "argon2-cffi" -version = "21.1.0" +version = "21.3.0" description = "The secure Argon2 password hashing algorithm." category = "main" optional = true -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] -cffi = ">=1.0.0" +argon2-cffi-bindings = "*" +dataclasses = {version = "*", markers = "python_version < \"3.7\""} +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "furo", "wheel", "pre-commit"] -docs = ["sphinx", "furo"] +dev = ["pre-commit", "cogapp", "tomli", "coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "sphinx-notfound-page", "furo"] +docs = ["sphinx", "sphinx-notfound-page", "furo"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] +[[package]] +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["pytest", "cogapp", "pre-commit", "wheel"] +tests = ["pytest"] + [[package]] name = "async-generator" version = "1.10" @@ -62,7 +79,7 @@ python-versions = "*" [[package]] name = "black" -version = "21.11b1" +version = "21.12b0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -74,7 +91,6 @@ dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" -regex = ">=2021.4.4" tomli = ">=0.2.6,<2.0.0" typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = [ @@ -146,7 +162,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "6.1.2" +version = "6.2" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -236,7 +252,7 @@ test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "nose", "jedi (<=0.17.2)"] [[package]] name = "ipython" -version = "7.16.1" +version = "7.16.2" description = "IPython: Productive Interactive Computing" category = "main" optional = true @@ -247,7 +263,7 @@ appnope = {version = "*", markers = "sys_platform == \"darwin\""} backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" -jedi = ">=0.10" +jedi = ">=0.10,<=0.17.2" pexpect = {version = "*", markers = "sys_platform != \"win32\""} pickleshare = "*" prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" @@ -295,18 +311,18 @@ test = ["pytest (>=3.6.0)", "pytest-cov", "mock"] [[package]] name = "jedi" -version = "0.18.1" +version = "0.17.2" description = "An autocompletion tool for Python that can be used for text editors." category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.7.0,<0.8.0" [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==3.7.9)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] [[package]] name = "jinja2" @@ -341,7 +357,7 @@ format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jupyter-client" -version = "7.0.6" +version = "7.1.0" description = "Jupyter protocol implementation and client libraries" category = "main" optional = true @@ -503,7 +519,7 @@ test = ["check-manifest", "fastjsonschema", "testpath", "pytest", "pytest-cov"] [[package]] name = "nest-asyncio" -version = "1.5.1" +version = "1.5.4" description = "Patch asyncio to allow nested event loops" category = "main" optional = true @@ -560,15 +576,14 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "parso" -version = "0.8.2" +version = "0.7.1" description = "A Python Parser" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] +testing = ["docopt", "pytest (>=3.0.7)"] [[package]] name = "pathspec" @@ -637,7 +652,7 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.22" +version = "3.0.24" description = "Library for building powerful interactive command lines in Python" category = "main" optional = true @@ -773,14 +788,6 @@ python-versions = ">=3.6" cffi = {version = "*", markers = "implementation_name == \"pypy\""} py = {version = "*", markers = "implementation_name == \"pypy\""} -[[package]] -name = "regex" -version = "2021.11.10" -description = "Alternative regular expression module, to replace re." -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "send2trash" version = "1.8.0" @@ -887,7 +894,7 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "4.0.0" +version = "4.0.1" description = "Backported and Experimental Type Hints for Python 3.6+" category = "main" optional = false @@ -946,17 +953,31 @@ appnope = [ {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, ] argon2-cffi = [ - {file = "argon2-cffi-21.1.0.tar.gz", hash = "sha256:f710b61103d1a1f692ca3ecbd1373e28aa5e545ac625ba067ff2feca1b2bb870"}, - {file = "argon2_cffi-21.1.0-cp35-abi3-macosx_10_14_x86_64.whl", hash = "sha256:217b4f0f853ccbbb5045242946ad2e162e396064575860141b71a85eb47e475a"}, - {file = "argon2_cffi-21.1.0-cp35-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa7e7d1fc22514a32b1761fdfa1882b6baa5c36bb3ef557bdd69e6fc9ba14a41"}, - {file = "argon2_cffi-21.1.0-cp35-abi3-win32.whl", hash = "sha256:e4d8f0ae1524b7b0372a3e574a2561cbdddb3fdb6c28b70a72868189bda19659"}, - {file = "argon2_cffi-21.1.0-cp35-abi3-win_amd64.whl", hash = "sha256:65213a9174320a1aee03fe826596e0620783966b49eb636955958b3074e87ff9"}, - {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:245f64a203012b144b7b8c8ea6d468cb02b37caa5afee5ba4a10c80599334f6a"}, - {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4ad152c418f7eb640eac41ac815534e6aa61d1624530b8e7779114ecfbf327f8"}, - {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:bc513db2283c385ea4da31a2cd039c33380701f376f4edd12fe56db118a3b21a"}, - {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c7a7c8cc98ac418002090e4add5bebfff1b915ea1cb459c578cd8206fef10378"}, - {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:165cadae5ac1e26644f5ade3bd9c18d89963be51d9ea8817bd671006d7909057"}, - {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:566ffb581bbd9db5562327aee71b2eda24a1c15b23a356740abe3c011bbe0dcb"}, + {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, + {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, +] +argon2-cffi-bindings = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, ] async-generator = [ {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, @@ -975,8 +996,8 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] black = [ - {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"}, - {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"}, + {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, + {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, ] bleach = [ {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, @@ -1047,53 +1068,53 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:675adb3b3380967806b3cbb9c5b00ceb29b1c472692100a338730c1d3e59c8b9"}, - {file = "coverage-6.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95a58336aa111af54baa451c33266a8774780242cab3704b7698d5e514840758"}, - {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d0a595a781f8e186580ff8e3352dd4953b1944289bec7705377c80c7e36c4d6c"}, - {file = "coverage-6.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d3c5f49ce6af61154060640ad3b3281dbc46e2e0ef2fe78414d7f8a324f0b649"}, - {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:310c40bed6b626fd1f463e5a83dba19a61c4eb74e1ac0d07d454ebbdf9047e9d"}, - {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a4d48e42e17d3de212f9af44f81ab73b9378a4b2b8413fd708d0d9023f2bbde4"}, - {file = "coverage-6.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ffa545230ca2ad921ad066bf8fd627e7be43716b6e0fcf8e32af1b8188ccb0ab"}, - {file = "coverage-6.1.2-cp310-cp310-win32.whl", hash = "sha256:cd2d11a59afa5001ff28073ceca24ae4c506da4355aba30d1e7dd2bd0d2206dc"}, - {file = "coverage-6.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:96129e41405887a53a9cc564f960d7f853cc63d178f3a182fdd302e4cab2745b"}, - {file = "coverage-6.1.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1de9c6f5039ee2b1860b7bad2c7bc3651fbeb9368e4c4d93e98a76358cdcb052"}, - {file = "coverage-6.1.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:80cb70264e9a1d04b519cdba3cd0dc42847bf8e982a4d55c769b9b0ee7cdce1e"}, - {file = "coverage-6.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:ba6125d4e55c0b8e913dad27b22722eac7abdcb1f3eab1bd090eee9105660266"}, - {file = "coverage-6.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8492d37acdc07a6eac6489f6c1954026f2260a85a4c2bb1e343fe3d35f5ee21a"}, - {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66af99c7f7b64d050d37e795baadf515b4561124f25aae6e1baa482438ecc388"}, - {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ebcc03e1acef4ff44f37f3c61df478d6e469a573aa688e5a162f85d7e4c3860d"}, - {file = "coverage-6.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d44a8136eebbf544ad91fef5bd2b20ef0c9b459c65a833c923d9aa4546b204"}, - {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c18725f3cffe96732ef96f3de1939d81215fd6d7d64900dcc4acfe514ea4fcbf"}, - {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c8e9c4bcaaaa932be581b3d8b88b677489975f845f7714efc8cce77568b6711c"}, - {file = "coverage-6.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:06d009e8a29483cbc0520665bc46035ffe9ae0e7484a49f9782c2a716e37d0a0"}, - {file = "coverage-6.1.2-cp36-cp36m-win32.whl", hash = "sha256:e5432d9c329b11c27be45ee5f62cf20a33065d482c8dec1941d6670622a6fb8f"}, - {file = "coverage-6.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:82fdcb64bf08aa5db881db061d96db102c77397a570fbc112e21c48a4d9cb31b"}, - {file = "coverage-6.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:94f558f8555e79c48c422045f252ef41eb43becdd945e9c775b45ebfc0cbd78f"}, - {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:046647b96969fda1ae0605f61288635209dd69dcd27ba3ec0bf5148bc157f954"}, - {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cc799916b618ec9fd00135e576424165691fec4f70d7dc12cfaef09268a2478c"}, - {file = "coverage-6.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62646d98cf0381ffda301a816d6ac6c35fc97aa81b09c4c52d66a15c4bef9d7c"}, - {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:27a3df08a855522dfef8b8635f58bab81341b2fb5f447819bc252da3aa4cf44c"}, - {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:610c0ba11da8de3a753dc4b1f71894f9f9debfdde6559599f303286e70aeb0c2"}, - {file = "coverage-6.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:35b246ae3a2c042dc8f410c94bcb9754b18179cdb81ff9477a9089dbc9ecc186"}, - {file = "coverage-6.1.2-cp37-cp37m-win32.whl", hash = "sha256:0cde7d9fe2fb55ff68ebe7fb319ef188e9b88e0a3d1c9c5db7dd829cd93d2193"}, - {file = "coverage-6.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:958ac66272ff20e63d818627216e3d7412fdf68a2d25787b89a5c6f1eb7fdd93"}, - {file = "coverage-6.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a300b39c3d5905686c75a369d2a66e68fd01472ea42e16b38c948bd02b29e5bd"}, - {file = "coverage-6.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d3855d5d26292539861f5ced2ed042fc2aa33a12f80e487053aed3bcb6ced13"}, - {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:586d38dfc7da4a87f5816b203ff06dd7c1bb5b16211ccaa0e9788a8da2b93696"}, - {file = "coverage-6.1.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a34fccb45f7b2d890183a263578d60a392a1a218fdc12f5bce1477a6a68d4373"}, - {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bc1ee1318f703bc6c971da700d74466e9b86e0c443eb85983fb2a1bd20447263"}, - {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3f546f48d5d80a90a266769aa613bc0719cb3e9c2ef3529d53f463996dd15a9d"}, - {file = "coverage-6.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd92ece726055e80d4e3f01fff3b91f54b18c9c357c48fcf6119e87e2461a091"}, - {file = "coverage-6.1.2-cp38-cp38-win32.whl", hash = "sha256:24ed38ec86754c4d5a706fbd5b52b057c3df87901a8610d7e5642a08ec07087e"}, - {file = "coverage-6.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:97ef6e9119bd39d60ef7b9cd5deea2b34869c9f0b9777450a7e3759c1ab09b9b"}, - {file = "coverage-6.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e5a8c947a2a89c56655ecbb789458a3a8e3b0cbf4c04250331df8f647b3de59"}, - {file = "coverage-6.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a39590d1e6acf6a3c435c5d233f72f5d43b585f5be834cff1f21fec4afda225"}, - {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d2c2e3ce7b8cc932a2f918186964bd44de8c84e2f9ef72dc616f5bb8be22e71"}, - {file = "coverage-6.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3348865798c077c695cae00da0924136bb5cc501f236cfd6b6d9f7a3c94e0ec4"}, - {file = "coverage-6.1.2-cp39-cp39-win32.whl", hash = "sha256:fae3fe111670e51f1ebbc475823899524e3459ea2db2cb88279bbfb2a0b8a3de"}, - {file = "coverage-6.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:af45eea024c0e3a25462fade161afab4f0d9d9e0d5a5d53e86149f74f0a35ecc"}, - {file = "coverage-6.1.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:eab14fdd410500dae50fd14ccc332e65543e7b39f6fc076fe90603a0e5d2f929"}, - {file = "coverage-6.1.2.tar.gz", hash = "sha256:d9a635114b88c0ab462e0355472d00a180a5fbfd8511e7f18e4ac32652e7d972"}, + {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, + {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, + {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, + {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, + {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, + {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, + {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, + {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, + {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, + {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, + {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, + {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, + {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, + {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, + {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, + {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, + {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, + {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, + {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, + {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, ] dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, @@ -1124,8 +1145,8 @@ ipykernel = [ {file = "ipykernel-5.5.6.tar.gz", hash = "sha256:4ea44b90ae1f7c38987ad58ea0809562a17c2695a0499644326f334aecd369ec"}, ] ipython = [ - {file = "ipython-7.16.1-py3-none-any.whl", hash = "sha256:2dbcc8c27ca7d3cfe4fcdff7f45b27f9a8d3edfa70ff8024a71c7a8eb5f09d64"}, - {file = "ipython-7.16.1.tar.gz", hash = "sha256:9f4fcb31d3b2c533333893b9172264e4821c1ac91839500f31bd43f2c59b3ccf"}, + {file = "ipython-7.16.2-py3-none-any.whl", hash = "sha256:2f644313be4fdc5c8c2a17467f2949c29423c9e283a159d1fc9bf450a1a300af"}, + {file = "ipython-7.16.2.tar.gz", hash = "sha256:613085f8acb0f35f759e32bea35fba62c651a4a2e409a0da11414618f5eec0c4"}, ] ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, @@ -1136,8 +1157,8 @@ ipywidgets = [ {file = "ipywidgets-7.6.5.tar.gz", hash = "sha256:00974f7cb4d5f8d494c19810fedb9fa9b64bffd3cda7c2be23c133a1ad3c99c5"}, ] jedi = [ - {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, - {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, + {file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, + {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, ] jinja2 = [ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, @@ -1148,8 +1169,8 @@ jsonschema = [ {file = "jsonschema-4.0.0.tar.gz", hash = "sha256:bc51325b929171791c42ebc1c70b9713eb134d3bb8ebd5474c8b659b15be6d86"}, ] jupyter-client = [ - {file = "jupyter_client-7.0.6-py3-none-any.whl", hash = "sha256:074bdeb1ffaef4a3095468ee16313938cfdc48fc65ca95cc18980b956c2e5d79"}, - {file = "jupyter_client-7.0.6.tar.gz", hash = "sha256:8b6e06000eb9399775e0a55c52df6c1be4766666209c22f90c2691ded0e338dc"}, + {file = "jupyter_client-7.1.0-py3-none-any.whl", hash = "sha256:64d93752d8cbfba0c1030c3335c3f0d9797cd1efac012652a14aac1653db11a3"}, + {file = "jupyter_client-7.1.0.tar.gz", hash = "sha256:a5f995a73cffb314ed262713ae6dfce53c6b8216cea9f332071b8ff44a6e1654"}, ] jupyter-core = [ {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"}, @@ -1164,28 +1185,12 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1194,27 +1199,14 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1224,12 +1216,6 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1280,8 +1266,8 @@ nbformat = [ {file = "nbformat-5.1.3.tar.gz", hash = "sha256:b516788ad70771c6250977c1374fcca6edebe6126fd2adb5a69aa5c2356fd1c8"}, ] nest-asyncio = [ - {file = "nest_asyncio-1.5.1-py3-none-any.whl", hash = "sha256:76d6e972265063fe92a90b9cc4fb82616e07d586b346ed9d2c89a4187acea39c"}, - {file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"}, + {file = "nest_asyncio-1.5.4-py3-none-any.whl", hash = "sha256:3fdd0d6061a2bb16f21fe8a9c6a7945be83521d81a0d15cff52e9edee50101d6"}, + {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"}, ] notebook = [ {file = "notebook-6.4.6-py3-none-any.whl", hash = "sha256:5cad068fa82cd4fb98d341c052100ed50cd69fbfb4118cb9b8ab5a346ef27551"}, @@ -1296,8 +1282,8 @@ pandocfilters = [ {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, ] parso = [ - {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, - {file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"}, + {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, + {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, ] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, @@ -1324,8 +1310,8 @@ prometheus-client = [ {file = "prometheus_client-0.12.0.tar.gz", hash = "sha256:1b12ba48cee33b9b0b9de64a1047cbd3c5f2d0ab6ebcead7ddda613a750ec3c5"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.22-py3-none-any.whl", hash = "sha256:48d85cdca8b6c4f16480c7ce03fd193666b62b0a21667ca56b4bb5ad679d1170"}, - {file = "prompt_toolkit-3.0.22.tar.gz", hash = "sha256:449f333dd120bd01f5d296a8ce1452114ba3a71fae7288d2f0ae2c918764fa72"}, + {file = "prompt_toolkit-3.0.24-py3-none-any.whl", hash = "sha256:e56f2ff799bacecd3e88165b1e2f5ebf9bcd59e80e06d395fa0cc4b8bd7bb506"}, + {file = "prompt_toolkit-3.0.24.tar.gz", hash = "sha256:1bb05628c7d87b645974a1bad3f17612be0c29fa39af9f7688030163f680bad6"}, ] ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, @@ -1408,32 +1394,24 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1441,8 +1419,6 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, @@ -1451,57 +1427,6 @@ pyzmq = [ {file = "pyzmq-22.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d6157793719de168b199194f6b6173f0ccd3bf3499e6870fac17086072e39115"}, {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, ] -regex = [ - {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, - {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, - {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, - {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, - {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, - {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, - {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, - {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, - {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, - {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, - {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, - {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, - {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, - {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, - {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, -] send2trash = [ {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, {file = "Send2Trash-1.8.0.tar.gz", hash = "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d"}, @@ -1610,8 +1535,8 @@ types-dataclasses = [ {file = "types_dataclasses-0.6.1-py3-none-any.whl", hash = "sha256:aa45bb0dacdba09e3195a36ff8337bba45eac03b6f31c4645e87b4a2a47830dd"}, ] typing-extensions = [ - {file = "typing_extensions-4.0.0-py3-none-any.whl", hash = "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9"}, - {file = "typing_extensions-4.0.0.tar.gz", hash = "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed"}, + {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, + {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/pyproject.toml b/pyproject.toml index 4be770b13c..1a5f8fac35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.15.2" +version = "10.15.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/live.py b/rich/live.py index 4413f16da1..768f95afd8 100644 --- a/rich/live.py +++ b/rich/live.py @@ -151,13 +151,8 @@ def stop(self) -> None: if self.transient and not self._alt_screen: self.console.control(self._live_render.restore_cursor()) - if self.ipy_widget is not None: # pragma: no cover - if self.transient: - self.ipy_widget.close() - else: - # jupyter last refresh must occur after console pop render hook - # i am not sure why this is needed - self.refresh() + if self.ipy_widget is not None and self.transient: + self.ipy_widget.close() def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) @@ -173,7 +168,7 @@ def __exit__( def _enable_redirect_io(self) -> None: """Enable redirecting of stdout / stderr.""" - if self.console.is_terminal: + if self.console.is_terminal or self.console.is_jupyter: if self._redirect_stdout and not isinstance(sys.stdout, FileProxy): self._restore_stdout = sys.stdout sys.stdout = cast("TextIO", FileProxy(self.console, sys.stdout)) From a8e188ffc9dc2f227025fc8c0a7500a25c2dadea Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 16:15:24 +0000 Subject: [PATCH 131/287] added markup property --- pyproject.toml | 2 +- rich/text.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1a5f8fac35..9437a4c5f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.15.3" +version = "10.15.3-alpha2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/text.py b/rich/text.py index 288cb6d110..4f42e4376b 100644 --- a/rich/text.py +++ b/rich/text.py @@ -213,6 +213,36 @@ def cell_len(self) -> int: """Get the number of cells required to render this text.""" return cell_len(self.plain) + @property + def markup(self) -> str: + """Get console markup to render this Text. + + Returns: + str: A string potentially creating markup tags. + """ + from .markup import escape + + output: List[str] = [] + + plain = self.plain + markup_spans = [ + (0, False, self.style), + *((span.start, False, span.style) for span in self._spans), + *((span.end, True, span.style) for span in self._spans), + (len(plain), True, self.style), + ] + markup_spans = sorted(markup_spans, key=itemgetter(0, 1)) + position = 0 + append = output.append + for offset, closing, style in markup_spans: + if offset > position: + append(escape(plain[position:offset])) + position = offset + if style: + append(f"[/{style}]" if closing else f"[{style}]") + markup = "".join(output) + return markup + @classmethod def from_markup( cls, @@ -1217,6 +1247,10 @@ def with_indent_guides( text.highlight_words(["ipsum"], "italic") console = Console() + + print(text.markup) + console.print(text.markup) + console.rule("justify='left'") console.print(text, style="red") console.print() From 67f1c7ab297abab0ea1741347b4a6ece02e5caed Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 16:29:21 +0000 Subject: [PATCH 132/287] simplify sort --- rich/text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/text.py b/rich/text.py index 4f42e4376b..387207feee 100644 --- a/rich/text.py +++ b/rich/text.py @@ -231,7 +231,7 @@ def markup(self) -> str: *((span.end, True, span.style) for span in self._spans), (len(plain), True, self.style), ] - markup_spans = sorted(markup_spans, key=itemgetter(0, 1)) + markup_spans.sort(key=itemgetter(0, 1)) position = 0 append = output.append for offset, closing, style in markup_spans: @@ -1250,7 +1250,7 @@ def with_indent_guides( print(text.markup) console.print(text.markup) - + console.rule("justify='left'") console.print(text, style="red") console.print() From 1c543b746d821ed836e9ab44c1f87a8270dcc37a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 16:41:19 +0000 Subject: [PATCH 133/287] tests for markup property --- CHANGELOG.md | 6 +++++- tests/test_text.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3afff1b4f2..55aa0c8ba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Double print of progress bar in Jupyter +- Double print of progress bar in Jupyter https://github.com/willmcgugan/rich/issues/1737 + +### Added + +- Added Text.markup property https://github.com/willmcgugan/rich/issues/1751 ## [10.15.2] - 2021-12-02 diff --git a/tests/test_text.py b/tests/test_text.py index 63f128e52e..d1d721bd4e 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -715,3 +715,19 @@ def test_on(): 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 + + +def test_markup_property(): + assert Text("").markup == "" + assert Text("foo").markup == "foo" + assert Text("foo", style="bold").markup == "[bold]foo[/bold]" + assert Text.from_markup("foo [red]bar[/red]").markup == "foo [red]bar[/red]" + assert ( + Text.from_markup("foo [red]bar[/red]", style="bold").markup + == "[bold]foo [red]bar[/red][/bold]" + ) + assert ( + Text.from_markup("[bold]foo [italic]bar[/bold] baz[/italic]").markup + == "[bold]foo [italic]bar[/bold] baz[/italic]" + ) + assert Text("[bold]foo").markup == "\\[bold]foo" From a38c21a993b7818908010979918cad2e6e36c471 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 16:45:50 +0000 Subject: [PATCH 134/287] formatting --- rich/_windows.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rich/_windows.py b/rich/_windows.py index bac88e639b..5169d83556 100644 --- a/rich/_windows.py +++ b/rich/_windows.py @@ -30,7 +30,6 @@ def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() return features - else: STDOUT = -11 From f7f0a4f96aa22e41099a25a1d12dc43148bd975d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 18:24:40 +0000 Subject: [PATCH 135/287] version bump --- CHANGELOG.md | 2 +- pyproject.toml | 4 ++-- rich/live.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55aa0c8ba8..0715ca7f14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.15.3] - 2021-12-11 +## [10.16.0] - Unreleased ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 9437a4c5f5..3fdc11c1e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.15.3-alpha2" +version = "10.16.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" @@ -16,7 +16,7 @@ classifiers = [ "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", + "Programming Languagesh :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/rich/live.py b/rich/live.py index 768f95afd8..6db5b605f9 100644 --- a/rich/live.py +++ b/rich/live.py @@ -152,7 +152,7 @@ def stop(self) -> None: if self.transient and not self._alt_screen: self.console.control(self._live_render.restore_cursor()) if self.ipy_widget is not None and self.transient: - self.ipy_widget.close() + self.ipy_widget.close() # pragma: no cover def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) From bb674b5baaccb6adea040e09bc83d73dafdfb888 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 11 Dec 2021 18:25:30 +0000 Subject: [PATCH 136/287] diff links --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0715ca7f14..05c064dc83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1573,6 +1573,8 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[10.16.0]: https://github.com/willmcgugan/rich/compare/v10.15.2...v10.16.0 +[10.15.2]: https://github.com/willmcgugan/rich/compare/v10.15.1...v10.15.2 [10.15.1]: https://github.com/willmcgugan/rich/compare/v10.15.0...v10.15.1 [10.14.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 [10.13.0]: https://github.com/willmcgugan/rich/compare/v10.13.0...v10.14.0 From 5ab8b9fa1de567c2529f34b70f0ca8e06947b09b Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:03:06 +0000 Subject: [PATCH 137/287] Simplify check for lexer --- rich/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index fe31a51d17..3a29762716 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -243,7 +243,7 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: - if all((lexer_name, lexer)): + if lexer_name and lexer: raise ValueError("Cannot pass both lexer_name and lexer") self.code = code From 2d5675b71a276bab54bec9072a5d4aaf332126b2 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:03:17 +0000 Subject: [PATCH 138/287] Split lexer check --- rich/syntax.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 3a29762716..6c51681e73 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -381,12 +381,17 @@ def highlight( ) _get_theme_style = self._theme.get_style_for_token try: - lexer = self.lexer or get_lexer_by_name( - cast(str, self.lexer_name), - stripnl=False, - ensurenl=True, - tabsize=self.tab_size, - ) + if self.lexer_name: + lexer = get_lexer_by_name( + self.lexer_name, + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + else: + assert self.lexer + + lexer = self.lexer except ClassNotFound: text.append(code) else: From 17ba9574a4c34f936b36150182ee4a8a2c0e1bc5 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:05:38 +0000 Subject: [PATCH 139/287] Remove unused import --- rich/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index 6c51681e73..aa5826b503 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -3,7 +3,7 @@ from rich.containers import Lines import textwrap from abc import ABC, abstractmethod -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, cast +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename From 6e930a30c3caf3c1e4f7c92f9114e27b7334773f Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:15:47 +0000 Subject: [PATCH 140/287] Add myself to contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1551e3657e..5aaf877653 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -25,3 +25,4 @@ The following people have contributed to the development of Rich: - [Tim Savage](https://github.com/timsavage) - [Nicolas Simonds](https://github.com/0xDEC0DE) - [Gabriele N. Tornetta](https://github.com/p403n1x87) +- [Patrick Arminio](https://github.com/patrick91) From 99387cf28fc7cb5e89818289678a6e27d2e632af Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 12 Dec 2021 10:27:19 +0000 Subject: [PATCH 141/287] remove extra chars --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 3fdc11c1e9..7e219d487f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3.6", - "Programming Languagesh :: Python :: 3.7", + "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From a61164da5cb7059c58eef3da9dc8b4db388f66c9 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 12 Dec 2021 11:08:30 +0000 Subject: [PATCH 142/287] version bump --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c064dc83..4218362e1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.16.0] - Unreleased +## [10.16.0] - 2021-12-12 ### Fixed From c57e1f508af1f042d2777e876f816ea157d7a61b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 12 Dec 2021 11:09:48 +0000 Subject: [PATCH 143/287] text tweak --- rich/text.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/rich/text.py b/rich/text.py index 387207feee..b277f6c163 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1248,9 +1248,6 @@ def with_indent_guides( console = Console() - print(text.markup) - console.print(text.markup) - console.rule("justify='left'") console.print(text, style="red") console.print() From 6c2510ed115f233510c49a8edc81fdba0469c296 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sun, 12 Dec 2021 12:31:40 +0000 Subject: [PATCH 144/287] Use only one argument for passing a lexer --- rich/syntax.py | 41 ++++++++++++++++++++--------------------- tests/test_syntax.py | 40 ++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index aa5826b503..05ebdf9aab 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -195,8 +195,7 @@ class Syntax(JupyterMixin): Args: code (str): Code to highlight. - lexer_name (str): Lexer to use (see https://pygments.org/docs/lexers/) - lexer (Lexer): Lexer instance to use (see https://pygments.org/docs/lexers/) + lexer (Lexer | str): Lexer to use (see https://pygments.org/docs/lexers/) theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "monokai". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. @@ -228,9 +227,8 @@ def get_theme(cls, name: Union[str, SyntaxTheme]) -> SyntaxTheme: def __init__( self, code: str, - lexer_name: Optional[str] = None, + lexer: Union[Lexer, str], *, - lexer: Optional[Lexer] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -243,12 +241,8 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: - if lexer_name and lexer: - raise ValueError("Cannot pass both lexer_name and lexer") - self.code = code - self.lexer_name = lexer_name - self.lexer = lexer + self._lexer = lexer self.dedent = dedent self.line_numbers = line_numbers self.start_line = start_line @@ -355,6 +349,20 @@ def _get_token_color(self, token_type: TokenType) -> Optional[Color]: style = self._theme.get_style_for_token(token_type) return style.color + @property + def lexer(self) -> Optional[Lexer]: + if isinstance(self._lexer, Lexer): + return self._lexer + try: + return get_lexer_by_name( + self._lexer, + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + except ClassNotFound: + return None + def highlight( self, code: str, line_range: Optional[Tuple[int, int]] = None ) -> Text: @@ -380,19 +388,10 @@ def highlight( no_wrap=not self.word_wrap, ) _get_theme_style = self._theme.get_style_for_token - try: - if self.lexer_name: - lexer = get_lexer_by_name( - self.lexer_name, - stripnl=False, - ensurenl=True, - tabsize=self.tab_size, - ) - else: - assert self.lexer - lexer = self.lexer - except ClassNotFound: + lexer = self.lexer + + if lexer is None: text.append(code) else: if line_range: diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 3f8e5d3d46..de739c8d8f 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -29,23 +29,10 @@ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: yield first, True, previous_value''' -def test_cannot_pass_both_lexer_name_and_lexer(): - code = "\n\nimport this\n\n" - with pytest.raises(ValueError, match="Cannot pass both lexer_name and lexer"): - Syntax( - code, - lexer_name="python", - lexer=PythonLexer, - theme="ascii_light", - code_width=30, - line_numbers=True, - ) - - def test_blank_lines(): code = "\n\nimport this\n\n" syntax = Syntax( - code, lexer_name="python", theme="ascii_light", code_width=30, line_numbers=True + code, lexer="python", theme="ascii_light", code_width=30, line_numbers=True ) result = render(syntax) print(repr(result)) @@ -59,7 +46,7 @@ def test_python_render(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -77,7 +64,7 @@ def test_python_render(): def test_python_render_simple(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="foo", code_width=60, @@ -107,7 +94,7 @@ def test_python_render_simple_passing_lexer_instance(): def test_python_render_simple_indent_guides(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="ansi_light", code_width=60, @@ -123,7 +110,7 @@ def test_python_render_simple_indent_guides(): def test_python_render_line_range_indent_guides(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="ansi_light", code_width=60, @@ -141,7 +128,7 @@ def test_python_render_indent_guides(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -174,7 +161,7 @@ def test_get_line_color_none(): style._background_style = Style(bgcolor=None) syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme=style, @@ -188,7 +175,7 @@ def test_get_line_color_none(): def test_highlight_background_color(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -219,7 +206,7 @@ def test_get_style_for_token(): style._style_cache = style_dict syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme=style, @@ -233,7 +220,7 @@ def test_get_style_for_token(): def test_option_no_wrap(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), code_width=60, @@ -260,7 +247,8 @@ def test_from_file(): try: os.write(fh, b"import this\n") syntax = Syntax.from_path(path) - assert syntax.lexer_name == "Python" + assert syntax.lexer + assert syntax.lexer.name == "Python" assert syntax.code == "import this\n" finally: os.remove(path) @@ -272,7 +260,7 @@ def test_from_file_unknown_lexer(): try: os.write(fh, b"import this\n") syntax = Syntax.from_path(path) - assert syntax.lexer_name == "default" + assert syntax.lexer is None assert syntax.code == "import this\n" finally: os.remove(path) @@ -282,7 +270,7 @@ def test_from_file_unknown_lexer(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", From 260508bfa058d9d7e7f782482e91adf7ddf06342 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 17:57:11 +0000 Subject: [PATCH 145/287] fix for overlapping markip --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- rich/text.py | 34 +++++++++------------------------- tests/test_segment.py | 30 +++++++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4218362e1c..ff135e765e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.16.1] - Unreleased + +### Fixed + +- Fixed issues with overlaping tags https://github.com/willmcgugan/rich/issues/1755 + ## [10.16.0] - 2021-12-12 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 7e219d487f..c26c6b1d29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.0" +version = "10.16.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/text.py b/rich/text.py index b277f6c163..43c089d6b8 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1033,6 +1033,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: Lines: New RichText instances between offsets. """ _offsets = list(offsets) + if not _offsets: return Lines([self.copy()]) @@ -1056,33 +1057,16 @@ def divide(self, offsets: Iterable[int]) -> Lines: ) if not self._spans: return new_lines - order = {span: span_index for span_index, span in enumerate(self._spans)} - span_stack = sorted(self._spans, key=attrgetter("start"), reverse=True) - pop = span_stack.pop - push = span_stack.append _Span = Span - get_order = order.__getitem__ - - for line, (start, end) in zip(new_lines, line_ranges): - if not span_stack: - break - append_span = line._spans.append - position = len(span_stack) - 1 - while span_stack[position].start < end: - span = pop(position) - add_span, remaining_span = span.split(end) - if remaining_span: - push(remaining_span) - order[remaining_span] = order[span] - span_start, span_end, span_style = add_span - line_span = _Span(span_start - start, span_end - start, span_style) - order[line_span] = order[span] - append_span(line_span) - position -= 1 - if position < 0 or not span_stack: - break # pragma: no cover - line._spans.sort(key=get_order) + + for line, (line_start, line_end) in zip(new_lines._lines, line_ranges): + for span_start, span_end, style in self._spans: + if span_end > line_start: + new_start = max(0, span_start - line_start) + new_end = min(span_end - line_start, line_end - line_start) + if new_end > new_start: + line._spans.append(_Span(new_start, new_end, style)) return new_lines diff --git a/tests/test_segment.py b/tests/test_segment.py index dcf7b218ce..9aff243a83 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -1,4 +1,4 @@ -import sys +from io import StringIO import pytest @@ -166,6 +166,34 @@ def test_divide(): ] +# https://github.com/willmcgugan/rich/issues/1755 +def test_divide_complex(): + MAP = ( + "[on orange4] [on green]XX[on orange4] \n" + " \n" + " \n" + " \n" + " [bright_red on black]Y[on orange4] \n" + "[on green]X[on orange4] [on green]X[on orange4] \n" + " [on green]X[on orange4] [on green]X\n" + "[on orange4] \n" + " [on green]XX[on orange4] \n" + ) + from rich.text import Text + from rich.console import Console + + text = Text.from_markup(MAP) + console = Console( + color_system="truecolor", width=30, force_terminal=True, file=StringIO() + ) + console.print(text) + result = console.file.getvalue() + + print(repr(result)) + expected = "\x1b[48;5;94m \x1b[0m\x1b[42mXX\x1b[0m\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\x1b[91;40mY\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\n\x1b[91;48;5;94m \x1b[0m\n\x1b[91;48;5;94m \x1b[0m\x1b[91;42mXX\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\n" + assert result == expected + + def test_divide_emoji(): bold = Style(bold=True) italic = Style(italic=True) From 7e64cc0b881e0785b9a18ce5cce1dfc9fd7a9448 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 18:00:41 +0000 Subject: [PATCH 146/287] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff135e765e..7b6f790b3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fixed issues with overlaping tags https://github.com/willmcgugan/rich/issues/1755 +- Fixed issues with overlapping tags https://github.com/willmcgugan/rich/issues/1755 ## [10.16.0] - 2021-12-12 From df61680a106c6c5f2edba0c5ecbf5f0a725de09f Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 18:02:35 +0000 Subject: [PATCH 147/287] simplify --- rich/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/text.py b/rich/text.py index 43c089d6b8..51fd2b7365 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1062,7 +1062,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: for line, (line_start, line_end) in zip(new_lines._lines, line_ranges): for span_start, span_end, style in self._spans: - if span_end > line_start: + if span_end > line_start and span_start < line_end: new_start = max(0, span_start - line_start) new_end = min(span_end - line_start, line_end - line_start) if new_end > new_start: From 6035a800ea647e8be15cfb3c30a20cc1c5b3639d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:29:59 +0000 Subject: [PATCH 148/287] more efficient divide --- rich/text.py | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/rich/text.py b/rich/text.py index 51fd2b7365..20173b2fa4 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1,7 +1,7 @@ import re from functools import partial, reduce from math import gcd -from operator import attrgetter, itemgetter +from operator import itemgetter from rich.emoji import EmojiVariant from typing import ( TYPE_CHECKING, @@ -1058,15 +1058,48 @@ def divide(self, offsets: Iterable[int]) -> Lines: if not self._spans: return new_lines + _lines = new_lines._lines + line_count = len(line_ranges) _Span = Span - for line, (line_start, line_end) in zip(new_lines._lines, line_ranges): - for span_start, span_end, style in self._spans: - if span_end > line_start and span_start < line_end: - new_start = max(0, span_start - line_start) - new_end = min(span_end - line_start, line_end - line_start) - if new_end > new_start: - line._spans.append(_Span(new_start, new_end, style)) + for span_start, span_end, style in self._spans: + + lower_bound = 0 + upper_bound = line_count + start_line_no = (lower_bound + upper_bound) // 2 + + while True: + line_start, line_end = line_ranges[start_line_no] + if span_start < line_start: + upper_bound = start_line_no - 1 + elif span_start > line_end: + lower_bound = start_line_no + 1 + else: + break + start_line_no = (lower_bound + upper_bound) // 2 + + lower_bound = 0 + upper_bound = line_count + end_line_no = start_line_no + + while True: + line_start, line_end = line_ranges[end_line_no] + if span_end < line_start: + upper_bound = end_line_no - 1 + elif span_end > line_end: + lower_bound = end_line_no + 1 + else: + break + end_line_no = (lower_bound + upper_bound) // 2 + + for line, (line_start, line_end) in zip( + _lines[start_line_no : end_line_no + 1], + line_ranges[start_line_no : end_line_no + 1], + ): + new_start = max(0, span_start - line_start) + new_end = min(span_end - line_start, line_end - line_start) + if new_end > new_start: + line._spans.append(_Span(new_start, new_end, style)) return new_lines From 5c2824910045221ccf92a36c3d008411229f69c6 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:32:27 +0000 Subject: [PATCH 149/287] alpha build --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c26c6b1d29..4cfe98bf81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.1" +version = "10.16.1-alpha1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From 6957cebe726970ebc8f04cd0d2c3b9d2fa3ecf79 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:43:40 +0000 Subject: [PATCH 150/287] optimize tweak --- rich/text.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rich/text.py b/rich/text.py index 20173b2fa4..3cdd58d441 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1078,9 +1078,8 @@ def divide(self, offsets: Iterable[int]) -> Lines: break start_line_no = (lower_bound + upper_bound) // 2 - lower_bound = 0 - upper_bound = line_count - end_line_no = start_line_no + end_line_no = lower_bound = start_line_no + upper_bound = line_count while True: line_start, line_end = line_ranges[end_line_no] From a1dd33912f71a6e1de6923be03dbe774fcc517dc Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:48:37 +0000 Subject: [PATCH 151/287] formatting --- rich/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/text.py b/rich/text.py index 3cdd58d441..7606d6c47b 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1079,7 +1079,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: start_line_no = (lower_bound + upper_bound) // 2 end_line_no = lower_bound = start_line_no - upper_bound = line_count + upper_bound = line_count while True: line_start, line_end = line_ranges[end_line_no] From c2c506f03c445eb69c6aabf9967b693680c3d949 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:51:48 +0000 Subject: [PATCH 152/287] optimization --- rich/text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/text.py b/rich/text.py index 7606d6c47b..ec5cd10f41 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1058,7 +1058,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: if not self._spans: return new_lines - _lines = new_lines._lines + _lines = [line._spans.append for line in new_lines._lines] line_count = len(line_ranges) _Span = Span @@ -1098,7 +1098,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: new_start = max(0, span_start - line_start) new_end = min(span_end - line_start, line_end - line_start) if new_end > new_start: - line._spans.append(_Span(new_start, new_end, style)) + line(_Span(new_start, new_end, style)) return new_lines From c3e0f7de579849dbed180d2fe5d3d608d4452330 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 21:56:30 +0000 Subject: [PATCH 153/287] optimization --- rich/text.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/rich/text.py b/rich/text.py index ec5cd10f41..8061f8d1a8 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1058,7 +1058,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: if not self._spans: return new_lines - _lines = [line._spans.append for line in new_lines._lines] + _line_appends = [line._spans.append for line in new_lines._lines] line_count = len(line_ranges) _Span = Span @@ -1091,14 +1091,12 @@ def divide(self, offsets: Iterable[int]) -> Lines: break end_line_no = (lower_bound + upper_bound) // 2 - for line, (line_start, line_end) in zip( - _lines[start_line_no : end_line_no + 1], - line_ranges[start_line_no : end_line_no + 1], - ): + for line_no in range(start_line_no, end_line_no + 1): + line_start, line_end = line_ranges[line_no] new_start = max(0, span_start - line_start) new_end = min(span_end - line_start, line_end - line_start) if new_end > new_start: - line(_Span(new_start, new_end, style)) + _line_appends[line_no](_Span(new_start, new_end, style)) return new_lines From a4c9fdb12c5e25c96192e0e3d48bb2c56a4a55a3 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 15 Dec 2021 09:26:05 +0000 Subject: [PATCH 154/287] version bump --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b6f790b3b..95cccbb3e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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.16.1] - Unreleased +## [10.16.1] - 2021-12-15 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 4cfe98bf81..c26c6b1d29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.1-alpha1" +version = "10.16.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From df2ec293e652977943f8e8dc4d0a751ae685e7d0 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 15 Dec 2021 10:24:43 +0000 Subject: [PATCH 155/287] changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95cccbb3e5..22d187424b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1579,6 +1579,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[10.16.1]: https://github.com/willmcgugan/rich/compare/v10.16.0...v10.16.1 [10.16.0]: https://github.com/willmcgugan/rich/compare/v10.15.2...v10.16.0 [10.15.2]: https://github.com/willmcgugan/rich/compare/v10.15.1...v10.15.2 [10.15.1]: https://github.com/willmcgugan/rich/compare/v10.15.0...v10.15.1 From 53b88a6d63bc197a97ce71a4cef4b5adf98090f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Dec 2021 13:04:09 +0000 Subject: [PATCH 156/287] Bump mypy from 0.910 to 0.920 Bumps [mypy](https://github.com/python/mypy) from 0.910 to 0.920. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.910...v0.920) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 100 +++++++++++++++++++++++++++++++++++-------------- pyproject.toml | 2 +- 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/poetry.lock b/poetry.lock index 38d7131768..0f129a7dbf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -425,21 +425,21 @@ python-versions = "*" [[package]] name = "mypy" -version = "0.910" +version = "0.920" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] mypy-extensions = ">=0.4.3,<0.5.0" -toml = "*" -typed-ast = {version = ">=1.4.0,<1.5.0", markers = "python_version < \"3.8\""} +tomli = ">=1.1.0,<3.0.0" +typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} typing-extensions = ">=3.7.4" [package.extras] dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<1.5.0)"] +python2 = ["typed-ast (>=1.4.0,<2)"] [[package]] name = "mypy-extensions" @@ -945,7 +945,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "8aa64ebd459c2f74eb6fa1e78eaf69e75e7a0599dfdd19bbeaa26de037ee2a1b" +content-hash = "6239ee87a97b028b97a30dae0b58017b53c96ffb6b4e6c655fc821d73042ad62" [metadata.files] appnope = [ @@ -1185,12 +1185,28 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1199,14 +1215,27 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1216,6 +1245,12 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1225,29 +1260,26 @@ mistune = [ {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] mypy = [ - {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, - {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, - {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, - {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, - {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, - {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, - {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, - {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, - {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, - {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, - {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, - {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, - {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, - {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, - {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, - {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, - {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, - {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, - {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, - {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, - {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, - {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, - {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, + {file = "mypy-0.920-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41f3575b20714171c832d8f6c7aaaa0d499c9a2d1b8adaaf837b4c9065c38540"}, + {file = "mypy-0.920-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:431be889ffc8d9681813a45575c42e341c19467cbfa6dd09bf41467631feb530"}, + {file = "mypy-0.920-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f8b2059f73878e92eff7ed11a03515d6572f4338a882dd7547b5f7dd242118e6"}, + {file = "mypy-0.920-cp310-cp310-win_amd64.whl", hash = "sha256:9cd316e9705555ca6a50670ba5fb0084d756d1d8cb1697c83820b1456b0bc5f3"}, + {file = "mypy-0.920-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e091fe58b4475b3504dc7c3022ff7f4af2f9e9ddf7182047111759ed0973bbde"}, + {file = "mypy-0.920-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98b4f91a75fed2e4c6339e9047aba95968d3a7c4b91e92ab9dc62c0c583564f4"}, + {file = "mypy-0.920-cp36-cp36m-win_amd64.whl", hash = "sha256:562a0e335222d5bbf5162b554c3afe3745b495d67c7fe6f8b0d1b5bace0c1eeb"}, + {file = "mypy-0.920-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:618e677aabd21f30670bffb39a885a967337f5b112c6fb7c79375e6dced605d6"}, + {file = "mypy-0.920-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40cb062f1b7ff4cd6e897a89d8ddc48c6ad7f326b5277c93a8c559564cc1551c"}, + {file = "mypy-0.920-cp37-cp37m-win_amd64.whl", hash = "sha256:69b5a835b12fdbfeed84ef31152d41343d32ccb2b345256d8682324409164330"}, + {file = "mypy-0.920-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:993c2e52ea9570e6e872296c046c946377b9f5e89eeb7afea2a1524cf6e50b27"}, + {file = "mypy-0.920-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df0fec878ccfcb2d1d2306ba31aa757848f681e7bbed443318d9bbd4b0d0fe9a"}, + {file = "mypy-0.920-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:331a81d2c9bf1be25317260a073b41f4584cd11701a7c14facef0aa5a005e843"}, + {file = "mypy-0.920-cp38-cp38-win_amd64.whl", hash = "sha256:ffb1e57ec49a30e3c0ebcfdc910ae4aceb7afb649310b7355509df6b15bd75f6"}, + {file = "mypy-0.920-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:31895b0b3060baf15bf76e789d94722c026f673b34b774bba9e8772295edccff"}, + {file = "mypy-0.920-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:140174e872d20d4768124a089b9f9fc83abd6a349b7f8cc6276bc344eb598922"}, + {file = "mypy-0.920-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:13b3c110309b53f5a62aa1b360f598124be33a42563b790a2a9efaacac99f1fc"}, + {file = "mypy-0.920-cp39-cp39-win_amd64.whl", hash = "sha256:82e6c15675264e923b60a11d6eb8f90665504352e68edfbb4a79aac7a04caddd"}, + {file = "mypy-0.920-py3-none-any.whl", hash = "sha256:71c77bd885d2ce44900731d4652d0d1c174dc66a0f11200e0c680bdedf1a6b37"}, + {file = "mypy-0.920.tar.gz", hash = "sha256:a55438627f5f546192f13255a994d6d1cf2659df48adcf966132b4379fd9c86b"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -1394,24 +1426,32 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1419,6 +1459,8 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, diff --git a/pyproject.toml b/pyproject.toml index c26c6b1d29..cb6674fed0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ jupyter = ["ipywidgets"] [tool.poetry.dev-dependencies] pytest = "^6.2.5" black = "^21.11b1" -mypy = "^0.910" +mypy = "^0.920" pytest-cov = "^3.0.0" attrs = "^21.2.0" types-dataclasses = "^0.6.1" From 58018cd4fe6960aa21da9377fdb38985113f1680 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 13:03:08 +0000 Subject: [PATCH 157/287] Bump sphinx from 4.3.1 to 4.3.2 Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.1 to 4.3.2. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.1...v4.3.2) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 61da40a33d..716b1b3ddc 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ alabaster==0.7.12 -Sphinx==4.3.1 +Sphinx==4.3.2 sphinx-rtd-theme==1.0.0 sphinx-copybutton==0.4.0 From 288e8e2d8396eb01dc23ea77ae9195aad10c3fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20G=C3=B6rner?= <5477952+MaxG87@users.noreply.github.com> Date: Mon, 27 Dec 2021 08:25:26 +0100 Subject: [PATCH 158/287] Fix import command in German README --- README.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.de.md b/README.de.md index 3e419ae6ea..f8e79fcffc 100644 --- a/README.de.md +++ b/README.de.md @@ -40,7 +40,7 @@ Rich funktioniert ohne zusätzliche Konfiguration mit [Jupyter Notebooks](https: Installation mit `pip` oder deinem bevorzugten PyPI-Paketmanager. ``` -python -m rich +python -m pip install rich ``` Führe die folgenden Schritte aus, um die Rich-Ausgabe auf deinem Terminal zu testen: From 5422537585895d0797f8c20d4c9b4a17de172521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20G=C3=B6rner?= <5477952+MaxG87@users.noreply.github.com> Date: Mon, 27 Dec 2021 08:25:52 +0100 Subject: [PATCH 159/287] Use `python -m pip` as install snippet It is advised to not use `pip` plain, it should always be `python -m pip`. One important benefit is that this way one always installs packages to the currently active virtual environment. The topic is covered in depth at https://snarky.ca/why-you-should-use-python-m-pip/. --- README.cn.md | 2 +- README.de-ch.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.hi.md | 2 +- README.it.md | 2 +- README.ja.md | 2 +- README.kr.md | 2 +- README.md | 2 +- README.pt-br.md | 2 +- README.sv.md | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.cn.md b/README.cn.md index f7cb2768e4..f49757f266 100644 --- a/README.cn.md +++ b/README.cn.md @@ -40,7 +40,7 @@ Rich 还可以与[Jupyter 笔记本](https://jupyter.org/)一起使用,而无 使用`pip`或其他 PyPI 软件包管理器进行安装。 ``` -pip install rich +python -m pip install rich ``` ## Rich 的打印功能 diff --git a/README.de-ch.md b/README.de-ch.md index 4d33d22735..edf7f5265e 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -40,7 +40,7 @@ Rich funktioniert mit [Jupyter notebooks](https://jupyter.org/) ohni irgendwelch Installation mit `pip` oder mit dim liäblings PyPI Päckli-Manager. ``` -pip install rich +python -m pip install rich ``` Für das do us zum d Rich usgob im Törminäl z teste: diff --git a/README.es.md b/README.es.md index 5edad6900b..4345f0da8e 100644 --- a/README.es.md +++ b/README.es.md @@ -40,7 +40,7 @@ Rich funciona con [Jupyter notebooks](https://jupyter.org/) sin necesidad de con Instale con `pip` o su administrador de paquetes PyPI favorito. ``` -pip install rich +python -m pip install rich ``` Ejecute lo siguiente para probar la salida de Rich sobre su terminal: diff --git a/README.fr.md b/README.fr.md index 13da865010..32665d3fd4 100644 --- a/README.fr.md +++ b/README.fr.md @@ -40,7 +40,7 @@ Rich fonctionne avec les notebooks Jupyter sans configuration supplémentaire. Installez avec `pip` ou votre gestionnaire de paquets PyPI préféré. ``` -pip install rich +python -m pip install rich ``` Exécutez ce qui suit pour tester la sortie de Rich sur votre terminal : diff --git a/README.hi.md b/README.hi.md index 569a549e81..8a0c0b59d4 100644 --- a/README.hi.md +++ b/README.hi.md @@ -42,7 +42,7 @@ Rich बिना किसी अतिरिक्त विन्यास `pip` या अपने पसंदीदा PyPI संकुल प्रबंधक (package manager) के द्वारा आप इसे स्थापित कर सकते हैं। ``` -pip install rich +python -m pip install rich ``` आपके टर्मिनल पर Rich उत्पादन का परीक्षण करने के लिए यह चलाएं: diff --git a/README.it.md b/README.it.md index 738f8b5fe3..749d71b80b 100644 --- a/README.it.md +++ b/README.it.md @@ -40,7 +40,7 @@ Rich funziona con i [Jupyter notebooks](https://jupyter.org/) senza configurazio Installa con `pip` o il tuo PyPI package manager preferito. ```shell -pip install rich +python -m pip install rich ``` Esegui il seguente comando per testare l'output di Rich sul tuo terminale: diff --git a/README.ja.md b/README.ja.md index 93c87c954f..f130c53f13 100644 --- a/README.ja.md +++ b/README.ja.md @@ -40,7 +40,7 @@ Richは追加の設定を行わずとも、[Jupyter notebooks](https://jupyter.o `pip` や、あなたのお気に入りのPyPIパッケージマネージャを使ってインストールしてください。 ``` -pip install rich +python -m pip install rich ``` 以下のコマンドを実行して、ターミナルでリッチの出力をテストできます: diff --git a/README.kr.md b/README.kr.md index b0a3508ba7..43d9f7d20e 100644 --- a/README.kr.md +++ b/README.kr.md @@ -40,7 +40,7 @@ Rich는 [Jupyter notebooks](https://jupyter.org/)에서 별도의 설정없이 `pip` 또는 좋아하는 PyPI 패키지 매니저로 설치하세요. ``` -pip install rich +python -m pip install rich ``` 아래 명령어를 통해 터미널에서 Rich 출력을 테스트해보세요. diff --git a/README.md b/README.md index ecd7a65c16..cbf5ba5f48 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Rich works with [Jupyter notebooks](https://jupyter.org/) with no additional con Install with `pip` or your favorite PyPI package manager. ``` -pip install rich +python -m pip install rich ``` Run the following to test Rich output on your terminal: diff --git a/README.pt-br.md b/README.pt-br.md index d4180467af..089810f380 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -39,7 +39,7 @@ Rich funciona com [Jupyter notebooks](https://jupyter.org/) sem a necessidade de Instale usando `pip` ou seu gerenciador de pacotes PyPI favorito. ``` -pip install rich +python -m pip install rich ``` Execute o seguinte comando para testar o output do Rich no seu terminal: diff --git a/README.sv.md b/README.sv.md index e14e520790..0a7dbc50e0 100644 --- a/README.sv.md +++ b/README.sv.md @@ -39,7 +39,7 @@ Rich funkar med [Jupyter notebooks](https://jupyter.org/) utan någon ytterligar Installera med `pip` eller din favorita PyPI packet hanterare. ``` -pip install rich +python -m pip install rich ``` Kör följade följande för att testa Rich utmatning i din terminal: From f1bdd3040db96d3436276cdc2e6072c4fd39f86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20G=C3=B6rner?= <5477952+MaxG87@users.noreply.github.com> Date: Mon, 27 Dec 2021 08:32:34 +0100 Subject: [PATCH 160/287] Use "sh" code block language specification In order to indicate that a block contains shell code one should use e.g. "sh". Under https://github.com/github/linguist/blob/master/lib/linguist/languages.yml#L5602 the exhaustive list can be found. The one file that already used "shell" was corrected. The indicator "shell" is used for interactive session snippets. See https://stackoverflow.com/a/49004070/8831116 for a reference. --- README.cn.md | 2 +- README.de-ch.md | 4 ++-- README.de.md | 4 ++-- README.es.md | 4 ++-- README.fr.md | 4 ++-- README.hi.md | 4 ++-- README.it.md | 4 ++-- README.ja.md | 4 ++-- README.kr.md | 4 ++-- README.md | 4 ++-- README.pt-br.md | 4 ++-- README.sv.md | 4 ++-- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.cn.md b/README.cn.md index f49757f266..d9959d1db1 100644 --- a/README.cn.md +++ b/README.cn.md @@ -39,7 +39,7 @@ Rich 还可以与[Jupyter 笔记本](https://jupyter.org/)一起使用,而无 使用`pip`或其他 PyPI 软件包管理器进行安装。 -``` +```sh python -m pip install rich ``` diff --git a/README.de-ch.md b/README.de-ch.md index edf7f5265e..2b7de59e96 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -39,13 +39,13 @@ Rich funktioniert mit [Jupyter notebooks](https://jupyter.org/) ohni irgendwelch Installation mit `pip` oder mit dim liäblings PyPI Päckli-Manager. -``` +```sh python -m pip install rich ``` Für das do us zum d Rich usgob im Törminäl z teste: -``` +```sh python -m rich ``` diff --git a/README.de.md b/README.de.md index f8e79fcffc..56878a460f 100644 --- a/README.de.md +++ b/README.de.md @@ -39,13 +39,13 @@ Rich funktioniert ohne zusätzliche Konfiguration mit [Jupyter Notebooks](https: Installation mit `pip` oder deinem bevorzugten PyPI-Paketmanager. -``` +```sh python -m pip install rich ``` Führe die folgenden Schritte aus, um die Rich-Ausgabe auf deinem Terminal zu testen: -``` +```sh python -m rich ``` diff --git a/README.es.md b/README.es.md index 4345f0da8e..2fd22f022c 100644 --- a/README.es.md +++ b/README.es.md @@ -39,13 +39,13 @@ Rich funciona con [Jupyter notebooks](https://jupyter.org/) sin necesidad de con Instale con `pip` o su administrador de paquetes PyPI favorito. -``` +```sh python -m pip install rich ``` Ejecute lo siguiente para probar la salida de Rich sobre su terminal: -``` +```sh python -m rich ``` diff --git a/README.fr.md b/README.fr.md index 32665d3fd4..5436d77068 100644 --- a/README.fr.md +++ b/README.fr.md @@ -39,13 +39,13 @@ Rich fonctionne avec les notebooks Jupyter sans configuration supplémentaire. Installez avec `pip` ou votre gestionnaire de paquets PyPI préféré. -``` +```sh python -m pip install rich ``` Exécutez ce qui suit pour tester la sortie de Rich sur votre terminal : -``` +```sh python -m rich ``` diff --git a/README.hi.md b/README.hi.md index 8a0c0b59d4..4a35e8335d 100644 --- a/README.hi.md +++ b/README.hi.md @@ -41,12 +41,12 @@ Rich बिना किसी अतिरिक्त विन्यास `pip` या अपने पसंदीदा PyPI संकुल प्रबंधक (package manager) के द्वारा आप इसे स्थापित कर सकते हैं। -``` +```sh python -m pip install rich ``` आपके टर्मिनल पर Rich उत्पादन का परीक्षण करने के लिए यह चलाएं: -``` +```sh python -m rich ``` diff --git a/README.it.md b/README.it.md index 749d71b80b..cd7809aed6 100644 --- a/README.it.md +++ b/README.it.md @@ -39,13 +39,13 @@ Rich funziona con i [Jupyter notebooks](https://jupyter.org/) senza configurazio Installa con `pip` o il tuo PyPI package manager preferito. -```shell +```sh python -m pip install rich ``` Esegui il seguente comando per testare l'output di Rich sul tuo terminale: -```shell +```sh python -m rich ``` diff --git a/README.ja.md b/README.ja.md index f130c53f13..dcd74a9655 100644 --- a/README.ja.md +++ b/README.ja.md @@ -39,13 +39,13 @@ Richは追加の設定を行わずとも、[Jupyter notebooks](https://jupyter.o `pip` や、あなたのお気に入りのPyPIパッケージマネージャを使ってインストールしてください。 -``` +```sh python -m pip install rich ``` 以下のコマンドを実行して、ターミナルでリッチの出力をテストできます: -``` +```sh python -m rich ``` diff --git a/README.kr.md b/README.kr.md index 43d9f7d20e..c345b3c893 100644 --- a/README.kr.md +++ b/README.kr.md @@ -39,13 +39,13 @@ Rich는 [Jupyter notebooks](https://jupyter.org/)에서 별도의 설정없이 `pip` 또는 좋아하는 PyPI 패키지 매니저로 설치하세요. -``` +```sh python -m pip install rich ``` 아래 명령어를 통해 터미널에서 Rich 출력을 테스트해보세요. -``` +```sh python -m rich ``` diff --git a/README.md b/README.md index cbf5ba5f48..42a7a570a0 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,13 @@ Rich works with [Jupyter notebooks](https://jupyter.org/) with no additional con Install with `pip` or your favorite PyPI package manager. -``` +```sh python -m pip install rich ``` Run the following to test Rich output on your terminal: -``` +```sh python -m rich ``` diff --git a/README.pt-br.md b/README.pt-br.md index 089810f380..fd2de06ec1 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -38,13 +38,13 @@ Rich funciona com [Jupyter notebooks](https://jupyter.org/) sem a necessidade de Instale usando `pip` ou seu gerenciador de pacotes PyPI favorito. -``` +```sh python -m pip install rich ``` Execute o seguinte comando para testar o output do Rich no seu terminal: -``` +```sh python -m rich ``` diff --git a/README.sv.md b/README.sv.md index 0a7dbc50e0..41564f7eeb 100644 --- a/README.sv.md +++ b/README.sv.md @@ -38,13 +38,13 @@ Rich funkar med [Jupyter notebooks](https://jupyter.org/) utan någon ytterligar Installera med `pip` eller din favorita PyPI packet hanterare. -``` +```sh python -m pip install rich ``` Kör följade följande för att testa Rich utmatning i din terminal: -``` +```sh python -m rich ``` From c395254ed3b710e35688ddc13249e2f53f56d661 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Dec 2021 13:03:55 +0000 Subject: [PATCH 161/287] Bump types-dataclasses from 0.6.1 to 0.6.2 Bumps [types-dataclasses](https://github.com/python/typeshed) from 0.6.1 to 0.6.2. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-dataclasses dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0f129a7dbf..76d0a0b8fc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -886,7 +886,7 @@ python-versions = "*" [[package]] name = "types-dataclasses" -version = "0.6.1" +version = "0.6.2" description = "Typing stubs for dataclasses" category = "dev" optional = false @@ -945,7 +945,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "6239ee87a97b028b97a30dae0b58017b53c96ffb6b4e6c655fc821d73042ad62" +content-hash = "9ceb81b5ba7b4c7e566c4adaaec17a86c5092c157a423ba9e7c716502607357c" [metadata.files] appnope = [ @@ -1573,8 +1573,8 @@ typed-ast = [ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] types-dataclasses = [ - {file = "types-dataclasses-0.6.1.tar.gz", hash = "sha256:6568532fed11f854e4db2eb48063385b323b93ecadd09f10a215d56246c306d7"}, - {file = "types_dataclasses-0.6.1-py3-none-any.whl", hash = "sha256:aa45bb0dacdba09e3195a36ff8337bba45eac03b6f31c4645e87b4a2a47830dd"}, + {file = "types-dataclasses-0.6.2.tar.gz", hash = "sha256:d74876d7a5e39ae6285765dd871e3b85d8186251f7b48e18130a35024c78bf73"}, + {file = "types_dataclasses-0.6.2-py3-none-any.whl", hash = "sha256:19ea746937b82bfa0d3bba1dd78858eca2ed81932eae888c3f2966aa3fd0aec6"}, ] typing-extensions = [ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, diff --git a/pyproject.toml b/pyproject.toml index cb6674fed0..68484aff9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ black = "^21.11b1" mypy = "^0.920" pytest-cov = "^3.0.0" attrs = "^21.2.0" -types-dataclasses = "^0.6.1" +types-dataclasses = "^0.6.2" [build-system] requires = ["poetry-core>=1.0.0"] From e2024482643b962e9dca3b7e82f214a439298a0e Mon Sep 17 00:00:00 2001 From: AaronBeaudoin Date: Wed, 29 Dec 2021 12:51:13 -0600 Subject: [PATCH 162/287] Fix flipped traceback border styles --- rich/traceback.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/traceback.py b/rich/traceback.py index 4315fe0539..63c4e2fc00 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -450,7 +450,7 @@ def __rich_console__( self._render_stack(stack), title="[traceback.title]Traceback [dim](most recent call last)", style=background_style, - border_style="traceback.border.syntax_error", + border_style="traceback.border", expand=True, padding=(0, 1), ) @@ -463,7 +463,7 @@ def __rich_console__( Panel( self._render_syntax_error(stack.syntax_error), style=background_style, - border_style="traceback.border", + border_style="traceback.border.syntax_error", expand=True, padding=(0, 1), width=self.width, From ca7d0e695cc6ad128d64957fb72b5ed29edf488d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 31 Dec 2021 10:48:12 +0000 Subject: [PATCH 163/287] fix mypy --- rich/text.py | 27 +++++++++++++++------------ rich/traceback.py | 7 +++++-- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/rich/text.py b/rich/text.py index 8061f8d1a8..d9ac2c0d6d 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1078,18 +1078,21 @@ def divide(self, offsets: Iterable[int]) -> Lines: break start_line_no = (lower_bound + upper_bound) // 2 - end_line_no = lower_bound = start_line_no - upper_bound = line_count - - while True: - line_start, line_end = line_ranges[end_line_no] - if span_end < line_start: - upper_bound = end_line_no - 1 - elif span_end > line_end: - lower_bound = end_line_no + 1 - else: - break - end_line_no = (lower_bound + upper_bound) // 2 + if span_end < line_end: + end_line_no = start_line_no + else: + end_line_no = lower_bound = start_line_no + upper_bound = line_count + + while True: + line_start, line_end = line_ranges[end_line_no] + if span_end < line_start: + upper_bound = end_line_no - 1 + elif span_end > line_end: + lower_bound = end_line_no + 1 + else: + break + end_line_no = (lower_bound + upper_bound) // 2 for line_no in range(start_line_no, end_line_no + 1): line_start, line_end = line_ranges[line_no] diff --git a/rich/traceback.py b/rich/traceback.py index 4315fe0539..c157218031 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -138,12 +138,12 @@ def ipy_display_traceback( # if wihin ipython, use customized traceback ip = get_ipython() # type: ignore ipy_excepthook_closure(ip) - return sys.excepthook # type: ignore # more strict signature that mypy can't interpret + return sys.excepthook except Exception: # otherwise use default system hook old_excepthook = sys.excepthook sys.excepthook = excepthook - return old_excepthook # type: ignore # more strict signature that mypy can't interpret + return old_excepthook @dataclass @@ -246,6 +246,9 @@ def __init__( self.suppress: Sequence[str] = [] for suppress_entity in suppress: if not isinstance(suppress_entity, str): + assert ( + suppress_entity.__file__ is not None + ), f"{suppress_entity!r} must be a module with '__file__' attribute" path = os.path.dirname(suppress_entity.__file__) else: path = suppress_entity From a4a4969d7e41dfb6087270cdc477547512a45530 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Dec 2021 10:55:57 +0000 Subject: [PATCH 164/287] Bump mypy from 0.920 to 0.930 Bumps [mypy](https://github.com/python/mypy) from 0.920 to 0.930. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.920...v0.930) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 50 +++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/poetry.lock b/poetry.lock index 76d0a0b8fc..4ddaa82933 100644 --- a/poetry.lock +++ b/poetry.lock @@ -425,17 +425,17 @@ python-versions = "*" [[package]] name = "mypy" -version = "0.920" +version = "0.930" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] -mypy-extensions = ">=0.4.3,<0.5.0" -tomli = ">=1.1.0,<3.0.0" +mypy-extensions = ">=0.4.3" +tomli = ">=1.1.0" typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} -typing-extensions = ">=3.7.4" +typing-extensions = ">=3.10" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -945,7 +945,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "9ceb81b5ba7b4c7e566c4adaaec17a86c5092c157a423ba9e7c716502607357c" +content-hash = "ccb268f01aef22259eb1ef17b807ccc1088b4b13345d4209dd27a5efc101920e" [metadata.files] appnope = [ @@ -1260,26 +1260,26 @@ mistune = [ {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] mypy = [ - {file = "mypy-0.920-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41f3575b20714171c832d8f6c7aaaa0d499c9a2d1b8adaaf837b4c9065c38540"}, - {file = "mypy-0.920-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:431be889ffc8d9681813a45575c42e341c19467cbfa6dd09bf41467631feb530"}, - {file = "mypy-0.920-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f8b2059f73878e92eff7ed11a03515d6572f4338a882dd7547b5f7dd242118e6"}, - {file = "mypy-0.920-cp310-cp310-win_amd64.whl", hash = "sha256:9cd316e9705555ca6a50670ba5fb0084d756d1d8cb1697c83820b1456b0bc5f3"}, - {file = "mypy-0.920-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e091fe58b4475b3504dc7c3022ff7f4af2f9e9ddf7182047111759ed0973bbde"}, - {file = "mypy-0.920-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98b4f91a75fed2e4c6339e9047aba95968d3a7c4b91e92ab9dc62c0c583564f4"}, - {file = "mypy-0.920-cp36-cp36m-win_amd64.whl", hash = "sha256:562a0e335222d5bbf5162b554c3afe3745b495d67c7fe6f8b0d1b5bace0c1eeb"}, - {file = "mypy-0.920-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:618e677aabd21f30670bffb39a885a967337f5b112c6fb7c79375e6dced605d6"}, - {file = "mypy-0.920-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40cb062f1b7ff4cd6e897a89d8ddc48c6ad7f326b5277c93a8c559564cc1551c"}, - {file = "mypy-0.920-cp37-cp37m-win_amd64.whl", hash = "sha256:69b5a835b12fdbfeed84ef31152d41343d32ccb2b345256d8682324409164330"}, - {file = "mypy-0.920-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:993c2e52ea9570e6e872296c046c946377b9f5e89eeb7afea2a1524cf6e50b27"}, - {file = "mypy-0.920-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df0fec878ccfcb2d1d2306ba31aa757848f681e7bbed443318d9bbd4b0d0fe9a"}, - {file = "mypy-0.920-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:331a81d2c9bf1be25317260a073b41f4584cd11701a7c14facef0aa5a005e843"}, - {file = "mypy-0.920-cp38-cp38-win_amd64.whl", hash = "sha256:ffb1e57ec49a30e3c0ebcfdc910ae4aceb7afb649310b7355509df6b15bd75f6"}, - {file = "mypy-0.920-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:31895b0b3060baf15bf76e789d94722c026f673b34b774bba9e8772295edccff"}, - {file = "mypy-0.920-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:140174e872d20d4768124a089b9f9fc83abd6a349b7f8cc6276bc344eb598922"}, - {file = "mypy-0.920-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:13b3c110309b53f5a62aa1b360f598124be33a42563b790a2a9efaacac99f1fc"}, - {file = "mypy-0.920-cp39-cp39-win_amd64.whl", hash = "sha256:82e6c15675264e923b60a11d6eb8f90665504352e68edfbb4a79aac7a04caddd"}, - {file = "mypy-0.920-py3-none-any.whl", hash = "sha256:71c77bd885d2ce44900731d4652d0d1c174dc66a0f11200e0c680bdedf1a6b37"}, - {file = "mypy-0.920.tar.gz", hash = "sha256:a55438627f5f546192f13255a994d6d1cf2659df48adcf966132b4379fd9c86b"}, + {file = "mypy-0.930-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:221cc94dc6a801ccc2be7c0c9fd791c5e08d1fa2c5e1c12dec4eab15b2469871"}, + {file = "mypy-0.930-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db3a87376a1380f396d465bed462e76ea89f838f4c5e967d68ff6ee34b785c31"}, + {file = "mypy-0.930-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1d2296f35aae9802eeb1327058b550371ee382d71374b3e7d2804035ef0b830b"}, + {file = "mypy-0.930-cp310-cp310-win_amd64.whl", hash = "sha256:959319b9a3cafc33a8185f440a433ba520239c72e733bf91f9efd67b0a8e9b30"}, + {file = "mypy-0.930-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:45a4dc21c789cfd09b8ccafe114d6de66f0b341ad761338de717192f19397a8c"}, + {file = "mypy-0.930-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1e689e92cdebd87607a041585f1dc7339aa2e8a9f9bad9ba7e6ece619431b20c"}, + {file = "mypy-0.930-cp36-cp36m-win_amd64.whl", hash = "sha256:ed4e0ea066bb12f56b2812a15ff223c57c0a44eca817ceb96b214bb055c7051f"}, + {file = "mypy-0.930-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a9d8dffefba634b27d650e0de2564379a1a367e2e08d6617d8f89261a3bf63b2"}, + {file = "mypy-0.930-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b419e9721260161e70d054a15abbd50603c16f159860cfd0daeab647d828fc29"}, + {file = "mypy-0.930-cp37-cp37m-win_amd64.whl", hash = "sha256:601f46593f627f8a9b944f74fd387c9b5f4266b39abad77471947069c2fc7651"}, + {file = "mypy-0.930-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ea7199780c1d7940b82dbc0a4e37722b4e3851264dbba81e01abecc9052d8a7"}, + {file = "mypy-0.930-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:70b197dd8c78fc5d2daf84bd093e8466a2b2e007eedaa85e792e513a820adbf7"}, + {file = "mypy-0.930-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5feb56f8bb280468fe5fc8e6f56f48f99aa0df9eed3c507a11505ee4657b5380"}, + {file = "mypy-0.930-cp38-cp38-win_amd64.whl", hash = "sha256:2e9c5409e9cb81049bb03fa1009b573dea87976713e3898561567a86c4eaee01"}, + {file = "mypy-0.930-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:554873e45c1ca20f31ddf873deb67fa5d2e87b76b97db50669f0468ccded8fae"}, + {file = "mypy-0.930-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0feb82e9fa849affca7edd24713dbe809dce780ced9f3feca5ed3d80e40b777f"}, + {file = "mypy-0.930-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bc1a0607ea03c30225347334af66b0af12eefba018a89a88c209e02b7065ea95"}, + {file = "mypy-0.930-cp39-cp39-win_amd64.whl", hash = "sha256:f9f665d69034b1fcfdbcd4197480d26298bbfb5d2dfe206245b6498addb34999"}, + {file = "mypy-0.930-py3-none-any.whl", hash = "sha256:bf4a44e03040206f7c058d1f5ba02ef2d1820720c88bc4285c7d9a4269f54173"}, + {file = "mypy-0.930.tar.gz", hash = "sha256:51426262ae4714cc7dd5439814676e0992b55bcc0f6514eccb4cf8e0678962c2"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, diff --git a/pyproject.toml b/pyproject.toml index 68484aff9a..2ce920116c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ jupyter = ["ipywidgets"] [tool.poetry.dev-dependencies] pytest = "^6.2.5" black = "^21.11b1" -mypy = "^0.920" +mypy = "^0.930" pytest-cov = "^3.0.0" attrs = "^21.2.0" types-dataclasses = "^0.6.2" From 704501f8a5a69aed691a8489c12567f0324c4509 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Dec 2021 11:11:49 +0000 Subject: [PATCH 165/287] Bump attrs from 21.2.0 to 21.4.0 Bumps [attrs](https://github.com/python-attrs/attrs) from 21.2.0 to 21.4.0. - [Release notes](https://github.com/python-attrs/attrs/releases) - [Changelog](https://github.com/python-attrs/attrs/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-attrs/attrs/compare/21.2.0...21.4.0) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 14 +++++++------- pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4ddaa82933..c26946367b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -57,17 +57,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "backcall" @@ -945,7 +945,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "ccb268f01aef22259eb1ef17b807ccc1088b4b13345d4209dd27a5efc101920e" +content-hash = "9323c671d22223dca6b8630798611fd990a0e3d7ac15d97ac4cece4fc89b3bb4" [metadata.files] appnope = [ @@ -988,8 +988,8 @@ atomicwrites = [ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] backcall = [ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, diff --git a/pyproject.toml b/pyproject.toml index 2ce920116c..50e121b158 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ pytest = "^6.2.5" black = "^21.11b1" mypy = "^0.930" pytest-cov = "^3.0.0" -attrs = "^21.2.0" +attrs = "^21.4.0" types-dataclasses = "^0.6.2" [build-system] From 86e0887b1d600ac88020278c5bfe086fb744beb8 Mon Sep 17 00:00:00 2001 From: Joe Halliwell Date: Sun, 12 Dec 2021 11:04:20 +0000 Subject: [PATCH 166/287] Add per-message override for log highlighter --- rich/logging.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rich/logging.py b/rich/logging.py index 47ca7d42de..435ecc4e93 100644 --- a/rich/logging.py +++ b/rich/logging.py @@ -10,6 +10,7 @@ from .highlighter import Highlighter, ReprHighlighter from .text import Text from .traceback import Traceback +from rich import highlighter class RichHandler(Handler): @@ -168,8 +169,13 @@ def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable" getattr(record, "markup") if hasattr(record, "markup") else self.markup ) message_text = Text.from_markup(message) if use_markup else Text(message) - if self.highlighter: - message_text = self.highlighter(message_text) + highlighter = ( + getattr(record, "highlighter") + if hasattr(record, "highlighter") + else self.highlighter + ) + if highlighter: + message_text = highlighter(message_text) if self.KEYWORDS: message_text.highlight_words(self.KEYWORDS, "logging.keyword") return message_text From 64b921727d4b47ac973f3cdb19ce1baba5d55b46 Mon Sep 17 00:00:00 2001 From: Joe Halliwell Date: Sun, 12 Dec 2021 11:05:49 +0000 Subject: [PATCH 167/287] Add tests for log markup and highlighting --- tests/test_logging.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/test_logging.py b/tests/test_logging.py index a1acc00222..a7353968ea 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -122,6 +122,46 @@ def mock_handle_error(record): assert "message" in actual_record.msg +def test_markup_and_highlight(): + console = Console( + file=io.StringIO(), + force_terminal=True, + width=140, + color_system="truecolor", + _environ={}, + ) + handler = RichHandler(console=console) + + # Check defaults are as expected + assert handler.highlighter + assert not handler.markup + + formatter = logging.Formatter("FORMATTER %(message)s %(asctime)s") + handler.setFormatter(formatter) + log.addHandler(handler) + + log_message = "foo 3.141 127.0.0.1 [red]alert[/red]" + + log.error(log_message) + render_fancy = handler.console.file.getvalue() + assert "FORMATTER" in render_fancy + assert log_message not in render_fancy + assert "red" in render_fancy + + handler.console.file = io.StringIO() + log.error(log_message, extra={"markup": True}) + render_markup = handler.console.file.getvalue() + assert "FORMATTER" in render_markup + assert log_message not in render_markup + assert "red" not in render_markup + + handler.console.file = io.StringIO() + log.error(log_message, extra={"highlighter": None}) + render_plain = handler.console.file.getvalue() + assert "FORMATTER" in render_plain + assert log_message in render_plain + + if __name__ == "__main__": render = make_log() print(render) From 23daac5d01de0f43ae02ac09eb477b279bfae4a8 Mon Sep 17 00:00:00 2001 From: Joe Halliwell Date: Sun, 12 Dec 2021 11:17:48 +0000 Subject: [PATCH 168/287] Add documentation --- docs/source/logging.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/logging.rst b/docs/source/logging.rst index b9077188ff..38daaf1f58 100644 --- a/docs/source/logging.rst +++ b/docs/source/logging.rst @@ -16,10 +16,14 @@ Here's an example of how to set up a rich logger:: log = logging.getLogger("rich") log.info("Hello, World!") -Rich logs won't render :ref:`console_markup` in logging by default as most libraries won't be aware of the need to escape literal square brackets, but you can enable it by setting ``markup=True`` on the handler. Alternatively you can enable it per log message by supplying the ``extra`` argument as follows:: +Rich logs won't render :ref:`console_markup` in logging by default as most libraries won't be aware of the need to escape literal square brackets, but you can enable it by setting ``markup=True`` on the handler. Alternatively you can enable it per log message by supplying the ``extra`` argument as follows:: log.error("[bold red blink]Server is shutting down![/]", extra={"markup": True}) +Similarly, the highlighter may be overridden per log message:: + + log.error("123 will not be highlighted", extra={"highlighter": None}) + Handle exceptions ------------------- From a8ae7b5c1e2633d1572390ae313b118b7413116f Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Fri, 31 Dec 2021 13:26:43 +0100 Subject: [PATCH 169/287] Fix for mypy --- rich/syntax.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index 05ebdf9aab..7dd5922a38 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -401,6 +401,8 @@ def highlight( def line_tokenize() -> Iterable[Tuple[Any, str]]: """Split tokens to one per line.""" + assert lexer + for token_type, token in lexer.get_tokens(code): while token: line_token, new_line, token = token.partition("\n") @@ -709,7 +711,7 @@ def __rich_console__( code = sys.stdin.read() syntax = Syntax( code=code, - lexer_name=args.lexer_name, + lexer=args.lexer_name, line_numbers=args.line_numbers, word_wrap=args.word_wrap, theme=args.theme, From de7ed16f71b54ab4ddc7d40ce67f918dfb9b5180 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Fri, 31 Dec 2021 13:29:26 +0100 Subject: [PATCH 170/287] Add docstring --- rich/syntax.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rich/syntax.py b/rich/syntax.py index 7dd5922a38..759351907a 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -351,6 +351,11 @@ def _get_token_color(self, token_type: TokenType) -> Optional[Color]: @property def lexer(self) -> Optional[Lexer]: + """The lexer for this syntax, or None if no lexer was found. + + Tries to find the lexer by name if a string was passed to the constructor. + """ + if isinstance(self._lexer, Lexer): return self._lexer try: From 300cff65b946b838e2578dbd3c87891c7b2030ae Mon Sep 17 00:00:00 2001 From: Joe Halliwell Date: Sun, 12 Dec 2021 11:25:41 +0000 Subject: [PATCH 171/287] Use getattr's built-in default --- rich/logging.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/rich/logging.py b/rich/logging.py index 435ecc4e93..6d85cd834b 100644 --- a/rich/logging.py +++ b/rich/logging.py @@ -165,17 +165,13 @@ def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable" Returns: ConsoleRenderable: Renderable to display log message. """ - use_markup = ( - getattr(record, "markup") if hasattr(record, "markup") else self.markup - ) + use_markup = getattr(record, "markup", self.markup) message_text = Text.from_markup(message) if use_markup else Text(message) - highlighter = ( - getattr(record, "highlighter") - if hasattr(record, "highlighter") - else self.highlighter - ) + + highlighter = getattr(record, "highlighter", self.highlighter) if highlighter: message_text = highlighter(message_text) + if self.KEYWORDS: message_text.highlight_words(self.KEYWORDS, "logging.keyword") return message_text From 8a3dc753cef0259933fbd5ee9bcd95614d24c0c6 Mon Sep 17 00:00:00 2001 From: Joe Halliwell Date: Sun, 12 Dec 2021 11:29:42 +0000 Subject: [PATCH 172/287] Remove unused import --- rich/logging.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rich/logging.py b/rich/logging.py index 6d85cd834b..002f1f7bf1 100644 --- a/rich/logging.py +++ b/rich/logging.py @@ -10,7 +10,6 @@ from .highlighter import Highlighter, ReprHighlighter from .text import Text from .traceback import Traceback -from rich import highlighter class RichHandler(Handler): From 1d5152ef52438f77db1d543beb03e972aa465962 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 2 Jan 2022 15:50:38 +0000 Subject: [PATCH 173/287] fix code block --- docs/source/text.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/text.rst b/docs/source/text.rst index 142b0639e1..9d8644f2ce 100644 --- a/docs/source/text.rst +++ b/docs/source/text.rst @@ -26,7 +26,7 @@ Alternatively, you can construct styled text by calling :meth:`~rich.text.Text.a text.append(" World!") console.print(text) -If you would like to use text that is already formatted with ANSI codes, call :meth:`~rich.text.Text.from_ansi` to convert it to a ``Text`` object: +If you would like to use text that is already formatted with ANSI codes, call :meth:`~rich.text.Text.from_ansi` to convert it to a ``Text`` object:: text = Text.from_ansi("\033[1mHello, World!\033[0m") console.print(text.spans) From 4b1293e00dc49513b8678be8d0ba51b50c5e0453 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 2 Jan 2022 16:51:41 +0000 Subject: [PATCH 174/287] fix at escape --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- rich/markup.py | 2 +- tests/test_markup.py | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22d187424b..db2fb521b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.16.2] - 2021-01-02 + +### Fixed + +- Fixed @ not being escaped in markup + ## [10.16.1] - 2021-12-15 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 50e121b158..e017d29c07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.1" +version = "10.16.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/markup.py b/rich/markup.py index 473f86ae1a..58903f6bbb 100644 --- a/rich/markup.py +++ b/rich/markup.py @@ -47,7 +47,7 @@ def markup(self) -> str: def escape( - markup: str, _escape: _EscapeSubMethod = re.compile(r"(\\*)(\[[a-z#\/].*?\])").sub + markup: str, _escape: _EscapeSubMethod = re.compile(r"(\\*)(\[[a-z#\/@].*?\])").sub ) -> str: """Escapes text so that it won't be interpreted as markup. diff --git a/tests/test_markup.py b/tests/test_markup.py index 24b0c4417b..139add2c14 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -32,6 +32,10 @@ def test_escape(): assert escape("[5]") == "[5]" assert escape("\\[5]") == "\\[5]" + # Test @ escape + assert escape("[@foo]") == "\\[@foo]" + assert escape("[@]") == "\\[@]" + def test_render_escape(): console = Console(width=80, color_system=None) From e839bfb3593b0de1dca4221c32a8098e72639893 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 2 Jan 2022 16:53:27 +0000 Subject: [PATCH 175/287] additional test --- tests/test_markup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_markup.py b/tests/test_markup.py index 139add2c14..5a0acbbf09 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -21,6 +21,9 @@ def test_re_match(): assert RE_TAGS.match("[color(1)]") assert RE_TAGS.match("[#ff00ff]") assert RE_TAGS.match("[/]") + assert RE_TAGS.match("[@]") + assert RE_TAGS.match("[@foo]") + assert RE_TAGS.match("[@foo=bar]") def test_escape(): From c3469772a44b393f69646277a810d81b70b2884c Mon Sep 17 00:00:00 2001 From: Aaron Stephens Date: Mon, 3 Jan 2022 01:04:35 -0800 Subject: [PATCH 176/287] docs: fix typos and whitespace --- docs/source/console.rst | 12 ++++++------ docs/source/highlighting.rst | 4 ++-- docs/source/introduction.rst | 4 ++-- docs/source/layout.rst | 4 ++-- docs/source/logging.rst | 2 +- docs/source/markup.rst | 4 ++-- docs/source/pretty.rst | 4 ++-- docs/source/progress.rst | 10 +++++----- docs/source/protocol.rst | 2 +- docs/source/style.rst | 4 ++-- docs/source/syntax.rst | 2 +- docs/source/tables.rst | 2 +- docs/source/text.rst | 2 +- docs/source/traceback.rst | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index 2b26e3104e..965fef7ee6 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -1,7 +1,7 @@ Console API =========== -For complete control over terminal formatting, Rich offers a :class:`~rich.console.Console` class. Most applications will require a single Console instance, so you may want to create one at the module level or as an attribute of your top-level object. For example, you could add a file called "console.py" to your project:: +For complete control over terminal formatting, Rich offers a :class:`~rich.console.Console` class. Most applications will require a single Console instance, so you may want to create one at the module level or as an attribute of your top-level object. For example, you could add a file called "console.py" to your project:: from rich.console import Console console = Console() @@ -52,7 +52,7 @@ To write rich content to the terminal use the :meth:`~rich.console.Console.print console.print(locals()) console.print("FOO", style="white on blue") -You can also use :meth:`~rich.console.Console.print` to render objects that support the :ref:`protocol`, which includes Rich's built in objects such as :class:`~rich.text.Text`, :class:`~rich.table.Table`, and :class:`~rich.syntax.Syntax` -- or other custom objects. +You can also use :meth:`~rich.console.Console.print` to render objects that support the :ref:`protocol`, which includes Rich's built-in objects such as :class:`~rich.text.Text`, :class:`~rich.table.Table`, and :class:`~rich.syntax.Syntax` -- or other custom objects. Logging @@ -170,7 +170,7 @@ Overflow Overflow is what happens when text you print is larger than the available space. Overflow may occur if you print long 'words' such as URLs for instance, or if you have text inside a panel or table cell with restricted space. -You can specify how Rich should handle overflow with the ``overflow`` argument to :meth:`~rich.console.Console.print` which should be one of the following strings: "fold", "crop", "ellipsis", or "ignore". The default is "fold" which will put any excess characters on the following line, creating as many new lines as required to fit the text. +You can specify how Rich should handle overflow with the ``overflow`` argument to :meth:`~rich.console.Console.print` which should be one of the following strings: "fold", "crop", "ellipsis", or "ignore". The default is "fold" which will put any excess characters on the following line, creating as many new lines as required to fit the text. The "crop" method truncates the text at the end of the line, discarding any characters that would overflow. @@ -223,7 +223,7 @@ The Console has a ``style`` attribute which you can use to apply a style to ever Soft Wrapping ------------- -Rich word wraps text you print by inserting line breaks. You can disable this behavior by setting ``soft_wrap=True`` when calling :meth:`~rich.console.Console.print`. With *soft wrapping* enabled any text that doesn't fit will run on to the following line(s), just like the builtin ``print``. +Rich word wraps text you print by inserting line breaks. You can disable this behavior by setting ``soft_wrap=True`` when calling :meth:`~rich.console.Console.print`. With *soft wrapping* enabled any text that doesn't fit will run on to the following line(s), just like the built-in ``print``. Cropping @@ -238,7 +238,7 @@ The :meth:`~rich.console.Console.print` method has a boolean ``crop`` argument. Input ----- -The console class has an :meth:`~rich.console.Console.input` method which works in the same way as Python's builtin :func:`input` function, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: +The console class has an :meth:`~rich.console.Console.input` method which works in the same way as Python's built-in :func:`input` function, but can use anything that Rich can print as a prompt. For example, here's a colorful prompt with an emoji:: from rich.console import Console console = Console() @@ -263,7 +263,7 @@ Error console The Console object will write to ``sys.stdout`` by default (so that you see output in the terminal). If you construct the Console with ``stderr=True`` Rich will write to ``sys.stderr``. You may want to use this to create an *error console* so you can split error messages from regular output. Here's an example:: - from rich.console import Console + from rich.console import Console error_console = Console(stderr=True) You might also want to set the ``style`` parameter on the Console to make error messages visually distinct. Here's how you might do that:: diff --git a/docs/source/highlighting.rst b/docs/source/highlighting.rst index 260cfbeacd..03993190c9 100644 --- a/docs/source/highlighting.rst +++ b/docs/source/highlighting.rst @@ -12,8 +12,8 @@ If the default highlighting doesn't fit your needs, you can define a custom high Here's an example which highlights text that looks like an email address:: - from rich.console import Console - from rich.highlighter import RegexHighlighter + from rich.console import Console + from rich.highlighter import RegexHighlighter from rich.theme import Theme class EmailHighlighter(RegexHighlighter): diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index bcbe906ea8..57d19154b5 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -10,7 +10,7 @@ Requirements Rich works with OSX, Linux and Windows. -On Windows both the (ancient) cmd.exe terminal is supported and the new `Windows Terminal `_. The later has much improved support for color and style. +On Windows both the (ancient) cmd.exe terminal is supported and the new `Windows Terminal `_. The latter has much improved support for color and style. Rich requires Python 3.6.1 and above. Note that Python 3.6.0 is *not* supported due to lack of support for methods on NamedTuples. @@ -63,7 +63,7 @@ This writes the following output to the terminal (including all the colors and s } -If you would rather not shadow Python's builtin print, you can import ``rich.print`` as ``rprint`` (for example):: +If you would rather not shadow Python's built-in print, you can import ``rich.print`` as ``rprint`` (for example):: from rich import print as rprint diff --git a/docs/source/layout.rst b/docs/source/layout.rst index f230931716..480956311f 100644 --- a/docs/source/layout.rst +++ b/docs/source/layout.rst @@ -99,7 +99,7 @@ This will set the upper portion to be exactly 10 rows, no matter the size of the Ratio ----- -In addition to a fixed size, you can also make a flexible layout setting the ``ratio`` argument on the constructor or by assigning to the attribute. The ratio defines how much of the screen the layout should occupy in relation to other layouts. For example, lets reset the size and set the ratio of the upper layout to 2:: +In addition to a fixed size, you can also make a flexible layout setting the ``ratio`` argument on the constructor or by assigning to the attribute. The ratio defines how much of the screen the layout should occupy in relation to other layouts. For example, let's reset the size and set the ratio of the upper layout to 2:: layout["upper"].size = None layout["upper"].ratio = 2 @@ -124,7 +124,7 @@ The top layout is now invisible, and the "lower" layout will expand to fill the layout["upper"].visible = True print(layout) -You could use this to toggle parts of your interface based on your applications configuration. +You could use this to toggle parts of your interface based on your application's configuration. Tree ---- diff --git a/docs/source/logging.rst b/docs/source/logging.rst index 38daaf1f58..2b1d853f63 100644 --- a/docs/source/logging.rst +++ b/docs/source/logging.rst @@ -28,7 +28,7 @@ Similarly, the highlighter may be overridden per log message:: Handle exceptions ------------------- -The :class:`~rich.logging.RichHandler` class may be configured to use Rich's :class:`~rich.traceback.Traceback` class to format exceptions, which provides more context than a builtin exception. To get beautiful exceptions in your logs set ``rich_tracebacks=True`` on the handler constructor:: +The :class:`~rich.logging.RichHandler` class may be configured to use Rich's :class:`~rich.traceback.Traceback` class to format exceptions, which provides more context than a built-in exception. To get beautiful exceptions in your logs set ``rich_tracebacks=True`` on the handler constructor:: import logging diff --git a/docs/source/markup.rst b/docs/source/markup.rst index 1ab925b089..7644bf8625 100644 --- a/docs/source/markup.rst +++ b/docs/source/markup.rst @@ -27,7 +27,7 @@ There is a shorthand for closing a style. If you omit the style name from the cl print("[bold red]Bold and red[/] not bold or red") -These markup tags may be use in combination with each other and don't need to be strictly nested. The following examples demonstrates overlapping of markup tags:: +These markup tags may be use in combination with each other and don't need to be strictly nested. The following example demonstrates overlapping of markup tags:: print("[bold]Bold[italic] bold and italic [/bold]italic[/italic]") @@ -86,7 +86,7 @@ If you add an *emoji code* to markup it will be replaced with the equivalent uni >>> print(":warning:") ⚠️ -Some emojis have two variants, the "emoji" variant displays in full color, and the "text" variant displays in monochrome (whatever your default colors are set to). You can specify the variant you want by adding either `"-emoji"` or `"-text"` to the emoji code. Here's an example: +Some emojis have two variants, the "emoji" variant displays in full color, and the "text" variant displays in monochrome (whatever your default colors are set to). You can specify the variant you want by adding either `"-emoji"` or `"-text"` to the emoji code. Here's an example: >>> from rich import print >>> print(":red_heart-emoji:") diff --git a/docs/source/pretty.rst b/docs/source/pretty.rst index 2c1c017ddd..7a050b9433 100644 --- a/docs/source/pretty.rst +++ b/docs/source/pretty.rst @@ -65,7 +65,7 @@ There are a large number of options to tweak the pretty formatting, See the :cla Rich Repr Protocol ------------------ -Rich is able to syntax highlight any output, but the formatting is restricted to builtin containers, dataclasses, and other objects Rich knows about, such as objects generated by the `attrs `_ library. To add Rich formatting capabilities to custom objects, you can implement the *rich repr protocol*. +Rich is able to syntax highlight any output, but the formatting is restricted to built-in containers, dataclasses, and other objects Rich knows about, such as objects generated by the `attrs `_ library. To add Rich formatting capabilities to custom objects, you can implement the *rich repr protocol*. Run the following command to see an example of what the Rich repr protocol can generate:: @@ -221,7 +221,7 @@ To automatically build a rich repr, use the :meth:`~rich.repr.auto` class decora from rich import print print(BIRDS) -Note that the decorator will also create a `__repr__`, so you you will get an auto-generated repr even if you don't print with Rich. +Note that the decorator will also create a `__repr__`, so you will get an auto-generated repr even if you don't print with Rich. If you want to auto-generate the angular type of repr, then set ``angular=True`` on the decorator:: diff --git a/docs/source/progress.rst b/docs/source/progress.rst index 364ad94ce8..1a4e02ed7d 100644 --- a/docs/source/progress.rst +++ b/docs/source/progress.rst @@ -59,12 +59,12 @@ Updating tasks When you call :meth:`~rich.progress.Progress.add_task` you get back a `Task ID`. Use this ID to call :meth:`~rich.progress.Progress.update` whenever you have completed some work, or any information has changed. Typically you will need to update ``completed`` every time you have completed a step. You can do this by updated ``completed`` directly or by setting ``advance`` which will add to the current ``completed`` value. -The :meth:`~rich.progress.Progress.update` method collects keyword arguments which are also associated with the task. Use this to supply any additional information you would like to render in the progress display. The additional arguments are stored in ``task.fields`` and may be referenced in :ref:`Column classes`. +The :meth:`~rich.progress.Progress.update` method collects keyword arguments which are also associated with the task. Use this to supply any additional information you would like to render in the progress display. The additional arguments are stored in ``task.fields`` and may be referenced in :ref:`Column classes`. Hiding tasks ~~~~~~~~~~~~ -You can show or hide tasks by updating the tasks ``visible`` value. Tasks are visible by default, but you can also add a invisible task by calling :meth:`~rich.progress.Progress.add_task` with ``visible=False``. +You can show or hide tasks by updating the tasks ``visible`` value. Tasks are visible by default, but you can also add an invisible task by calling :meth:`~rich.progress.Progress.add_task` with ``visible=False``. Transient progress @@ -174,7 +174,7 @@ If you have another Console object you want to use, pass it in to the :class:`~r Redirecting stdout / stderr ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To avoid breaking the progress display visuals, Rich will redirect ``stdout`` and ``stderr`` so that you can use the builtin ``print`` statement. This feature is enabled by default, but you can disable by setting ``redirect_stdout`` or ``redirect_stderr`` to ``False`` +To avoid breaking the progress display visuals, Rich will redirect ``stdout`` and ``stderr`` so that you can use the built-in ``print`` statement. This feature is enabled by default, but you can disable by setting ``redirect_stdout`` or ``redirect_stderr`` to ``False`` Customizing @@ -187,12 +187,12 @@ If the :class:`~rich.progress.Progress` class doesn't offer exactly what you nee class MyProgress(Progress): def get_renderables(self): - yield Panel(self.make_tasks_table(self.tasks)) + yield Panel(self.make_tasks_table(self.tasks)) Multiple Progress ----------------- -You can't have different columns per task with a single Progress instance. However, you can have as many Progress instance as you like in a :ref:`live`. See `live_progress.py `_ and `dynamic_progress.py `_ for examples of using multiple Progress instances. +You can't have different columns per task with a single Progress instance. However, you can have as many Progress instances as you like in a :ref:`live`. See `live_progress.py `_ and `dynamic_progress.py `_ for examples of using multiple Progress instances. Example ------- diff --git a/docs/source/protocol.rst b/docs/source/protocol.rst index 796bed6467..cd8c03a4ab 100644 --- a/docs/source/protocol.rst +++ b/docs/source/protocol.rst @@ -4,7 +4,7 @@ Console Protocol ================ -Rich supports a simple protocol to add rich formatting capabilities to custom objects, so you can :meth:`~rich.console.Console.print` your object with color, styles and formatting. +Rich supports a simple protocol to add rich formatting capabilities to custom objects, so you can :meth:`~rich.console.Console.print` your object with color, styles and formatting. Use this for presentation or to display additional debugging information that might be hard to parse from a typical ``__repr__`` string. diff --git a/docs/source/style.rst b/docs/source/style.rst index ee9eca5df0..c9a5fe92c5 100644 --- a/docs/source/style.rst +++ b/docs/source/style.rst @@ -106,7 +106,7 @@ You can parse a style definition explicitly with the :meth:`~rich.style.Style.pa Style Themes ------------ -If you re-use styles it can be a maintenance headache if you ever want to modify an attribute or color -- you would have to change every line where the style is used. Rich provides a :class:`~rich.theme.Theme` class which you can use to define custom styles that you can refer to by name. That way you only need update your styles in one place. +If you re-use styles it can be a maintenance headache if you ever want to modify an attribute or color -- you would have to change every line where the style is used. Rich provides a :class:`~rich.theme.Theme` class which you can use to define custom styles that you can refer to by name. That way you only need to update your styles in one place. Style themes can make your code more semantic, for instance a style called ``"warning"`` better expresses intent that ``"italic magenta underline"``. @@ -132,7 +132,7 @@ To use a style theme, construct a :class:`~rich.theme.Theme` instance and pass i Customizing Defaults ~~~~~~~~~~~~~~~~~~~~ -The Theme class will inherit the default styles builtin to Rich. If your custom theme contains the name of an existing style, it will replace it. This allows you to customize the defaults as easily as you can create your own styles. For instance, here's how you can change how Rich highlights numbers:: +The Theme class will inherit the default styles built-in to Rich. If your custom theme contains the name of an existing style, it will replace it. This allows you to customize the defaults as easily as you can create your own styles. For instance, here's how you can change how Rich highlights numbers:: from rich.console import Console from rich.theme import Theme diff --git a/docs/source/syntax.rst b/docs/source/syntax.rst index 823d345c8b..4e55bf9967 100644 --- a/docs/source/syntax.rst +++ b/docs/source/syntax.rst @@ -10,7 +10,7 @@ To syntax highlight code, construct a :class:`~rich.syntax.Syntax` object and pr console = Console() with open("syntax.py", "rt") as code_file: - syntax = Syntax(code_file.read(), "python") + syntax = Syntax(code_file.read(), "python") console.print(syntax) You may also use the :meth:`~rich.syntax.Syntax.from_path` alternative constructor which will load the code from disk and auto-detect the file type. The example above could be re-written as follows:: diff --git a/docs/source/tables.rst b/docs/source/tables.rst index 9048334ca9..2603e7912a 100644 --- a/docs/source/tables.rst +++ b/docs/source/tables.rst @@ -70,7 +70,7 @@ You may also add columns by specifying them in the positional arguments of the : table = Table("Released", "Title", "Box Office", title="Star Wars Movies") -This allows you to specify the text of the column only. If you want to set other attributes, such as width and style, you can add an :class:`~rich.table.Column` class. Here's an example:: +This allows you to specify the text of the column only. If you want to set other attributes, such as width and style, you can add a :class:`~rich.table.Column` class. Here's an example:: from rich.table import Column table = Table( diff --git a/docs/source/text.rst b/docs/source/text.rst index 9d8644f2ce..fd6851fb4f 100644 --- a/docs/source/text.rst +++ b/docs/source/text.rst @@ -5,7 +5,7 @@ Rich Text Rich has a :class:`~rich.text.Text` class you can use to mark up strings with color and style attributes. You can use a Text instance anywhere a string is accepted, which gives you a lot of control over presentation. -You can consider this class to be like a string with marked up regions of text. Unlike a builtin ``str``, a Text instance is mutable, and most methods operate in-place rather than returning a new instance. +You can consider this class to be like a string with marked up regions of text. Unlike a built-in ``str``, a Text instance is mutable, and most methods operate in-place rather than returning a new instance. One way to add a style to Text is the :meth:`~rich.text.Text.stylize` method which applies a style to a start and end offset. Here is an example:: diff --git a/docs/source/traceback.rst b/docs/source/traceback.rst index 120ca0ceb4..f940bbbeae 100644 --- a/docs/source/traceback.rst +++ b/docs/source/traceback.rst @@ -18,7 +18,7 @@ The :meth:`~rich.console.Console.print_exception` method will print a traceback try: do_something() - except Exception: + except Exception: console.print_exception(show_locals=True) The ``show_locals=True`` parameter causes Rich to display the value of local variables for each frame of the traceback. @@ -76,7 +76,7 @@ Max Frames A recursion error can generate very large tracebacks that take a while to render and contain a lot of repetitive frames. Rich guards against this with a `max_frames` argument, which defaults to 100. If a traceback contains more than 100 frames then only the first 50, and last 50 will be shown. You can disable this feature by setting `max_frames` to 0. -Here's an example of printing an recursive error:: +Here's an example of printing a recursive error:: from rich.console import Console From f12cea1aafe3197fc84f58867d4536fe3c606c7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 13:04:53 +0000 Subject: [PATCH 177/287] Bump pygments from 2.10.0 to 2.11.1 Bumps [pygments](https://github.com/pygments/pygments) from 2.10.0 to 2.11.1. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.10.0...2.11.1) --- updated-dependencies: - dependency-name: pygments dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index c26946367b..d0391f5c70 100644 --- a/poetry.lock +++ b/poetry.lock @@ -687,7 +687,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.10.0" +version = "2.11.1" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false @@ -1358,8 +1358,8 @@ pycparser = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pygments = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, + {file = "Pygments-2.11.1-py3-none-any.whl", hash = "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c"}, + {file = "Pygments-2.11.1.tar.gz", hash = "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4"}, ] pyparsing = [ {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, From ef943a95a21cd80f737f18d6bf731fe07033be9c Mon Sep 17 00:00:00 2001 From: Nathan Page Date: Mon, 3 Jan 2022 11:25:57 -0500 Subject: [PATCH 178/287] remove default_styles table from appendix --- docs/source/appendix.rst | 2 - docs/source/appendix/default_styles.rst | 162 ------------------------ docs/source/style.rst | 3 +- 3 files changed, 2 insertions(+), 165 deletions(-) delete mode 100644 docs/source/appendix/default_styles.rst diff --git a/docs/source/appendix.rst b/docs/source/appendix.rst index 166ce7d6c8..a381eb84fa 100644 --- a/docs/source/appendix.rst +++ b/docs/source/appendix.rst @@ -6,5 +6,3 @@ Appendix appendix/box.rst appendix/colors.rst - appendix/default_styles.rst - \ No newline at end of file diff --git a/docs/source/appendix/default_styles.rst b/docs/source/appendix/default_styles.rst deleted file mode 100644 index 3057cb9ef2..0000000000 --- a/docs/source/appendix/default_styles.rst +++ /dev/null @@ -1,162 +0,0 @@ -.. _appendix-styles: - -Default Styles -============== - -A list of all the available styles provided in the default Theme. - -You can also produce this table by running the following command:: - - python -m rich.default_styles - -.. raw:: html - -
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
-    ┃ Name                           Styling                            ┃
-    ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
-    │ none                          │ none                               │
-    │ reset                         │ not bold not dim not italic not    │
-    │                               │ underline not blink not blink2 not │
-    │                               │ reverse not conceal not strike     │
-    │                               │ default on default                 │
-    │ dim                           │ dim                                │
-    │ bright                        │ not dim                            │
-    │ bold                          │ bold                               │
-    │ strong                        │ bold                               │
-    │ code                          │ bold reverse                       │
-    │ italic                        │ italic                             │
-    │ emphasize                     │ italic                             │
-    │ underline                     │ underline                          │
-    │ blink                         │ blink                              │
-    │ blink2                        │ blink2                             │
-    │ reverse                       │ reverse                            │
-    │ strike                        │ strike                             │
-    │ black                         │ black                              │
-    │ red                           │ red                                │
-    │ green                         │ green                              │
-    │ yellow                        │ yellow                             │
-    │ magenta                       │ magenta                            │
-    │ cyan                          │ cyan                               │
-    │ white                         │ white                              │
-    │ inspect.attr                  │ italic yellow                      │
-    │ inspect.attr.dunder           │ dim italic yellow                  │
-    │ inspect.callable              │ bold red                           │
-    │ inspect.def                   │ italic bright_cyan                 │
-    │ inspect.error                 │ bold red                           │
-    │ inspect.equals                │ none                               │
-    │ inspect.help                  │ cyan                               │
-    │ inspect.doc                   │ dim                                │
-    │ inspect.value.border          │ green                              │
-    │ live.ellipsis                 │ bold red                           │
-    │ layout.tree.row               │ not dim red                        │
-    │ layout.tree.column            │ not dim blue                       │
-    │ logging.keyword               │ bold yellow                        │
-    │ logging.level.notset          │ dim                                │
-    │ logging.level.debug           │ green                              │
-    │ logging.level.info            │ blue                               │
-    │ logging.level.warning         │ red                                │
-    │ logging.level.error           │ bold red                           │
-    │ logging.level.critical        │ bold reverse red                   │
-    │ log.level                     │ none                               │
-    │ log.time                      │ dim cyan                           │
-    │ log.message                   │ none                               │
-    │ log.path                      │ dim                                │
-    │ repr.ellipsis                 │ yellow                             │
-    │ repr.indent                   │ dim green                          │
-    │ repr.error                    │ bold red                           │
-    │ repr.str                      │ not bold not italic green          │
-    │ repr.brace                    │ bold                               │
-    │ repr.comma                    │ bold                               │
-    │ repr.ipv4                     │ bold bright_green                  │
-    │ repr.ipv6                     │ bold bright_green                  │
-    │ repr.eui48                    │ bold bright_green                  │
-    │ repr.eui64                    │ bold bright_green                  │
-    │ repr.tag_start                │ bold                               │
-    │ repr.tag_name                 │ bold bright_magenta                │
-    │ repr.tag_contents             │ default                            │
-    │ repr.tag_end                  │ bold                               │
-    │ repr.attrib_name              │ not italic yellow                  │
-    │ repr.attrib_equal             │ bold                               │
-    │ repr.attrib_value             │ not italic magenta                 │
-    │ repr.number                   │ bold not italic cyan               │
-    │ repr.bool_true                │ italic bright_green                │
-    │ repr.bool_false               │ italic bright_red                  │
-    │ repr.none                     │ italic magenta                     │
-    │ repr.url                      │ not bold not italic underline      │
-    │                               │ bright_blue                        │
-    │ repr.uuid                     │ not bold bright_yellow             │
-    │ repr.call                     │ bold magenta                       │
-    │ repr.path                     │ magenta                            │
-    │ repr.filename                 │ bright_magenta                     │
-    │ rule.line                     │ bright_green                       │
-    │ rule.text                     │ none                               │
-    │ json.brace                    │ bold                               │
-    │ json.bool_true                │ italic bright_green                │
-    │ json.bool_false               │ italic bright_red                  │
-    │ json.null                     │ italic magenta                     │
-    │ json.number                   │ bold not italic cyan               │
-    │ json.str                      │ not bold not italic green          │
-    │ json.key                      │ bold blue                          │
-    │ prompt                        │ none                               │
-    │ prompt.choices                │ bold magenta                       │
-    │ prompt.default                │ bold cyan                          │
-    │ prompt.invalid                │ red                                │
-    │ prompt.invalid.choice         │ red                                │
-    │ pretty                        │ none                               │
-    │ scope.border                  │ blue                               │
-    │ scope.key                     │ italic yellow                      │
-    │ scope.key.special             │ dim italic yellow                  │
-    │ scope.equals                  │ red                                │
-    │ table.header                  │ bold                               │
-    │ table.footer                  │ bold                               │
-    │ table.cell                    │ none                               │
-    │ table.title                   │ italic                             │
-    │ table.caption                 │ dim italic                         │
-    │ traceback.error               │ italic red                         │
-    │ traceback.border.syntax_error │ bright_red                         │
-    │ traceback.border              │ red                                │
-    │ traceback.text                │ none                               │
-    │ traceback.title               │ bold red                           │
-    │ traceback.exc_type            │ bold bright_red                    │
-    │ traceback.exc_value           │ none                               │
-    │ traceback.offset              │ bold bright_red                    │
-    │ bar.back                      │ grey23                             │
-    │ bar.complete                  │ rgb(249,38,114)                    │
-    │ bar.finished                  │ rgb(114,156,31)                    │
-    │ bar.pulse                     │ rgb(249,38,114)                    │
-    │ progress.description          │ none                               │
-    │ progress.filesize             │ green                              │
-    │ progress.filesize.total       │ green                              │
-    │ progress.download             │ green                              │
-    │ progress.elapsed              │ yellow                             │
-    │ progress.percentage           │ magenta                            │
-    │ progress.remaining            │ cyan                               │
-    │ progress.data.speed           │ red                                │
-    │ progress.spinner              │ green                              │
-    │ status.spinner                │ green                              │
-    │ tree                          │ none                               │
-    │ tree.line                     │ none                               │
-    │ markdown.paragraph            │ none                               │
-    │ markdown.text                 │ none                               │
-    │ markdown.emph                 │ italic                             │
-    │ markdown.strong               │ bold                               │
-    │ markdown.code                 │ bright_white on black              │
-    │ markdown.code_block           │ dim cyan on black                  │
-    │ markdown.block_quote          │ magenta                            │
-    │ markdown.list                 │ cyan                               │
-    │ markdown.item                 │ none                               │
-    │ markdown.item.bullet          │ bold yellow                        │
-    │ markdown.item.number          │ bold yellow                        │
-    │ markdown.hr                   │ yellow                             │
-    │ markdown.h1.border            │ none                               │
-    │ markdown.h1                   │ bold                               │
-    │ markdown.h2                   │ bold underline                     │
-    │ markdown.h3                   │ bold                               │
-    │ markdown.h4                   │ bold dim                           │
-    │ markdown.h5                   │ underline                          │
-    │ markdown.h6                   │ italic                             │
-    │ markdown.h7                   │ dim italic                         │
-    │ markdown.link                 │ bright_blue                        │
-    │ markdown.link_url             │ blue                               │
-    └───────────────────────────────┴────────────────────────────────────┘
-    
diff --git a/docs/source/style.rst b/docs/source/style.rst index e248be5d53..4b96117aea 100644 --- a/docs/source/style.rst +++ b/docs/source/style.rst @@ -141,9 +141,10 @@ The Theme class will inherit the default styles builtin to Rich. If your custom You can disable inheriting the default theme by setting ``inherit=False`` on the :class:`rich.theme.Theme` constructor. -To see the default theme refer to :ref:`appendix-styles` or run the following command:: +To see the default theme run the following commands:: python -m rich.theme + python -m rich.default_styles Loading Themes From 854638f54e9ba17d9f2e6a9dc6e0a1af0509d29d Mon Sep 17 00:00:00 2001 From: Nathan Page Date: Mon, 3 Jan 2022 11:30:48 -0500 Subject: [PATCH 179/287] clean up diffs --- docs/source/appendix.rst | 1 + docs/source/style.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/appendix.rst b/docs/source/appendix.rst index a381eb84fa..3ae7fa68b4 100644 --- a/docs/source/appendix.rst +++ b/docs/source/appendix.rst @@ -6,3 +6,4 @@ Appendix appendix/box.rst appendix/colors.rst + \ No newline at end of file diff --git a/docs/source/style.rst b/docs/source/style.rst index 4b96117aea..53ff7c51ff 100644 --- a/docs/source/style.rst +++ b/docs/source/style.rst @@ -141,7 +141,7 @@ The Theme class will inherit the default styles builtin to Rich. If your custom You can disable inheriting the default theme by setting ``inherit=False`` on the :class:`rich.theme.Theme` constructor. -To see the default theme run the following commands:: +To see the default theme, run the following commands:: python -m rich.theme python -m rich.default_styles From 9b71f5b72374bbb0f9900c73be8858fa8d69d2c5 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 5 Jan 2022 11:43:55 +0000 Subject: [PATCH 180/287] Remove links to sponsorship --- .github/workflows/comment.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/comment.yml b/.github/workflows/comment.yml index 5c2bd86b79..964169b5b3 100644 --- a/.github/workflows/comment.yml +++ b/.github/workflows/comment.yml @@ -15,11 +15,4 @@ jobs: body: | Did I solve your problem? - Consider [sponsoring](https://github.com/sponsors/willmcgugan) the ongoing work on Rich and Textual. - - Or buy me a [coffee](https://ko-fi.com/willmcgugan) to say thanks. - - – [Will McGugan](https://twitter.com/willmcgugan) - - - + Why not buy the devs a [coffee](https://ko-fi.com/willmcgugan) to say thanks? From 3ac7b5cf86dfe96f5860915a380b355416e0db8b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 5 Jan 2022 11:47:08 +0000 Subject: [PATCH 181/287] Update comment.yml --- .github/workflows/comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/comment.yml b/.github/workflows/comment.yml index 964169b5b3..8da8617c52 100644 --- a/.github/workflows/comment.yml +++ b/.github/workflows/comment.yml @@ -15,4 +15,4 @@ jobs: body: | Did I solve your problem? - Why not buy the devs a [coffee](https://ko-fi.com/willmcgugan) to say thanks? + Why not buy the devs a [coffee](https://ko-fi.com/textualize) to say thanks? From 13589da335545f8af5a4ffb328a352349b1f27ee Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 5 Jan 2022 14:40:36 +0000 Subject: [PATCH 182/287] for environment to empty in tests --- Makefile | 2 +- tests/test_console.py | 2 +- tests/test_layout.py | 2 +- tests/test_spinner.py | 2 +- tests/test_tree.py | 8 ++++++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 56977d2c8c..17ede92638 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ test: - pytest --cov-report term-missing --cov=rich tests/ -vv + TERM=unknown pytest --cov-report term-missing --cov=rich tests/ -vv format-check: black --check . format: diff --git a/tests/test_console.py b/tests/test_console.py index 4b21e397e9..0989d8ba16 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -686,7 +686,7 @@ def test_is_alt_screen(): def test_update_screen(): - console = Console(force_terminal=True, width=20, height=5) + console = Console(force_terminal=True, width=20, height=5, _environ={}) if console.legacy_windows: return with pytest.raises(errors.NoAltScreen): diff --git a/tests/test_layout.py b/tests/test_layout.py index 21d30d27f6..61cc9b6b5d 100644 --- a/tests/test_layout.py +++ b/tests/test_layout.py @@ -86,7 +86,7 @@ def test_tree(): def test_refresh_screen(): layout = Layout() layout.split_row(Layout(name="foo"), Layout(name="bar")) - console = Console(force_terminal=True, width=20, height=5) + console = Console(force_terminal=True, width=20, height=5, _environ={}) with console.capture(): console.print(layout) with console.screen(): diff --git a/tests/test_spinner.py b/tests/test_spinner.py index 5560f1daf6..98e3d9d66a 100644 --- a/tests/test_spinner.py +++ b/tests/test_spinner.py @@ -41,7 +41,7 @@ def get_time(): nonlocal time return time - console = Console(width=20, force_terminal=True, get_time=get_time) + console = Console(width=20, force_terminal=True, get_time=get_time, _environ={}) console.begin_capture() spinner = Spinner("dots") console.print(spinner) diff --git a/tests/test_tree.py b/tests/test_tree.py index 8fc070d3f3..f5510aa536 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -67,7 +67,9 @@ def test_render_tree_non_win32(): baz_tree.add("2") tree.add("egg") - console = Console(width=20, force_terminal=True, color_system="standard") + console = Console( + width=20, force_terminal=True, color_system="standard", _environ={} + ) console.begin_capture() console.print(tree) result = console.end_capture() @@ -103,7 +105,9 @@ def test_render_tree_hide_root_non_win32(): baz_tree.add("2") tree.add("egg") - console = Console(width=20, force_terminal=True, color_system="standard") + console = Console( + width=20, force_terminal=True, color_system="standard", _environ={} + ) console.begin_capture() console.print(tree) result = console.end_capture() From 39edbf69adeaf1c0231ea664cf4886f887602afa Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 09:56:15 +0000 Subject: [PATCH 183/287] Check for _repr_*_ methods notebooks can display For all of the mimetypes that Jupyter notebook can display, we check if the method exists and ensure it doesn't return None. If this is the case, we delegate rendering to the notebook. Otherwise, Rich will be used to render. https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display --- rich/pretty.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index f705911210..db22911b90 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -1,4 +1,5 @@ import builtins +import inspect import os from rich.repr import RichReprResult import sys @@ -137,10 +138,32 @@ def ipy_display_hook(value: Any) -> None: # pragma: no cover if isinstance(value, JupyterRenderable) or value is None: return # on jupyter rich display, if using one of the special representations don't use rich - if console.is_jupyter and any( - _re_jupyter_repr.match(attr) for attr in dir(value) - ): - return + + if console.is_jupyter: + # Delegate rendering to IPython if the object (and IPython) supports it + # https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display + ipython_repr_methods = [ + "_repr_html_", + "_repr_markdown_", + "_repr_json_", + "_repr_latex_", + "_repr_jpeg_", + "_repr_png_", + "_repr_svg_", + "_repr_mimebundle_", + ] + for repr_method in ipython_repr_methods: + method = getattr(value, repr_method, None) + if inspect.ismethod(method): + # Calling this isn't ideal. The interface for the `_repr_*_` methods + # specifies that if they return None, then they should not be rendered + # by the notebook. + try: + repr_result = method() + except Exception: + continue # If the method fails, treat it as if it doesn't exist + if repr_result is not None: + return # Delegate rendering to IPython # certain renderables should start on a new line if isinstance(value, ConsoleRenderable): From f48339e7b55f680ce1137c6ac43e4ec53360e3a0 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 10:05:39 +0000 Subject: [PATCH 184/287] Fix formatting --- rich/_windows.py | 1 + rich/pretty.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rich/_windows.py b/rich/_windows.py index 5169d83556..bac88e639b 100644 --- a/rich/_windows.py +++ b/rich/_windows.py @@ -30,6 +30,7 @@ def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() return features + else: STDOUT = -11 diff --git a/rich/pretty.py b/rich/pretty.py index db22911b90..4231b314c2 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -141,7 +141,7 @@ def ipy_display_hook(value: Any) -> None: # pragma: no cover if console.is_jupyter: # Delegate rendering to IPython if the object (and IPython) supports it - # https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display + # https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display ipython_repr_methods = [ "_repr_html_", "_repr_markdown_", @@ -155,13 +155,13 @@ def ipy_display_hook(value: Any) -> None: # pragma: no cover for repr_method in ipython_repr_methods: method = getattr(value, repr_method, None) if inspect.ismethod(method): - # Calling this isn't ideal. The interface for the `_repr_*_` methods + # Calling the method ourselves isn't ideal. The interface for the `_repr_*_` methods # specifies that if they return None, then they should not be rendered # by the notebook. try: repr_result = method() except Exception: - continue # If the method fails, treat it as if it doesn't exist + continue # If the method raises, treat it as if it doesn't exist, try any others if repr_result is not None: return # Delegate rendering to IPython From 35795dc9e95a5d416065289504e03aea24852330 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 10:08:40 +0000 Subject: [PATCH 185/287] Add darrenburns to CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5aaf877653..c29cd79049 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -5,6 +5,7 @@ The following people have contributed to the development of Rich: - [Gregory Beauregard](https://github.com/GBeauregard/pyffstream) +- [Darren Burns](https://github.com/darrenburns) - [Pete Davison](https://github.com/pd93) - [James Estevez](https://github.com/jstvz) - [Oleksis Fraga](https://github.com/oleksis) From 01f95d7e810d0f99cb2406cfdecac841db5ce36b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 10:33:18 +0000 Subject: [PATCH 186/287] max depth arg --- rich/pretty.py | 187 +++++++++++++++++++++++++------------------ tests/test_pretty.py | 69 ++++++++++++++++ 2 files changed, 179 insertions(+), 77 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index f705911210..80c4df98eb 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -196,6 +196,7 @@ class Pretty(JupyterMixin): max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to None. max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None. + max_depth (int, optional): Maximum depth of nested data structures, or None for no maximum. Defaults to None. expand_all (bool, optional): Expand all containers. Defaults to False. margin (int, optional): Subtrace a margin from width to force containers to expand earlier. Defaults to 0. insert_line (bool, optional): Insert a new line if the output has multiple new lines. Defaults to False. @@ -213,6 +214,7 @@ def __init__( indent_guides: bool = False, max_length: Optional[int] = None, max_string: Optional[int] = None, + max_depth: Optional[int] = None, expand_all: bool = False, margin: int = 0, insert_line: bool = False, @@ -226,6 +228,7 @@ def __init__( self.indent_guides = indent_guides self.max_length = max_length self.max_string = max_string + self.max_depth = max_depth self.expand_all = expand_all self.margin = margin self.insert_line = insert_line @@ -239,6 +242,7 @@ def __rich_console__( indent_size=self.indent_size, max_length=self.max_length, max_string=self.max_string, + max_depth=self.max_depth, expand_all=self.expand_all, ) pretty_text = Text( @@ -474,7 +478,10 @@ def __str__(self) -> str: def traverse( - _object: Any, max_length: Optional[int] = None, max_string: Optional[int] = None + _object: Any, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, ) -> Node: """Traverse object and generate a tree. @@ -484,6 +491,8 @@ def traverse( Defaults to None. max_string (int, optional): Maximum length of string before truncating, or None to disable truncating. Defaults to None. + max_depth (int, optional): Maximum depth of data structures, or None for no maximum. + Defaults to None. Returns: Node: The root of a tree structure which can be used to render a pretty repr. @@ -509,11 +518,13 @@ def to_repr(obj: Any) -> str: push_visited = visited_ids.add pop_visited = visited_ids.remove - def _traverse(obj: Any, root: bool = False) -> Node: + def _traverse(obj: Any, root: bool = False, depth: int = 0) -> Node: """Walk the object depth first.""" + obj_type = type(obj) py_version = (sys.version_info.major, sys.version_info.minor) children: List[Node] + reached_max_depth = max_depth is not None and depth >= max_depth def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: for arg in rich_args: @@ -554,33 +565,37 @@ def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: if args: children = [] append = children.append - if angular: - node = Node( - open_brace=f"<{class_name} ", - close_brace=">", - children=children, - last=root, - separator=" ", - ) + + if reached_max_depth: + node = Node(value_repr=f"...") else: - node = Node( - open_brace=f"{class_name}(", - close_brace=")", - children=children, - last=root, - ) - for last, arg in loop_last(args): - if isinstance(arg, tuple): - key, child = arg - child_node = _traverse(child) - child_node.last = last - child_node.key_repr = key - child_node.key_separator = "=" - append(child_node) + if angular: + node = Node( + open_brace=f"<{class_name} ", + close_brace=">", + children=children, + last=root, + separator=" ", + ) else: - child_node = _traverse(arg) - child_node.last = last - append(child_node) + node = Node( + open_brace=f"{class_name}(", + close_brace=")", + children=children, + last=root, + ) + for last, arg in loop_last(args): + if isinstance(arg, tuple): + key, child = arg + child_node = _traverse(child, depth=depth + 1) + child_node.last = last + child_node.key_repr = key + child_node.key_separator = "=" + append(child_node) + else: + child_node = _traverse(arg, depth=depth + 1) + child_node.last = last + append(child_node) else: node = Node( value_repr=f"<{class_name}>" if angular else f"{class_name}()", @@ -593,40 +608,43 @@ def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: attr_fields = _get_attr_fields(obj) if attr_fields: - node = Node( - open_brace=f"{obj.__class__.__name__}(", - close_brace=")", - children=children, - last=root, - ) + if reached_max_depth: + node = Node(value_repr=f"...") + else: + node = Node( + open_brace=f"{obj.__class__.__name__}(", + close_brace=")", + children=children, + last=root, + ) - def iter_attrs() -> Iterable[ - Tuple[str, Any, Optional[Callable[[Any], str]]] - ]: - """Iterate over attr fields and values.""" - for attr in attr_fields: - if attr.repr: - try: - value = getattr(obj, attr.name) - except Exception as error: - # Can happen, albeit rarely - yield (attr.name, error, None) - else: - yield ( - attr.name, - value, - attr.repr if callable(attr.repr) else None, - ) - - for last, (name, value, repr_callable) in loop_last(iter_attrs()): - if repr_callable: - child_node = Node(value_repr=str(repr_callable(value))) - else: - child_node = _traverse(value) - child_node.last = last - child_node.key_repr = name - child_node.key_separator = "=" - append(child_node) + def iter_attrs() -> Iterable[ + Tuple[str, Any, Optional[Callable[[Any], str]]] + ]: + """Iterate over attr fields and values.""" + for attr in attr_fields: + if attr.repr: + try: + value = getattr(obj, attr.name) + except Exception as error: + # Can happen, albeit rarely + yield (attr.name, error, None) + else: + yield ( + attr.name, + value, + attr.repr if callable(attr.repr) else None, + ) + + for last, (name, value, repr_callable) in loop_last(iter_attrs()): + if repr_callable: + child_node = Node(value_repr=str(repr_callable(value))) + else: + child_node = _traverse(value, depth=depth + 1) + child_node.last = last + child_node.key_repr = name + child_node.key_separator = "=" + append(child_node) else: node = Node( value_repr=f"{obj.__class__.__name__}()", children=[], last=root @@ -646,21 +664,26 @@ def iter_attrs() -> Iterable[ children = [] append = children.append - node = Node( - open_brace=f"{obj.__class__.__name__}(", - close_brace=")", - children=children, - last=root, - ) + if reached_max_depth: + node = Node(value_repr=f"...") + else: + node = Node( + open_brace=f"{obj.__class__.__name__}(", + close_brace=")", + children=children, + last=root, + ) - for last, field in loop_last(field for field in fields(obj) if field.repr): - child_node = _traverse(getattr(obj, field.name)) - child_node.key_repr = field.name - child_node.last = last - child_node.key_separator = "=" - append(child_node) + for last, field in loop_last( + field for field in fields(obj) if field.repr + ): + child_node = _traverse(getattr(obj, field.name), depth=depth + 1) + child_node.key_repr = field.name + child_node.last = last + child_node.key_separator = "=" + append(child_node) - pop_visited(obj_id) + pop_visited(obj_id) elif isinstance(obj, _CONTAINERS): for container_type in _CONTAINERS: @@ -676,7 +699,9 @@ def iter_attrs() -> Iterable[ open_brace, close_brace, empty = _BRACES[obj_type](obj) - if obj_type.__repr__ != type(obj).__repr__: + if reached_max_depth: + node = Node(value_repr=f"...", last=root) + elif obj_type.__repr__ != type(obj).__repr__: node = Node(value_repr=to_repr(obj), last=root) elif obj: children = [] @@ -695,7 +720,7 @@ def iter_attrs() -> Iterable[ if max_length is not None: iter_items = islice(iter_items, max_length) for index, (key, child) in enumerate(iter_items): - child_node = _traverse(child) + child_node = _traverse(child, depth=depth + 1) child_node.key_repr = to_repr(key) child_node.last = index == last_item_index append(child_node) @@ -704,7 +729,7 @@ def iter_attrs() -> Iterable[ if max_length is not None: iter_values = islice(iter_values, max_length) for index, child in enumerate(iter_values): - child_node = _traverse(child) + child_node = _traverse(child, depth=depth + 1) child_node.last = index == last_item_index append(child_node) if max_length is not None and num_items > max_length: @@ -729,6 +754,7 @@ def pretty_repr( indent_size: int = 4, max_length: Optional[int] = None, max_string: Optional[int] = None, + max_depth: Optional[int] = None, expand_all: bool = False, ) -> str: """Prettify repr string by expanding on to new lines to fit within a given width. @@ -741,6 +767,8 @@ def pretty_repr( Defaults to None. max_string (int, optional): Maximum length of string before truncating, or None to disable truncating. Defaults to None. + max_depth (int, optional): Maximum depth of nested data structure, or None for no depth. + Defaults to None. expand_all (bool, optional): Expand all containers regardless of available width. Defaults to False. Returns: @@ -750,7 +778,9 @@ def pretty_repr( if isinstance(_object, Node): node = _object else: - node = traverse(_object, max_length=max_length, max_string=max_string) + node = traverse( + _object, max_length=max_length, max_string=max_string, max_depth=max_depth + ) repr_str = node.render( max_width=max_width, indent_size=indent_size, expand_all=expand_all ) @@ -764,6 +794,7 @@ def pprint( indent_guides: bool = True, max_length: Optional[int] = None, max_string: Optional[int] = None, + max_depth: Optional[int] = None, expand_all: bool = False, ) -> None: """A convenience function for pretty printing. @@ -774,6 +805,7 @@ def pprint( max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to None. max_string (int, optional): Maximum length of strings before truncating, or None to disable. Defaults to None. + max_depth (int, optional): Maximum depth for nested data structures, or None for no maximum. Defaults to None. indent_guides (bool, optional): Enable indentation guides. Defaults to True. expand_all (bool, optional): Expand all containers. Defaults to False. """ @@ -783,6 +815,7 @@ def pprint( _object, max_length=max_length, max_string=max_string, + max_depth=max_depth, indent_guides=indent_guides, expand_all=expand_all, overflow="ignore", diff --git a/tests/test_pretty.py b/tests/test_pretty.py index ab83d930d1..1752d1e6d1 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -131,6 +131,75 @@ def test_recursive(): assert result == expected +def test_max_depth(): + d = d = {} + d["foo"] = {"fob": {"a": [1, 2, 3], "b": {"z": "x", "y": ["a", "b", "c"]}}} + + assert pretty_repr(d, max_depth=0) == "..." + assert pretty_repr(d, max_depth=1) == "{'foo': ...}" + assert pretty_repr(d, max_depth=2) == "{'foo': {'fob': ...}}" + assert pretty_repr(d, max_depth=3) == "{'foo': {'fob': {'a': ..., 'b': ...}}}" + assert ( + pretty_repr(d, max_width=100, max_depth=4) + == "{'foo': {'fob': {'a': [1, 2, 3], 'b': {'z': 'x', 'y': ...}}}}" + ) + assert ( + pretty_repr(d, max_width=100, max_depth=5) + == "{'foo': {'fob': {'a': [1, 2, 3], 'b': {'z': 'x', 'y': ['a', 'b', 'c']}}}}" + ) + + +def test_max_depth_rich_repr(): + class Foo: + def __init__(self, foo): + self.foo = foo + + def __rich_repr__(self): + yield "foo", self.foo + + class Bar: + def __init__(self, bar): + self.bar = bar + + def __rich_repr__(self): + yield "bar", self.bar + + assert ( + pretty_repr(Foo(foo=Bar(bar=Foo(foo=[]))), max_depth=2) + == "Foo(foo=Bar(bar=...))" + ) + + +def test_max_depth_attrs(): + @attr.define + class Foo: + foo = attr.field() + + @attr.define + class Bar: + bar = attr.field() + + assert ( + pretty_repr(Foo(foo=Bar(bar=Foo(foo=[]))), max_depth=2) + == "Foo(foo=Bar(bar=...))" + ) + + +def test_max_depth_dataclass(): + @dataclass + class Foo: + foo: object + + @dataclass + class Bar: + bar: object + + assert ( + pretty_repr(Foo(foo=Bar(bar=Foo(foo=[]))), max_depth=2) + == "Foo(foo=Bar(bar=...))" + ) + + def test_defaultdict(): test_dict = defaultdict(int, {"foo": 2}) result = pretty_repr(test_dict) From 3999c8a8e696eb853ba00b1b49c4fa049170ad33 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 10:45:33 +0000 Subject: [PATCH 187/287] changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db2fb521b0..a5f50c903d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## [11.0.0] - Unreleased + +### Added + +- Added max_depth arg to pretty printing + ## [10.16.2] - 2021-01-02 ### Fixed From 3ac1b578cdc488d957166d618d34367a37fceb36 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 10:47:36 +0000 Subject: [PATCH 188/287] Running `make format` with correct Black version --- rich/_windows.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rich/_windows.py b/rich/_windows.py index bac88e639b..5169d83556 100644 --- a/rich/_windows.py +++ b/rich/_windows.py @@ -30,7 +30,6 @@ def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() return features - else: STDOUT = -11 From 2cf35b18a8716c963c0f9252544a3a8b9881cd6c Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 11:07:23 +0000 Subject: [PATCH 189/287] Try using default theme in test to avoid ubuntu/macos variance --- tests/test_syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index de739c8d8f..31f2389164 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -131,7 +131,7 @@ def test_python_render_indent_guides(): lexer="python", line_numbers=True, line_range=(2, 10), - theme="foo", + theme="default", code_width=60, word_wrap=True, indent_guides=True, From 5f311dc2d7d8f1a1b79e97d360f5ca69d5544c2f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 11:10:38 +0000 Subject: [PATCH 190/287] Try using monokai theme to avoid ubuntu/macos variance --- tests/test_syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 31f2389164..d6a0b4e8c4 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -131,7 +131,7 @@ def test_python_render_indent_guides(): lexer="python", line_numbers=True, line_range=(2, 10), - theme="default", + theme="monokai", code_width=60, word_wrap=True, indent_guides=True, From 23bc0a2d7c5828fa641cefa9cceabe4914134573 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 11:18:50 +0000 Subject: [PATCH 191/287] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db2fb521b0..e5d3610475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ 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.16.2] - 2021-01-02 +## [11.0.0] - 2022-01-06 + +### Fixed + +- Fixed issue with pretty repr in jupyter notebook https://github.com/Textualize/rich/issues/1717 + +## [10.16.2] - 2022-01-02 ### Fixed @@ -1585,6 +1591,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[11.0.0]: https://github.com/willmcgugan/rich/compare/v10.16.1...v11.0.0 [10.16.1]: https://github.com/willmcgugan/rich/compare/v10.16.0...v10.16.1 [10.16.0]: https://github.com/willmcgugan/rich/compare/v10.15.2...v10.16.0 [10.15.2]: https://github.com/willmcgugan/rich/compare/v10.15.1...v10.15.2 From 47e6da19d5368b5d748cd8ce57631b4d5b55bed3 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 11:54:17 +0000 Subject: [PATCH 192/287] Use hardcoded monokai Pygments theme in syntax tests --- tests/test_syntax.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index d6a0b4e8c4..834285ac17 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -49,7 +49,7 @@ def test_python_render(): lexer="python", line_numbers=True, line_range=(2, 10), - theme="foo", + theme="monokai", code_width=60, word_wrap=True, ), @@ -57,7 +57,7 @@ def test_python_render(): ) rendered_syntax = render(syntax) print(repr(rendered_syntax)) - expected = '╭────────────────────────────────────────────────────────────────╮\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 2 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first \x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248mand last value."""\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 3 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 4 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 5 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 6 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 7 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 8 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 9 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m10 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n╰────────────────────────────────────────────────────────────────╯\n' + expected = '╭────────────────────────────────────────────────────────────────╮\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m"""Iterate and generate a tuple with a flag for first \x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[48;2;39;40;34m \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34mand last value."""\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n╰────────────────────────────────────────────────────────────────╯\n' assert rendered_syntax == expected @@ -66,13 +66,13 @@ def test_python_render_simple(): CODE, lexer="python", line_numbers=False, - theme="foo", + theme="monokai", code_width=60, word_wrap=False, ) rendered_syntax = render(syntax) print(repr(rendered_syntax)) - expected = '\x1b[1;38;2;0;128;0;48;2;248;248;248mdef\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;255;48;2;248;248;248mloop_first_last\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mT\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m]\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m-\x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m>\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mTuple\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mb\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n' + expected = '\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mloop_first_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mTuple\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mb\x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n' assert rendered_syntax == expected @@ -81,13 +81,13 @@ def test_python_render_simple_passing_lexer_instance(): CODE, lexer=PythonLexer(), line_numbers=False, - theme="foo", + theme="monokai", code_width=60, word_wrap=False, ) rendered_syntax = render(syntax) print(repr(rendered_syntax)) - expected = '\x1b[1;38;2;0;128;0;48;2;248;248;248mdef\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;255;48;2;248;248;248mloop_first_last\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mT\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m]\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m-\x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m>\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mTuple\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mb\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n' + expected = '\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mloop_first_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mTuple\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mb\x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m\n' assert rendered_syntax == expected @@ -140,7 +140,7 @@ def test_python_render_indent_guides(): ) rendered_syntax = render(syntax) print(repr(rendered_syntax)) - expected = '╭────────────────────────────────────────────────────────────────╮\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 2 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first \x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248mand last value."""\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 3 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 4 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 5 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ │ \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 6 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 7 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ │ \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 8 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 9 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m10 \x1b[0m\x1b[2;3;38;2;64;128;128;48;2;248;248;248m│ │ \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n╰────────────────────────────────────────────────────────────────╯\n' + expected = '╭────────────────────────────────────────────────────────────────╮\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m"""Iterate and generate a tuple with a flag for first \x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[48;2;39;40;34m \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34mand last value."""\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n│\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mfirst\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m│\n╰────────────────────────────────────────────────────────────────╯\n' assert rendered_syntax == expected From 703d40168fa3aff249440a4108365a4b98eb45a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jan 2022 13:30:10 +0000 Subject: [PATCH 193/287] Bump pygments from 2.11.1 to 2.11.2 Bumps [pygments](https://github.com/pygments/pygments) from 2.11.1 to 2.11.2. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.11.1...2.11.2) --- updated-dependencies: - dependency-name: pygments dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index d0391f5c70..b07b4e4766 100644 --- a/poetry.lock +++ b/poetry.lock @@ -687,7 +687,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.11.1" +version = "2.11.2" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false @@ -1358,8 +1358,8 @@ pycparser = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pygments = [ - {file = "Pygments-2.11.1-py3-none-any.whl", hash = "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c"}, - {file = "Pygments-2.11.1.tar.gz", hash = "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4"}, + {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, + {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, ] pyparsing = [ {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, From a3fcdbe21099bef37a8840ea63928ceaf3ea9533 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 14:17:34 +0000 Subject: [PATCH 194/287] Extract ipy display hook and add tests around it --- rich/pretty.py | 134 ++++++++++++++++++++++++------------------- tests/test_pretty.py | 90 +++++++++++++++++++++++++++-- 2 files changed, 159 insertions(+), 65 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index 4231b314c2..a866f1843a 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import builtins import inspect import os @@ -52,9 +54,6 @@ RenderResult, ) -# Matches Jupyter's special methods -_re_jupyter_repr = re.compile(f"^_repr_.+_$") - def _is_attr_object(obj: Any) -> bool: """Check if an object was created with attrs module.""" @@ -83,6 +82,70 @@ def _is_dataclass_repr(obj: object) -> bool: return False +def _ipy_display_hook( + value: Any, + console: Console | None = None, + overflow: "OverflowMethod" = "ignore", + crop: bool = False, + indent_guides: bool = False, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + expand_all: bool = False, +) -> None: + from .console import ConsoleRenderable # needed here to prevent circular import + + # always skip rich generated jupyter renderables or None values + if isinstance(value, JupyterRenderable) or value is None: + return + + console = console or get_console() + if console.is_jupyter: + # Delegate rendering to IPython if the object (and IPython) supports it + # https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display + ipython_repr_methods = [ + "_repr_html_", + "_repr_markdown_", + "_repr_json_", + "_repr_latex_", + "_repr_jpeg_", + "_repr_png_", + "_repr_svg_", + "_repr_mimebundle_", + ] + for repr_method in ipython_repr_methods: + method = getattr(value, repr_method, None) + if inspect.ismethod(method): + # Calling the method ourselves isn't ideal. The interface for the `_repr_*_` methods + # specifies that if they return None, then they should not be rendered + # by the notebook. + try: + repr_result = method() + except Exception: + continue # If the method raises, treat it as if it doesn't exist, try any others + if repr_result is not None: + return # Delegate rendering to IPython + + # certain renderables should start on a new line + if isinstance(value, ConsoleRenderable): + console.line() + + console.print( + value + if isinstance(value, RichRenderable) + else Pretty( + value, + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + expand_all=expand_all, + margin=12, + ), + crop=crop, + new_line_start=True, + ) + + def install( console: Optional["Console"] = None, overflow: "OverflowMethod" = "ignore", @@ -107,8 +170,6 @@ def install( """ from rich import get_console - from .console import ConsoleRenderable # needed here to prevent circular import - console = console or get_console() assert console is not None @@ -132,59 +193,6 @@ def display_hook(value: Any) -> None: ) builtins._ = value # type: ignore - def ipy_display_hook(value: Any) -> None: # pragma: no cover - assert console is not None - # always skip rich generated jupyter renderables or None values - if isinstance(value, JupyterRenderable) or value is None: - return - # on jupyter rich display, if using one of the special representations don't use rich - - if console.is_jupyter: - # Delegate rendering to IPython if the object (and IPython) supports it - # https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display - ipython_repr_methods = [ - "_repr_html_", - "_repr_markdown_", - "_repr_json_", - "_repr_latex_", - "_repr_jpeg_", - "_repr_png_", - "_repr_svg_", - "_repr_mimebundle_", - ] - for repr_method in ipython_repr_methods: - method = getattr(value, repr_method, None) - if inspect.ismethod(method): - # Calling the method ourselves isn't ideal. The interface for the `_repr_*_` methods - # specifies that if they return None, then they should not be rendered - # by the notebook. - try: - repr_result = method() - except Exception: - continue # If the method raises, treat it as if it doesn't exist, try any others - if repr_result is not None: - return # Delegate rendering to IPython - - # certain renderables should start on a new line - if isinstance(value, ConsoleRenderable): - console.line() - - console.print( - value - if isinstance(value, RichRenderable) - else Pretty( - value, - overflow=overflow, - indent_guides=indent_guides, - max_length=max_length, - max_string=max_string, - expand_all=expand_all, - margin=12, - ), - crop=crop, - new_line_start=True, - ) - try: # pragma: no cover ip = get_ipython() # type: ignore from IPython.core.formatters import BaseFormatter @@ -194,7 +202,15 @@ class RichFormatter(BaseFormatter): # type: ignore def __call__(self, value: Any) -> Any: if self.pprint: - return ipy_display_hook(value) + return _ipy_display_hook( + value, + console=get_console(), + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + expand_all=expand_all, + ) else: return repr(value) diff --git a/tests/test_pretty.py b/tests/test_pretty.py index ab83d930d1..954721f75f 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -1,16 +1,16 @@ -from array import array -from collections import defaultdict, UserDict, UserList -from dataclasses import dataclass, field import io import sys +from array import array +from collections import defaultdict, UserDict from typing import List import attr import pytest +from dataclasses import dataclass, field from rich.console import Console -from rich.pretty import install, Pretty, pprint, pretty_repr, Node - +from rich.pretty import install, Pretty, pprint, pretty_repr, Node, _ipy_display_hook +from rich.text import Text skip_py36 = pytest.mark.skipif( sys.version_info.minor == 6 and sys.version_info.major == 3, @@ -44,6 +44,85 @@ def test_install(): assert sys.displayhook is not dh +def test_ipy_display_hook__repr_html(): + console = Console(file=io.StringIO(), force_jupyter=True) + + class Thing: + def _repr_html_(self): + return "hello" + + console.begin_capture() + _ipy_display_hook(Thing(), console=console) + + # Rendering delegated to notebook because _repr_html_ method exists + assert console.end_capture() == "" + + +def test_ipy_display_hook__multiple_special_reprs(): + """ + The case where there are multiple IPython special _repr_*_ + methods on the object, and one of them returns None but another + one does not. + """ + console = Console(file=io.StringIO(), force_jupyter=True) + + class Thing: + def _repr_latex_(self): + return None + + def _repr_html_(self): + return "hello" + + console.begin_capture() + _ipy_display_hook(Thing(), console=console) + + assert console.end_capture() == "" + + +def test_ipy_display_hook__no_special_repr_methods(): + console = Console(file=io.StringIO(), force_jupyter=True) + + class Thing: + def __repr__(self) -> str: + return "hello" + + console.begin_capture() + _ipy_display_hook(Thing(), console=console) + + # No IPython special repr methods, so printed by Rich + assert console.end_capture() == "hello\n" + + +def test_ipy_display_hook__special_repr_raises_exception(): + """ + When an IPython special repr method raises an exception, + we treat it as if it doesn't exist and look for the next. + """ + console = Console(file=io.StringIO(), force_jupyter=True) + + class Thing: + def _repr_markdown_(self): + raise Exception() + + def _repr_latex_(self): + return None + + def _repr_html_(self): + return "hello" + + console.begin_capture() + _ipy_display_hook(Thing(), console=console) + + assert console.end_capture() == "" + + +def test_ipy_display_hook__console_renderables_on_newline(): + console = Console(file=io.StringIO(), force_jupyter=True) + console.begin_capture() + _ipy_display_hook(Text("hello"), console=console) + assert console.end_capture() == "\nhello\n" + + def test_pretty(): test = { "foo": [1, 2, 3, (4, 5, {6}, 7, 8, {9}), {}], @@ -55,7 +134,6 @@ def test_pretty(): result = pretty_repr(test, max_width=80) print(result) - # print(repr(result)) expected = "{\n 'foo': [1, 2, 3, (4, 5, {6}, 7, 8, {9}), {}],\n 'bar': {\n 'egg': 'baz',\n 'words': [\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World',\n 'Hello World'\n ]\n },\n False: 'foo',\n True: '',\n 'text': ('Hello World', 'foo bar baz egg')\n}" print(expected) assert result == expected From 9d0ca53f0a777391489710d922555d6c4e269a06 Mon Sep 17 00:00:00 2001 From: G_cat Date: Thu, 6 Jan 2022 17:27:37 +0300 Subject: [PATCH 195/287] Added russian README --- README.cn.md | 1 + README.de-ch.md | 1 + README.de.md | 1 + README.es.md | 1 + README.fr.md | 1 + README.hi.md | 1 + README.it.md | 1 + README.ja.md | 1 + README.kr.md | 1 + README.md | 1 + README.pt-br.md | 1 + README.ru.md | 457 ++++++++++++++++++++++++++++++++++++++++++++++++ README.sv.md | 1 + 13 files changed, 469 insertions(+) create mode 100644 README.ru.md diff --git a/README.cn.md b/README.cn.md index d9959d1db1..3fc571cd72 100644 --- a/README.cn.md +++ b/README.cn.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich 是一个 Python 库,可以为您在终端中提供富文本和精美格式。 diff --git a/README.de-ch.md b/README.de-ch.md index 2b7de59e96..e965753221 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich isch ä Python Library för _rich_ Text ond ganz schöni formatiärig im Törminäl diff --git a/README.de.md b/README.de.md index 56878a460f..38cf845d79 100644 --- a/README.de.md +++ b/README.de.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich ist eine Python-Bibliothek für _rich_ Text und schöne Formatierung im Terminal. diff --git a/README.es.md b/README.es.md index 2fd22f022c..a3aa631cab 100644 --- a/README.es.md +++ b/README.es.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich es un paquete de Python para texto _enriquecido_ y un hermoso formato en la terminal. diff --git a/README.fr.md b/README.fr.md index 5436d77068..394f03bf83 100644 --- a/README.fr.md +++ b/README.fr.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich est une bibliothèque Python pour le _rich_ texte et la mise en forme dans le terminal. diff --git a/README.hi.md b/README.hi.md index 4a35e8335d..9c3009f4fa 100644 --- a/README.hi.md +++ b/README.hi.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich टर्मिनल में _समृद्ध_ पाठ और सुंदर स्वरूपण के लिए एक Python संग्रह है। diff --git a/README.it.md b/README.it.md index cd7809aed6..7d0b68d714 100644 --- a/README.it.md +++ b/README.it.md @@ -17,6 +17,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich è una libreria Python per un testo _rich_ e con una piacevole formattazione nel terminale. diff --git a/README.ja.md b/README.ja.md index dcd74a9655..1bec484597 100644 --- a/README.ja.md +++ b/README.ja.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Richは、 _リッチ_ なテキストや美しい書式設定をターミナルで行うためのPythonライブラリです。 diff --git a/README.kr.md b/README.kr.md index c345b3c893..a1a67ea95d 100644 --- a/README.kr.md +++ b/README.kr.md @@ -18,6 +18,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich는 터미널에서 _풍부한(rich)_ 텍스트와 아름다운 서식을 지원하기 위한 파이썬 라이브러리입니다. diff --git a/README.md b/README.md index 42a7a570a0..f5365e7d0f 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich is a Python library for _rich_ text and beautiful formatting in the terminal. diff --git a/README.pt-br.md b/README.pt-br.md index fd2de06ec1..c2294502ea 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich é uma biblioteca Python para _rich_ text e formatação de estilos no terminal. diff --git a/README.ru.md b/README.ru.md new file mode 100644 index 0000000000..4223309d97 --- /dev/null +++ b/README.ru.md @@ -0,0 +1,457 @@ +[![Supported Python Versions](https://img.shields.io/pypi/pyversions/rich/10.11.0)](https://pypi.org/project/rich/) [![PyPI version](https://badge.fury.io/py/rich.svg)](https://badge.fury.io/py/rich) + +[![Downloads](https://pepy.tech/badge/rich/month)](https://pepy.tech/project/rich) +[![codecov](https://codecov.io/gh/willmcgugan/rich/branch/master/graph/badge.svg)](https://codecov.io/gh/willmcgugan/rich) +[![Rich blog](https://img.shields.io/badge/blog-rich%20news-yellowgreen)](https://www.willmcgugan.com/tag/rich/) +[![Twitter Follow](https://img.shields.io/twitter/follow/willmcgugan.svg?style=social)](https://twitter.com/willmcgugan) + +![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) + +[English readme](https://github.com/willmcgugan/rich/blob/master/README.md) + • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) + • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) + • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) + • [日本語 readme](https://github.com/willmcgugan/rich/blob/master/README.ja.md) + • [한국어 readme](https://github.com/willmcgugan/rich/blob/master/README.kr.md) + • [Français readme](https://github.com/willmcgugan/rich/blob/master/README.fr.md) + • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) + • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) + • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) + +Rich это Python библиотека позволяющая отображать _красивый_ текст и форматировать терминал. + +[Rich API](https://rich.readthedocs.io/en/latest/) упрощает добавление цветов и стилей к выводу терминала. Rich также позволяет отображать красивые таблицы, прогресс бары, markdown, код с отображением синтаксиса, ошибки, и т.д. — прямо после установки. + +![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) + +Для видео инструкции смотрите [calmcode.io](https://calmcode.io/rich/introduction.html) от [@fishnets88](https://twitter.com/fishnets88). + +Посмотрите [что люди думают о Rich](https://www.willmcgugan.com/blog/pages/post/rich-tweets/). + +## Cовместимость + +Rich работает с Linux, OSX, и Windows. True color / эмоджи работают с новым терминалом Windows, классический терминал лимитирован 16 цветами. Rich требует Python 3.6.1 или более новый. + +Rich работает с [Jupyter notebooks](https://jupyter.org/) без дополнительной конфигурации. + +## Установка + +Установите с `pip` или вашим любимым PyPI менеджером пакетов. + +```sh +python -m pip install rich +``` + +Запустите следующею команду чтобы проверить Rich вывод в вашем терминале: + +```sh +python -m rich +``` + +## Rich Print + +Простейший способ получить красивый вывод это импортировать метод [rich print](https://rich.readthedocs.io/en/latest/introduction.html#quick-start), он принимает такие же аргументы что и стандартный метод print. Попробуйте: + +```python +from rich import print + +print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals()) +``` + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/print.png) + +## Rich REPL + +Rich может быть установлен в Python REPL, так, все данные будут выведены через Rich. + +```python +>>> from rich import pretty +>>> pretty.install() +``` + +![REPL](https://github.com/willmcgugan/rich/raw/master/imgs/repl.png) + +## Использование класса Console + +Для большего контроля над терминалом Rich, импортируйте и инициализируйте класс [Console](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console). + +```python +from rich.console import Console + +console = Console() +``` + +У класса console есть метод `print` который имеет идентичный функционал к встроеной функции `print`. Вот пример использования: + +```python +console.print("Hello", "World!") +``` + +Как вы могли подумать, этот выведет `"Hello World!"` в терминал. Запомните что, в отличии от встроеной функции `print`, Rich увеличит ваш текст так, чтобы он распространялся на всю ширину терминала. + +Есть несколько способов добавить цвет и стиль к вашему выводу. Вы можете выбрать стиль для всего вывода добавив аргумент `style`. Вот пример: + +```python +console.print("Hello", "World!", style="bold red") +``` + +Вывод будет выглядить примерно так: + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/hello_world.png) + +Этого достаточно чтобы стилизовать 1 строку. Для более детального стилизования, Rich использует специальную разметку похожую по синтаксису на [bbcode](https://en.wikipedia.org/wiki/BBCode). Вот пример: + +```python +console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a [i]way[/i].") +``` + +![Console Markup](https://github.com/willmcgugan/rich/raw/master/imgs/where_there_is_a_will.png) + +Вы можете использовать класс Console чтобы генерировать утонченный вывод с минимальными усилиями. Смотрите [документацию Console API](https://rich.readthedocs.io/en/latest/console.html) для детального объяснения. + +## Rich Inspect + +В Rich есть функция [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) которая может украсить любой Python объект, например класс, переменная, или функция. + +```python +>>> my_list = ["foo", "bar"] +>>> from rich import inspect +>>> inspect(my_list, methods=True) +``` + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/inspect.png) + +Смотрите [документацию inspect](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) для детального объяснения. + +# Библиотека Rich + +Rich содержит несколько встроенных _визуализаций_ которые вы можете использовать чтобы сделать элегантный вывод в важем CLI или помочь в дебаггинге кода. + +Вот несколько вещей которые может делать Rich (нажмите чтобы узнать больше): + +
+Лог + +В классе console есть метод `log()` который похож на `print()`, но также изображает столбец для текущего времени, файла и линии кода которая вызвала метод. По умолчанию Rich будет подсвечивать синтаксис для структур Python и для строк repr. Если вы передадите в метод коллекцию (т.е. dict или list) Rich выведет её так, чтобы она помещалась в доступном месте. Вот пример использования этого метода. + +```python +from rich.console import Console +console = Console() + +test_data = [ + {"jsonrpc": "2.0", "method": "sum", "params": [None, 1, 2, 4, False, True], "id": "1",}, + {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}, + {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"}, +] + +def test_log(): + enabled = False + context = { + "foo": "bar", + } + movies = ["Deadpool", "Rise of the Skywalker"] + console.log("Hello from", console, "!") + console.log(test_data, log_locals=True) + + +test_log() +``` + +Код выше выведет это: + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/log.png) + +Запомните аргумент `log_locals`, он выводит таблицу имеющую локальные переменные функции в которой метод был вызван. + +Метод может быть использован для вывода данных в терминал в длинно-работающих программ, таких как сервера, но он также может помочь в дебаггинге. + +
+
+Обработчик Логов + +Вы также можете использовать встроенный [класс Handler](https://rich.readthedocs.io/en/latest/logging.html) чтобы форматировать и раскрашивать вывод из встроенной библиотеки logging. Вот пример вывода: + +![Logging](https://github.com/willmcgugan/rich/raw/master/imgs/logging.png) + +
+ +
+Эмоджи + +Чтобы вставить эмоджи в вывод консоли поместите название между двумя двоеточиями. Вот пример: + +```python +>>> console.print(":smiley: :vampire: :pile_of_poo: :thumbs_up: :raccoon:") +😃 🧛 💩 👍 🦝 +``` + +Пожалуйста, используйте это мудро. + +
+ +
+Таблицы + +Rich может отображать гибкие [таблицы](https://rich.readthedocs.io/en/latest/tables.html) с символами unicode. Есть большое количество форматов границ, стилей, выравниваний ячеек и т.п. + +![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) + +Эта анимация была сгенерирована с помощью [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) в директории примеров. + +Вот пример более простой таблицы: + +```python +from rich.console import Console +from rich.table import Table + +console = Console() + +table = Table(show_header=True, header_style="bold magenta") +table.add_column("Date", style="dim", width=12) +table.add_column("Title") +table.add_column("Production Budget", justify="right") +table.add_column("Box Office", justify="right") +table.add_row( + "Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118" +) +table.add_row( + "May 25, 2018", + "[red]Solo[/red]: A Star Wars Story", + "$275,000,000", + "$393,151,347", +) +table.add_row( + "Dec 15, 2017", + "Star Wars Ep. VIII: The Last Jedi", + "$262,000,000", + "[bold]$1,332,539,889[/bold]", +) + +console.print(table) +``` + +Этот пример выводит: + +![table](https://github.com/willmcgugan/rich/raw/master/imgs/table.png) + +Запомните что разметка консоли отображается таким же способом что и `print()` и `log()`. На самом деле, всё, что может отобразить Rich может быть в заголовках или рядах (даже другие таблицы). + +Класс `Table` достаточно умный чтобы менять размер столбцов, так, чтобы они заполняли доступную ширину терминала, обёртывая текст как нужно. Вот тот же самый пример с терминалом меньше таблицы: + +![table2](https://github.com/willmcgugan/rich/raw/master/imgs/table2.png) + +
+ +
+Прогресс Бары + +Rich может отображать несколько плавных [прогресс](https://rich.readthedocs.io/en/latest/progress.html) баров чтобы отслеживать долго-идущие задания. + +Для базового использования, оберните любую последовательность в функции `track` и переберите результат. Вот пример: + +```python +from rich.progress import track + +for step in track(range(100)): + do_step(step) +``` + +Отслеживать больше чем 1 задание не сложнее. Вот пример взятый из документации: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/progress.gif) + +Столбцы могут быть настроены чтобы показывать любые детали. Стандартные столбцы содержат проценты исполнения, размер файлы, скорость файла, и оставшееся время. Вот ещё пример показывающий загрузку в прогрессе: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/downloader.gif) + +Чтобы попробовать самому, скачайте [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) который может скачать несколько URL одновременно пока отображая прогресс. + +
+ +
+Статус + +Для ситуаций где сложно высчитать прогресс, вы можете использовать метод [статус](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console.status) который будет отображать крутящуюся анимацию и сообщение. Анимация не перекроет вам доступ к консоли. Вот пример: + +```python +from time import sleep +from rich.console import Console + +console = Console() +tasks = [f"task {n}" for n in range(1, 11)] + +with console.status("[bold green]Working on tasks...") as status: + while tasks: + task = tasks.pop(0) + sleep(1) + console.log(f"{task} complete") +``` + +Это генерирует вот такой вывод в консоль. + +![status](https://github.com/willmcgugan/rich/raw/master/imgs/status.gif) + +Крутящиеся анимации были взяты из [cli-spinners](https://www.npmjs.com/package/cli-spinners). Вы можете выбрать одну из них указав параметр `spinner`. Запустите следующую команду чтобы узнать доступные анимации: + +``` +python -m rich.spinner +``` + +Эта команда выдаёт вот такой вывод в терминал: + +![spinners](https://github.com/willmcgugan/rich/raw/master/imgs/spinners.gif) + +
+ +
+Дерево + +Rich может отобразить [дерево](https://rich.readthedocs.io/en/latest/tree.html) с указаниями. Дерево идеально подходит для отображения структуры файлов или любых других иерархических данных. + +Ярлыки дерева могут быть простым текстом или любой другой вещью Rich может отобразить. Запустите следующую команду для демонстрации: + +``` +python -m rich.tree +``` + +Это генерирует следующий вывод: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/tree.png) + +Смотрите пример [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) для скрипта который отображает дерево любой директории, похоже на команду linux `tree`. + +
+ +
+Столбцы + +Rich может отображать контент в [столбцах](https://rich.readthedocs.io/en/latest/columns.html) с равной или оптимальной шириной. Вот очень простой пример клона команды `ls` (MacOS / Linux) который отображает a файлы директории в столбцах: + +```python +import os +import sys + +from rich import print +from rich.columns import Columns + +directory = os.listdir(sys.argv[1]) +print(Columns(directory)) +``` + +Следующий скриншот это вывод из [примера столбцов](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) который изображает данные взятые из API в столбцах: + +![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) + +
+ +
+Markdown + +Rich может отображать [markdown](https://rich.readthedocs.io/en/latest/markdown.html) и делает неплохую работу в форматировании под терминал. + +Чтобы отобразить markdown импортируйте класс `Markdown` и инициализируйте его с помощью строки содержащей код markdown. После чего выведите его в консоль. Вот пример: + +```python +from rich.console import Console +from rich.markdown import Markdown + +console = Console() +with open("README.md") as readme: + markdown = Markdown(readme.read()) +console.print(markdown) +``` + +Это выведет что-то похожее на это: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/markdown.png) + +
+ +
+Подсвечивание Синтаксиса + +Rich использует библиотеку [pygments](https://pygments.org/) чтобы имплементировать [подсвечивание синтаксиса](https://rich.readthedocs.io/en/latest/syntax.html). Использование похоже на отображение markdown; инициализируйте класс `Syntax` и выводите его в консоль. Вот пример: + +```python +from rich.console import Console +from rich.syntax import Syntax + +my_code = ''' +def iter_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: + """Iterate and generate a tuple with a flag for first and last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + first = True + for value in iter_values: + yield first, False, previous_value + first = False + previous_value = value + yield first, True, previous_value +''' +syntax = Syntax(my_code, "python", theme="monokai", line_numbers=True) +console = Console() +console.print(syntax) +``` + +Это выведет что-то похожее на это: + +![syntax](https://github.com/willmcgugan/rich/raw/master/imgs/syntax.png) + +
+ +
+Ошибки + +Rich может отображать [красивые ошибки](https://rich.readthedocs.io/en/latest/traceback.html) которые проще читать и показывают больше кода чем стандартные ошибки Python. Вы можете установить Rich как стандартный обработчик ошибок чтобы все непойманные ошибки отображал Rich. + +Вот как это выглядит на OSX (похоже на Linux): + +![traceback](https://github.com/willmcgugan/rich/raw/master/imgs/traceback.png) + +
+ +Все визуализации Rich используют [протокол Console](https://rich.readthedocs.io/en/latest/protocol.html), который также позволяет вам добавлять свой Rich контент. + +# Rich для предприятий + +Rich доступен как часть подписки Tidelift. + +Поддержатели проекта Rich и тысячи других работают над подпиской Tidelift чтобы предоставить коммерческую поддержку и поддержание для проектов с открытым кодом вы используете чтобы построить своё приложение. Сохраните время, избавьтесь от риска, и улучшите состояние кода, пока вы платите поддержателям проектов вы используете. [Узнайте больше.](https://tidelift.com/subscription/pkg/pypi-rich?utm_source=pypi-rich&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +# Проекты использующие Rich + +Вот пару проектов использующих Rich: + +- [BrancoLab/BrainRender](https://github.com/BrancoLab/BrainRender) + библиотека Python для визуализации нейроанатомических данных в 3 измерениях +- [Ciphey/Ciphey](https://github.com/Ciphey/Ciphey) + автоматизированная утилита для расшифровки +- [emeryberger/scalene](https://github.com/emeryberger/scalene) + Высокая производительность, высокая точность CPU и профилировщик памяти для Python +- [hedythedev/StarCli](https://github.com/hedythedev/starcli) + Просматривайте трендовые проекты GitHub прямо из вашего терминала +- [intel/cve-bin-tool](https://github.com/intel/cve-bin-tool) + Эта утилита сканирует известные уязвимости (openssl, libpng, libxml2, expat and a few others) чтобы уведомить вас если ваша система использует библиотеки с известными уязвимостями. +- [nf-core/tools](https://github.com/nf-core/tools) + Библиотека Python с полезными инструментами для сообщества nf-core. +- [cansarigol/pdbr](https://github.com/cansarigol/pdbr) + pdb + Rich библиотека для улучшенного дебаггинга +- [plant99/felicette](https://github.com/plant99/felicette) + Изображения со спутников для чайников. +- [seleniumbase/SeleniumBase](https://github.com/seleniumbase/SeleniumBase) + Автоматизируйте и тестируйте в 10 раз быстрее с Selenium и pytest. Батарейки включены. +- [smacke/ffsubsync](https://github.com/smacke/ffsubsync) + Автоматически синхронизируйте субтитры с видео. +- [tryolabs/norfair](https://github.com/tryolabs/norfair) + Простая библиотека Python для добавления 2D отслеживания к любому детектеру в реальном времени. +- [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint проверяет пьесы для практик и поведений которые могут быть исправлены +- [ansible-community/molecule](https://github.com/ansible-community/molecule) Ansible Molecule тестинг фреймворк +- +[Ещё больше](https://github.com/willmcgugan/rich/network/dependents)! + + diff --git a/README.sv.md b/README.sv.md index 41564f7eeb..35b2669791 100644 --- a/README.sv.md +++ b/README.sv.md @@ -17,6 +17,7 @@ • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) Rich är ett Python bibliotek för _rich_ text och vacker formattering i terminalen. From c417aec782ffbee806528162f78d9e8689410113 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 14:30:08 +0000 Subject: [PATCH 196/287] eof --- .pre-commit-config.yaml | 16 +++ poetry.lock | 224 +++++++++++++++++++++++++++++++--------- pyproject.toml | 1 + 3 files changed, 194 insertions(+), 47 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..82c4aa129d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/psf/black + rev: 21.12b0 + hooks: + - id: black +- repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: isort (python) diff --git a/poetry.lock b/poetry.lock index d0391f5c70..06678a0859 100644 --- a/poetry.lock +++ b/poetry.lock @@ -129,6 +129,14 @@ python-versions = "*" [package.dependencies] pycparser = "*" +[[package]] +name = "cfgv" +version = "3.3.1" +description = "Validate configuration and produce human readable error messages." +category = "dev" +optional = false +python-versions = ">=3.6.1" + [[package]] name = "click" version = "8.0.3" @@ -198,6 +206,14 @@ category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "distlib" +version = "0.3.4" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "entrypoints" version = "0.3" @@ -206,6 +222,29 @@ category = "main" optional = true python-versions = ">=2.7" +[[package]] +name = "filelock" +version = "3.4.1" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] + +[[package]] +name = "identify" +version = "2.4.1" +description = "File identification library for Python" +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.extras] +license = ["ukkonen"] + [[package]] name = "importlib-metadata" version = "4.8.2" @@ -223,6 +262,21 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +[[package]] +name = "importlib-resources" +version = "5.2.3" +description = "Read resources from Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] + [[package]] name = "iniconfig" version = "1.1.1" @@ -525,6 +579,14 @@ category = "main" optional = true python-versions = ">=3.5" +[[package]] +name = "nodeenv" +version = "1.6.0" +description = "Node.js virtual environment builder" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "notebook" version = "6.4.6" @@ -639,6 +701,24 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pre-commit" +version = "2.16.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +importlib-resources = {version = "<5.3", markers = "python_version < \"3.7\""} +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + [[package]] name = "prometheus-client" version = "0.12.0" @@ -776,6 +856,14 @@ category = "main" optional = true python-versions = ">=3.6" +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "pyzmq" version = "22.3.0" @@ -806,7 +894,7 @@ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" category = "main" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] @@ -900,6 +988,26 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "virtualenv" +version = "20.13.0" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +distlib = ">=0.3.1,<1" +filelock = ">=3.2,<4" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""} +platformdirs = ">=2,<3" +six = ">=1.9.0,<2" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] + [[package]] name = "wcwidth" version = "0.2.5" @@ -945,7 +1053,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "9323c671d22223dca6b8630798611fd990a0e3d7ac15d97ac4cece4fc89b3bb4" +content-hash = "020be391dbd668426ce6c2c3b98366d3bc4612dee16f75208ed298c27130013b" [metadata.files] appnope = [ @@ -1055,6 +1163,10 @@ cffi = [ {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, @@ -1128,14 +1240,30 @@ defusedxml = [ {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +distlib = [ + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, +] entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] +filelock = [ + {file = "filelock-3.4.1-py3-none-any.whl", hash = "sha256:a4bc51381e01502a30e9f06dd4fa19a1712eab852b6fb0f84fd7cce0793d8ca3"}, + {file = "filelock-3.4.1.tar.gz", hash = "sha256:0f12f552b42b5bf60dba233710bf71337d35494fc8bdd4fd6d9f6d082ad45e06"}, +] +identify = [ + {file = "identify-2.4.1-py2.py3-none-any.whl", hash = "sha256:0192893ff68b03d37fed553e261d4a22f94ea974093aefb33b29df2ff35fed3c"}, + {file = "identify-2.4.1.tar.gz", hash = "sha256:64d4885e539f505dd8ffb5e93c142a1db45480452b1594cacd3e91dca9a984e9"}, +] importlib-metadata = [ {file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"}, {file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"}, ] +importlib-resources = [ + {file = "importlib_resources-5.2.3-py3-none-any.whl", hash = "sha256:ae35ed1cfe8c0d6c1a53ecd168167f01fa93b893d51a62cdf23aea044c67211b"}, + {file = "importlib_resources-5.2.3.tar.gz", hash = "sha256:203d70dda34cfbfbb42324a8d4211196e7d3e858de21a5eb68c6d1cdd99e4e98"}, +] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, @@ -1185,28 +1313,12 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1215,27 +1327,14 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1245,12 +1344,6 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1301,6 +1394,10 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.4-py3-none-any.whl", hash = "sha256:3fdd0d6061a2bb16f21fe8a9c6a7945be83521d81a0d15cff52e9edee50101d6"}, {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"}, ] +nodeenv = [ + {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, + {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, +] notebook = [ {file = "notebook-6.4.6-py3-none-any.whl", hash = "sha256:5cad068fa82cd4fb98d341c052100ed50cd69fbfb4118cb9b8ab5a346ef27551"}, {file = "notebook-6.4.6.tar.gz", hash = "sha256:7bcdf79bd1cda534735bd9830d2cbedab4ee34d8fe1df6e7b946b3aab0902ba3"}, @@ -1337,6 +1434,10 @@ pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] +pre-commit = [ + {file = "pre_commit-2.16.0-py2.py3-none-any.whl", hash = "sha256:758d1dc9b62c2ed8881585c254976d66eae0889919ab9b859064fc2fe3c7743e"}, + {file = "pre_commit-2.16.0.tar.gz", hash = "sha256:fe9897cac830aa7164dbd02a4e7b90cae49630451ce88464bca73db486ba9f65"}, +] prometheus-client = [ {file = "prometheus_client-0.12.0-py2.py3-none-any.whl", hash = "sha256:317453ebabff0a1b02df7f708efbab21e3489e7072b61cb6957230dd004a0af0"}, {file = "prometheus_client-0.12.0.tar.gz", hash = "sha256:1b12ba48cee33b9b0b9de64a1047cbd3c5f2d0ab6ebcead7ddda613a750ec3c5"}, @@ -1420,38 +1521,65 @@ pywinpty = [ {file = "pywinpty-1.1.6-cp39-none-win_amd64.whl", hash = "sha256:c703bf569a98ab7844b9daf37e88ab86f31862754ef6910a8b3824993a525c72"}, {file = "pywinpty-1.1.6.tar.gz", hash = "sha256:8808f07350c709119cc4464144d6e749637f98e15acc1e5d3c37db1953d2eebc"}, ] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2841997a0d85b998cbafecb4183caf51fd19c4357075dfd33eb7efea57e4c149"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1459,8 +1587,6 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, @@ -1580,6 +1706,10 @@ typing-extensions = [ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, ] +virtualenv = [ + {file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"}, + {file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"}, +] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, diff --git a/pyproject.toml b/pyproject.toml index e017d29c07..42b60550f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ mypy = "^0.930" pytest-cov = "^3.0.0" attrs = "^21.4.0" types-dataclasses = "^0.6.2" +pre-commit = "^2.16.0" [build-system] requires = ["poetry-core>=1.0.0"] From 76b5dd233a866f8975e15fa92849e1ff743b6067 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 15:04:47 +0000 Subject: [PATCH 197/287] Update tests/test_pretty.py Co-authored-by: Darren Burns --- tests/test_pretty.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pretty.py b/tests/test_pretty.py index 1752d1e6d1..40bb485fc7 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -132,7 +132,7 @@ def test_recursive(): def test_max_depth(): - d = d = {} + d = {} d["foo"] = {"fob": {"a": [1, 2, 3], "b": {"z": "x", "y": ["a", "b", "c"]}}} assert pretty_repr(d, max_depth=0) == "..." From 3974a9ef828e724ba57f34ca977962325a3bedae Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 15:05:11 +0000 Subject: [PATCH 198/287] Update rich/pretty.py Co-authored-by: Darren Burns --- rich/pretty.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/pretty.py b/rich/pretty.py index 80c4df98eb..10cc29251e 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -805,7 +805,7 @@ def pprint( max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to None. max_string (int, optional): Maximum length of strings before truncating, or None to disable. Defaults to None. - max_depth (int, optional): Maximum depth for nested data structures, or None for no maximum. Defaults to None. + max_depth (int, optional): Maximum depth for nested data structures, or None for unlimited depth. Defaults to None. indent_guides (bool, optional): Enable indentation guides. Defaults to True. expand_all (bool, optional): Expand all containers. Defaults to False. """ From bff7981788dd9a29bff771f0bc2267d1e3936f31 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Thu, 6 Jan 2022 15:07:05 +0000 Subject: [PATCH 199/287] test max depth of None --- tests/test_pretty.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_pretty.py b/tests/test_pretty.py index 1752d1e6d1..e955bd610e 100644 --- a/tests/test_pretty.py +++ b/tests/test_pretty.py @@ -147,6 +147,10 @@ def test_max_depth(): pretty_repr(d, max_width=100, max_depth=5) == "{'foo': {'fob': {'a': [1, 2, 3], 'b': {'z': 'x', 'y': ['a', 'b', 'c']}}}}" ) + assert ( + pretty_repr(d, max_width=100, max_depth=None) + == "{'foo': {'fob': {'a': [1, 2, 3], 'b': {'z': 'x', 'y': ['a', 'b', 'c']}}}}" + ) def test_max_depth_rich_repr(): From d8ff3597aea90ea01ad81ac1cb894b7a11a7d212 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 16:39:22 +0000 Subject: [PATCH 200/287] Theme used for Traceback should not inherit defaults --- rich/traceback.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/rich/traceback.py b/rich/traceback.py index a27affddc2..723a2f9a44 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -6,7 +6,8 @@ from dataclasses import dataclass, field from traceback import walk_tb from types import ModuleType, TracebackType -from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Type, Union +from typing import (Any, Callable, Dict, Iterable, List, Optional, Sequence, + Type, Union) from pygments.lexers import guess_lexer_for_filename from pygments.token import Comment, Keyword, Name, Number, Operator, String @@ -16,13 +17,8 @@ from . import pretty from ._loop import loop_first, loop_last from .columns import Columns -from .console import ( - Console, - ConsoleOptions, - ConsoleRenderable, - RenderResult, - group, -) +from .console import (Console, ConsoleOptions, ConsoleRenderable, RenderResult, + group) from .constrain import Constrain from .highlighter import RegexHighlighter, ReprHighlighter from .panel import Panel @@ -443,7 +439,8 @@ def __rich_console__( "scope.equals": token_style(Operator), "scope.key": token_style(Name), "scope.key.special": token_style(Name.Constant) + Style(dim=True), - } + }, + inherit=False, ) highlighter = ReprHighlighter() From 757555b9eb28f4757ca798964b7c27ca6603a4ec Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 16:41:31 +0000 Subject: [PATCH 201/287] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5f50c903d..a2868fd84f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added max_depth arg to pretty printing +- Fix Traceback theme defaults override user supplied styles https://github.com/Textualize/rich/issues/1786 ## [10.16.2] - 2021-01-02 From 7c27af63ff303fa2f677d8fbaf60ca80e7d44b01 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 16:42:35 +0000 Subject: [PATCH 202/287] Let isort & black play together nicely, adds new hooks --- .pre-commit-config.yaml | 45 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82c4aa129d..892dc79187 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,37 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace -- repo: https://github.com/psf/black + - id: check-ast + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-merge-conflict + - id: check-json + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + - id: check-vcs-permalinks + - id: check-shebang-scripts-are-executable + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.9.0 + hooks: + - id: python-check-mock-methods + - id: python-no-eval + - id: python-no-log-warn + - id: python-use-type-annotations + - id: rst-directive-colons + - id: rst-inline-touching-normal + - repo: https://github.com/psf/black rev: 21.12b0 hooks: - - id: black -- repo: https://github.com/pycqa/isort - rev: 5.10.1 - hooks: - - id: isort - name: isort (python) + - id: black + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + args: ["--profile", "black"] From 810ba9369241152e89b2a77e8b9b3e4666a98c32 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 16:49:08 +0000 Subject: [PATCH 203/287] Fix formatting --- rich/_windows.py | 1 + rich/traceback.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/rich/_windows.py b/rich/_windows.py index 5169d83556..bac88e639b 100644 --- a/rich/_windows.py +++ b/rich/_windows.py @@ -30,6 +30,7 @@ def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() return features + else: STDOUT = -11 diff --git a/rich/traceback.py b/rich/traceback.py index 723a2f9a44..f683ea94a8 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -6,8 +6,7 @@ from dataclasses import dataclass, field from traceback import walk_tb from types import ModuleType, TracebackType -from typing import (Any, Callable, Dict, Iterable, List, Optional, Sequence, - Type, Union) +from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Type, Union from pygments.lexers import guess_lexer_for_filename from pygments.token import Comment, Keyword, Name, Number, Operator, String @@ -17,8 +16,7 @@ from . import pretty from ._loop import loop_first, loop_last from .columns import Columns -from .console import (Console, ConsoleOptions, ConsoleRenderable, RenderResult, - group) +from .console import Console, ConsoleOptions, ConsoleRenderable, RenderResult, group from .constrain import Constrain from .highlighter import RegexHighlighter, ReprHighlighter from .panel import Panel From 26bdcc5e760ccb1a84b1ce33af36ec89fa35c0bc Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 20:09:38 +0000 Subject: [PATCH 204/287] Ensuring correct version of Black is used --- rich/_windows.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rich/_windows.py b/rich/_windows.py index bac88e639b..b1b30b65ec 100644 --- a/rich/_windows.py +++ b/rich/_windows.py @@ -1,5 +1,4 @@ import sys - from dataclasses import dataclass @@ -15,8 +14,7 @@ class WindowsConsoleFeatures: try: import ctypes - from ctypes import wintypes - from ctypes import LibraryLoader + from ctypes import LibraryLoader, wintypes if sys.platform == "win32": windll = LibraryLoader(ctypes.WinDLL) @@ -30,7 +28,6 @@ def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() return features - else: STDOUT = -11 From 371c3e2eee96a72ed658251d6e4f93af34060218 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 20:21:38 +0000 Subject: [PATCH 205/287] Handle case where force_jupyter=True, but IPython not found --- rich/jupyter.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rich/jupyter.py b/rich/jupyter.py index 7cdcc9cabc..bedf5cb19a 100644 --- a/rich/jupyter.py +++ b/rich/jupyter.py @@ -4,7 +4,6 @@ from .segment import Segment from .terminal_theme import DEFAULT_TERMINAL_THEME - JUPYTER_HTML_FORMAT = """\
{code}
""" @@ -75,11 +74,16 @@ def escape(text: str) -> str: def display(segments: Iterable[Segment], text: str) -> None: """Render segments to Jupyter.""" - from IPython.display import display as ipython_display - html = _render_segments(segments) jupyter_renderable = JupyterRenderable(html, text) - ipython_display(jupyter_renderable) + try: + from IPython.display import display as ipython_display + + ipython_display(jupyter_renderable) + except ModuleNotFoundError: + # Handle the case where the Console has force_jupyter=True, + # but IPython is not installed. + pass def print(*args: Any, **kwargs: Any) -> None: From fa0ab1fdd6b0ccc86066d6c42344d997bb79524d Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 20:30:14 +0000 Subject: [PATCH 206/287] Use Python 3.6-supported Optional instead of `| None` --- rich/pretty.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index 47d9e0548e..62fed6d7b0 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -1,31 +1,30 @@ -from __future__ import annotations - import builtins +import dataclasses import inspect import os -from rich.repr import RichReprResult +import re import sys from array import array -from collections import Counter, defaultdict, deque, UserDict, UserList -import dataclasses +from collections import Counter, UserDict, UserList, defaultdict, deque from dataclasses import dataclass, fields, is_dataclass from inspect import isclass from itertools import islice -import re +from types import MappingProxyType from typing import ( - DefaultDict, TYPE_CHECKING, Any, Callable, + DefaultDict, Dict, Iterable, List, Optional, Set, - Union, Tuple, + Union, ) -from types import MappingProxyType + +from rich.repr import RichReprResult try: import attr as _attr_module @@ -33,7 +32,6 @@ _attr_module = None # type: ignore -from .highlighter import ReprHighlighter from . import get_console from ._loop import loop_last from ._pick import pick_bool @@ -84,7 +82,7 @@ def _is_dataclass_repr(obj: object) -> bool: def _ipy_display_hook( value: Any, - console: Console | None = None, + console: Optional[Console] = None, overflow: "OverflowMethod" = "ignore", crop: bool = False, indent_guides: bool = False, From 1f7c5dffe1e98a3a5703b919d6d3d188a7901077 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 20:40:47 +0000 Subject: [PATCH 207/287] Add quotes around type --- rich/pretty.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/pretty.py b/rich/pretty.py index 62fed6d7b0..57e743df49 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -82,7 +82,7 @@ def _is_dataclass_repr(obj: object) -> bool: def _ipy_display_hook( value: Any, - console: Optional[Console] = None, + console: Optional["Console"] = None, overflow: "OverflowMethod" = "ignore", crop: bool = False, indent_guides: bool = False, From 8e622897547e1da1e832892f47625ff8fa10a16e Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 21:14:08 +0000 Subject: [PATCH 208/287] Add regression test to ensure theme from Console applies to Tracebacks --- tests/test_traceback.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/test_traceback.py b/tests/test_traceback.py index 3b3e8de65d..88b89438a2 100644 --- a/tests/test_traceback.py +++ b/tests/test_traceback.py @@ -4,7 +4,8 @@ import pytest from rich.console import Console -from rich.traceback import install, Traceback +from rich.theme import Theme +from rich.traceback import Traceback, install # from .render import render @@ -109,7 +110,7 @@ def test_syntax_error(): console = Console(width=100, file=io.StringIO()) try: # raises SyntaxError: unexpected EOF while parsing - eval("(2 + 2") + compile("(2+2") except Exception: console.print_exception() exception_text = console.file.getvalue() @@ -190,6 +191,29 @@ def test_filename_not_a_file(): assert "string" in exception_text +def test_traceback_console_theme_applies(): + """ + Ensure that themes supplied via Console init work on Tracebacks. + Regression test for https://github.com/Textualize/rich/issues/1786 + """ + r, g, b = 123, 234, 123 + console = Console( + force_terminal=True, + _environ={"COLORTERM": "truecolor"}, + theme=Theme({"traceback.title": f"rgb({r},{g},{b})"}), + ) + + console.begin_capture() + try: + 1 / 0 + except Exception: + console.print_exception() + + result = console.end_capture() + + assert f"\\x1b[38;2;{r};{g};{b}mTraceback \\x1b[0m" in repr(result) + + def test_broken_str(): class BrokenStr(Exception): def __str__(self): From 1a053eb9e6355d40e64b82f0103d021d4e17a9ce Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 6 Jan 2022 21:21:30 +0000 Subject: [PATCH 209/287] Skip test on Windows --- tests/test_traceback.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_traceback.py b/tests/test_traceback.py index 88b89438a2..e3342ca13c 100644 --- a/tests/test_traceback.py +++ b/tests/test_traceback.py @@ -191,6 +191,7 @@ def test_filename_not_a_file(): assert "string" in exception_text +@pytest.mark.skipif(sys.platform == "win32", reason="renders different on windows") def test_traceback_console_theme_applies(): """ Ensure that themes supplied via Console init work on Tracebacks. From 5960f54917b3b4c5926700b77696e5fc851cab82 Mon Sep 17 00:00:00 2001 From: Aaron Stephens Date: Thu, 6 Jan 2022 22:44:05 -0800 Subject: [PATCH 210/287] chore: fix typos --- rich/traceback.py | 2 +- tests/test_columns.py | 4 ++-- tests/test_highlighter.py | 2 +- tests/test_logging.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rich/traceback.py b/rich/traceback.py index a27affddc2..845f600671 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -135,7 +135,7 @@ def ipy_display_traceback( ) try: # pragma: no cover - # if wihin ipython, use customized traceback + # if within ipython, use customized traceback ip = get_ipython() # type: ignore ipy_excepthook_closure(ip) return sys.excepthook diff --git a/tests/test_columns.py b/tests/test_columns.py index 927aba2116..1b167f4acb 100644 --- a/tests/test_columns.py +++ b/tests/test_columns.py @@ -41,7 +41,7 @@ def render(): console.rule("optimal, expand") columns.expand = True console.print(columns) - console.rule("columm first, optimal") + console.rule("column first, optimal") columns.column_first = True columns.expand = False console.print(columns) @@ -62,7 +62,7 @@ def render(): def test_render(): - expected = "────────────────────────────────────────────── empty ───────────────────────────────────────────────\n───────────────────────────────────────────── optimal ──────────────────────────────────────────────\nUrsus americanus American buffalo Bison bison American crow \nCorvus brachyrhynchos American marten Martes americana American racer \nColuber constrictor American woodcock Scolopax minor Anaconda (unidentified)\nEunectes sp. Andean goose Chloephaga melanoptera Ant \nAnteater, australian spiny Tachyglossus aculeatus Anteater, giant Myrmecophaga tridactyla\n───────────────────────────────────────── optimal, expand ──────────────────────────────────────────\nUrsus americanus American buffalo Bison bison American crow \nCorvus brachyrhynchos American marten Martes americana American racer \nColuber constrictor American woodcock Scolopax minor Anaconda (unidentified)\nEunectes sp. Andean goose Chloephaga melanoptera Ant \nAnteater, australian spiny Tachyglossus aculeatus Anteater, giant Myrmecophaga tridactyla\n────────────────────────────────────── columm first, optimal ───────────────────────────────────────\nUrsus americanus American marten Scolopax minor Ant \nAmerican buffalo Martes americana Anaconda (unidentified) Anteater, australian spiny\nBison bison American racer Eunectes sp. Tachyglossus aculeatus \nAmerican crow Coluber constrictor Andean goose Anteater, giant \nCorvus brachyrhynchos American woodcock Chloephaga melanoptera Myrmecophaga tridactyla \n─────────────────────────────────── column first, right to left ────────────────────────────────────\nAnt Scolopax minor American marten Ursus americanus \nAnteater, australian spiny Anaconda (unidentified) Martes americana American buffalo \nTachyglossus aculeatus Eunectes sp. American racer Bison bison \nAnteater, giant Andean goose Coluber constrictor American crow \nMyrmecophaga tridactyla Chloephaga melanoptera American woodcock Corvus brachyrhynchos\n────────────────────────────────────── equal columns, expand ───────────────────────────────────────\nChloephaga melanoptera American racer Ursus americanus \nAnt Coluber constrictor American buffalo \nAnteater, australian spiny American woodcock Bison bison \nTachyglossus aculeatus Scolopax minor American crow \nAnteater, giant Anaconda (unidentified) Corvus brachyrhynchos \nMyrmecophaga tridactyla Eunectes sp. American marten \n Andean goose Martes americana \n─────────────────────────────────────────── fixed width ────────────────────────────────────────────\nAnteater, Eunectes sp. Coluber Corvus Ursus americanus \naustralian spiny constrictor brachyrhynchos \nTachyglossus Andean goose American American marten American buffalo \naculeatus woodcock \nAnteater, giant Chloephaga Scolopax minor Martes americana Bison bison \n melanoptera \nMyrmecophaga Ant Anaconda American racer American crow \ntridactyla (unidentified) \n\n" + expected = "────────────────────────────────────────────── empty ───────────────────────────────────────────────\n───────────────────────────────────────────── optimal ──────────────────────────────────────────────\nUrsus americanus American buffalo Bison bison American crow \nCorvus brachyrhynchos American marten Martes americana American racer \nColuber constrictor American woodcock Scolopax minor Anaconda (unidentified)\nEunectes sp. Andean goose Chloephaga melanoptera Ant \nAnteater, australian spiny Tachyglossus aculeatus Anteater, giant Myrmecophaga tridactyla\n───────────────────────────────────────── optimal, expand ──────────────────────────────────────────\nUrsus americanus American buffalo Bison bison American crow \nCorvus brachyrhynchos American marten Martes americana American racer \nColuber constrictor American woodcock Scolopax minor Anaconda (unidentified)\nEunectes sp. Andean goose Chloephaga melanoptera Ant \nAnteater, australian spiny Tachyglossus aculeatus Anteater, giant Myrmecophaga tridactyla\n────────────────────────────────────── column first, optimal ───────────────────────────────────────\nUrsus americanus American marten Scolopax minor Ant \nAmerican buffalo Martes americana Anaconda (unidentified) Anteater, australian spiny\nBison bison American racer Eunectes sp. Tachyglossus aculeatus \nAmerican crow Coluber constrictor Andean goose Anteater, giant \nCorvus brachyrhynchos American woodcock Chloephaga melanoptera Myrmecophaga tridactyla \n─────────────────────────────────── column first, right to left ────────────────────────────────────\nAnt Scolopax minor American marten Ursus americanus \nAnteater, australian spiny Anaconda (unidentified) Martes americana American buffalo \nTachyglossus aculeatus Eunectes sp. American racer Bison bison \nAnteater, giant Andean goose Coluber constrictor American crow \nMyrmecophaga tridactyla Chloephaga melanoptera American woodcock Corvus brachyrhynchos\n────────────────────────────────────── equal columns, expand ───────────────────────────────────────\nChloephaga melanoptera American racer Ursus americanus \nAnt Coluber constrictor American buffalo \nAnteater, australian spiny American woodcock Bison bison \nTachyglossus aculeatus Scolopax minor American crow \nAnteater, giant Anaconda (unidentified) Corvus brachyrhynchos \nMyrmecophaga tridactyla Eunectes sp. American marten \n Andean goose Martes americana \n─────────────────────────────────────────── fixed width ────────────────────────────────────────────\nAnteater, Eunectes sp. Coluber Corvus Ursus americanus \naustralian spiny constrictor brachyrhynchos \nTachyglossus Andean goose American American marten American buffalo \naculeatus woodcock \nAnteater, giant Chloephaga Scolopax minor Martes americana Bison bison \n melanoptera \nMyrmecophaga Ant Anaconda American racer American crow \ntridactyla (unidentified) \n\n" assert render() == expected diff --git a/tests/test_highlighter.py b/tests/test_highlighter.py index b683312d1e..99793723c8 100644 --- a/tests/test_highlighter.py +++ b/tests/test_highlighter.py @@ -1,4 +1,4 @@ -"""Tests for the higlighter classes.""" +"""Tests for the highlighter classes.""" import pytest from typing import List diff --git a/tests/test_logging.py b/tests/test_logging.py index a7353968ea..ce3ac25af9 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -93,7 +93,7 @@ def test_exception_with_extra_lines(): def test_stderr_and_stdout_are_none(monkeypatch): # This test is specifically to handle cases when using pythonw on - # windows an stderr and stdout are set to None. + # windows and stderr and stdout are set to None. # See https://bugs.python.org/issue13807 monkeypatch.setattr("sys.stdout", None) From f220a5085bdbc2a6f1b697b2f3fb9ce3a402f2d6 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 11:49:21 +0000 Subject: [PATCH 211/287] formatting --- rich/segment.py | 105 ++++++++++++++++++++++++++++++++++++++++-- rich/table.py | 46 +++++++++++++++--- tests/_card_render.py | 2 +- tests/test_log.py | 3 +- tests/test_segment.py | 35 ++++++++++++-- tests/test_table.py | 28 ++++++++++- 6 files changed, 200 insertions(+), 19 deletions(-) diff --git a/rich/segment.py b/rich/segment.py index c9bb4a494f..dac9f655c1 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -12,6 +12,7 @@ Optional, Sequence, Tuple, + Type, Union, ) @@ -384,21 +385,28 @@ def set_shape( lines (List[List[Segment]]): A list of lines. width (int): Desired width. height (int, optional): Desired height or None for no change. - style (Style, optional): Style of any padding added. Defaults to None. + style (Style, optional): Style of any padding added. new_lines (bool, optional): Padded lines should include "\n". Defaults to False. Returns: - List[List[Segment]]: New list of lines that fits width x height. + List[List[Segment]]: New list of lines. """ if height is None: height = len(lines) - shaped_lines: List[List[Segment]] = [] - pad_line = ( + blank = ( [Segment(" " * width, style), Segment("\n")] if new_lines else [Segment(" " * width, style)] ) + adjust_line_length = cls.adjust_line_length + shaped_lines = [ + adjust_line_length(line, width, style=style) for line in lines[:height] + ] + if len(shaped_lines) < height: + shaped_lines.extend([blank] * (height - len(shaped_lines))) + return shaped_lines + append = shaped_lines.append adjust_line_length = cls.adjust_line_length line: Optional[List[Segment]] @@ -411,6 +419,95 @@ def set_shape( append(adjust_line_length(line, width, style=style)) return shaped_lines + @classmethod + def align_top( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns lines to top (adds extra lines to bottom as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style, optional): Style of any padding added. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + lines = lines + [[blank]] * extra_lines + return lines + + @classmethod + def align_bottom( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns render to bottom (adds extra lines above as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style, optional): Style of any padding added. Defaults to None. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + lines = [[blank]] * extra_lines + lines + return lines + + @classmethod + def align_middle( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns lines to middle (adds extra lines to above and below as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style, optional): Style of any padding added. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + top_lines = extra_lines // 2 + bottom_lines = extra_lines - top_lines + lines = [[blank]] * top_lines + lines + [[blank]] * bottom_lines + return lines + @classmethod def simplify(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: """Simplify an iterable of segments by combining contiguous segments with the same style. diff --git a/rich/table.py b/rich/table.py index 24d7afbd26..2b11fbd38b 100644 --- a/rich/table.py +++ b/rich/table.py @@ -1,7 +1,7 @@ from dataclasses import dataclass, field, replace from typing import ( - Dict, TYPE_CHECKING, + Dict, Iterable, List, NamedTuple, @@ -15,6 +15,7 @@ from ._loop import loop_first_last, loop_last from ._pick import pick_bool from ._ratio import ratio_distribute, ratio_reduce +from .align import VerticalAlignMethod from .jupyter import JupyterMixin from .measure import Measurement from .padding import Padding, PaddingDimensions @@ -56,6 +57,9 @@ class Column: justify: "JustifyMethod" = "left" """str: How to justify text within the column ("left", "center", "right", or "full")""" + vertical_align: "VerticalAlignMethod" = "top" + """str: How to vertically align content ("top", "middle", or "bottom")""" + overflow: "OverflowMethod" = "ellipsis" """str: Overflow method.""" @@ -112,6 +116,8 @@ class _Cell(NamedTuple): """Style to apply to cell.""" renderable: "RenderableType" """Cell renderable.""" + vertical_align: VerticalAlignMethod + """Cell vertical alignment.""" class Table(JupyterMixin): @@ -335,6 +341,7 @@ def add_column( footer_style: Optional[StyleType] = None, style: Optional[StyleType] = None, justify: "JustifyMethod" = "left", + vertical_align: "VerticalAlignMethod" = "top", overflow: "OverflowMethod" = "ellipsis", width: Optional[int] = None, min_width: Optional[int] = None, @@ -353,6 +360,7 @@ def add_column( footer_style (Union[str, Style], optional): Style for the footer, or None for default. Defaults to None. style (Union[str, Style], optional): Style for the column cells, or None for default. Defaults to None. justify (JustifyMethod, optional): Alignment for cells. Defaults to "left". + vertical_align (VerticalAlignMethod, optional): Vertical alignment, one of "top", "middle", or "bottom". Defaults to "top". overflow (OverflowMethod): Overflow method: "crop", "fold", "ellipsis". Defaults to "ellipsis". width (int, optional): Desired width of column in characters, or None to fit to contents. Defaults to None. min_width (Optional[int], optional): Minimum width of column, or ``None`` for no minimum. Defaults to None. @@ -369,6 +377,7 @@ def add_column( footer_style=footer_style or "", style=style or "", justify=justify, + vertical_align=vertical_align, overflow=overflow, width=width, min_width=min_width, @@ -636,10 +645,14 @@ def get_padding(first_row: bool, last_row: bool) -> Tuple[int, int, int, int]: if any_padding: _Padding = Padding for first, last, (style, renderable) in loop_first_last(raw_cells): - yield _Cell(style, _Padding(renderable, get_padding(first, last))) + yield _Cell( + style, + _Padding(renderable, get_padding(first, last)), + column.vertical_align, + ) else: for (style, renderable) in raw_cells: - yield _Cell(style, renderable) + yield _Cell(style, renderable, column.vertical_align) def _get_padding_width(self, column_index: int) -> int: """Get extra width from padding.""" @@ -770,18 +783,37 @@ def _render( overflow=column.overflow, height=None, ) - cell_style = table_style + row_style + get_style(cell.style) lines = console.render_lines( - cell.renderable, render_options, style=cell_style + cell.renderable, + render_options, + style=get_style(cell.style) + row_style, ) max_height = max(max_height, len(lines)) cells.append(lines) + row_height = max(len(cell) for cell in cells) + + def align_cell( + cell: List[List[Segment]], + vertical_align: "VerticalAlignMethod", + style: Style, + ) -> List[List[Segment]]: + + if vertical_align == "top": + return _Segment.align_top(cell, width, row_height, style) + elif vertical_align == "middle": + return _Segment.align_middle(cell, width, row_height, style) + return _Segment.align_bottom(cell, width, row_height, style) + cells[:] = [ _Segment.set_shape( - _cell, width, max_height, style=table_style + row_style + align_cell( + cell, column.vertical_align, get_style(_cell.style) + row_style + ), + width, + max_height, ) - for width, _cell in zip(widths, cells) + for width, _cell, cell, column in zip(widths, row_cell, cells, columns) ] if _box: diff --git a/tests/_card_render.py b/tests/_card_render.py index 232191da0f..bc713103b0 100644 --- a/tests/_card_render.py +++ b/tests/_card_render.py @@ -1 +1 @@ -expected = """\x1b[3m Rich features \x1b[0m\n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Colors \x1b[0m\x1b[1;31m \x1b[0m✓ \x1b[1;32m4-bit color\x1b[0m \x1b[38;2;86;0;0;48;2;51;0;0m▄\x1b[0m\x1b[38;2;86;9;0;48;2;51;5;0m▄\x1b[0m\x1b[38;2;86;18;0;48;2;51;11;0m▄\x1b[0m\x1b[38;2;86;28;0;48;2;51;16;0m▄\x1b[0m\x1b[38;2;86;37;0;48;2;51;22;0m▄\x1b[0m\x1b[38;2;86;47;0;48;2;51;27;0m▄\x1b[0m\x1b[38;2;86;56;0;48;2;51;33;0m▄\x1b[0m\x1b[38;2;86;66;0;48;2;51;38;0m▄\x1b[0m\x1b[38;2;86;75;0;48;2;51;44;0m▄\x1b[0m\x1b[38;2;86;85;0;48;2;51;50;0m▄\x1b[0m\x1b[38;2;78;86;0;48;2;46;51;0m▄\x1b[0m\x1b[38;2;69;86;0;48;2;40;51;0m▄\x1b[0m\x1b[38;2;59;86;0;48;2;35;51;0m▄\x1b[0m\x1b[38;2;50;86;0;48;2;29;51;0m▄\x1b[0m\x1b[38;2;40;86;0;48;2;24;51;0m▄\x1b[0m\x1b[38;2;31;86;0;48;2;18;51;0m▄\x1b[0m\x1b[38;2;22;86;0;48;2;12;51;0m▄\x1b[0m\x1b[38;2;12;86;0;48;2;7;51;0m▄\x1b[0m\x1b[38;2;3;86;0;48;2;1;51;0m▄\x1b[0m\x1b[38;2;0;86;6;48;2;0;51;3m▄\x1b[0m\x1b[38;2;0;86;15;48;2;0;51;9m▄\x1b[0m\x1b[38;2;0;86;25;48;2;0;51;14m▄\x1b[0m\x1b[38;2;0;86;34;48;2;0;51;20m▄\x1b[0m\x1b[38;2;0;86;44;48;2;0;51;25m▄\x1b[0m\x1b[38;2;0;86;53;48;2;0;51;31m▄\x1b[0m\x1b[38;2;0;86;63;48;2;0;51;37m▄\x1b[0m\x1b[38;2;0;86;72;48;2;0;51;42m▄\x1b[0m\x1b[38;2;0;86;81;48;2;0;51;48m▄\x1b[0m\x1b[38;2;0;81;86;48;2;0;48;51m▄\x1b[0m\x1b[38;2;0;72;86;48;2;0;42;51m▄\x1b[0m\x1b[38;2;0;63;86;48;2;0;37;51m▄\x1b[0m\x1b[38;2;0;53;86;48;2;0;31;51m▄\x1b[0m\x1b[38;2;0;44;86;48;2;0;25;51m▄\x1b[0m\x1b[38;2;0;34;86;48;2;0;20;51m▄\x1b[0m\x1b[38;2;0;25;86;48;2;0;14;51m▄\x1b[0m\x1b[38;2;0;15;86;48;2;0;9;51m▄\x1b[0m\x1b[38;2;0;6;86;48;2;0;3;51m▄\x1b[0m\x1b[38;2;3;0;86;48;2;1;0;51m▄\x1b[0m\x1b[38;2;12;0;86;48;2;7;0;51m▄\x1b[0m\x1b[38;2;22;0;86;48;2;12;0;51m▄\x1b[0m\x1b[38;2;31;0;86;48;2;18;0;51m▄\x1b[0m\x1b[38;2;40;0;86;48;2;24;0;51m▄\x1b[0m\x1b[38;2;50;0;86;48;2;29;0;51m▄\x1b[0m\x1b[38;2;59;0;86;48;2;35;0;51m▄\x1b[0m\x1b[38;2;69;0;86;48;2;40;0;51m▄\x1b[0m\x1b[38;2;78;0;86;48;2;46;0;51m▄\x1b[0m\x1b[38;2;86;0;85;48;2;51;0;50m▄\x1b[0m\x1b[38;2;86;0;75;48;2;51;0;44m▄\x1b[0m\x1b[38;2;86;0;66;48;2;51;0;38m▄\x1b[0m\x1b[38;2;86;0;56;48;2;51;0;33m▄\x1b[0m\x1b[38;2;86;0;47;48;2;51;0;27m▄\x1b[0m\x1b[38;2;86;0;37;48;2;51;0;22m▄\x1b[0m\x1b[38;2;86;0;28;48;2;51;0;16m▄\x1b[0m\x1b[38;2;86;0;18;48;2;51;0;11m▄\x1b[0m\x1b[38;2;86;0;9;48;2;51;0;5m▄\x1b[0m \n ✓ \x1b[1;34m8-bit color\x1b[0m \x1b[38;2;158;0;0;48;2;122;0;0m▄\x1b[0m\x1b[38;2;158;17;0;48;2;122;13;0m▄\x1b[0m\x1b[38;2;158;34;0;48;2;122;26;0m▄\x1b[0m\x1b[38;2;158;51;0;48;2;122;40;0m▄\x1b[0m\x1b[38;2;158;68;0;48;2;122;53;0m▄\x1b[0m\x1b[38;2;158;86;0;48;2;122;66;0m▄\x1b[0m\x1b[38;2;158;103;0;48;2;122;80;0m▄\x1b[0m\x1b[38;2;158;120;0;48;2;122;93;0m▄\x1b[0m\x1b[38;2;158;137;0;48;2;122;106;0m▄\x1b[0m\x1b[38;2;158;155;0;48;2;122;120;0m▄\x1b[0m\x1b[38;2;143;158;0;48;2;111;122;0m▄\x1b[0m\x1b[38;2;126;158;0;48;2;97;122;0m▄\x1b[0m\x1b[38;2;109;158;0;48;2;84;122;0m▄\x1b[0m\x1b[38;2;91;158;0;48;2;71;122;0m▄\x1b[0m\x1b[38;2;74;158;0;48;2;57;122;0m▄\x1b[0m\x1b[38;2;57;158;0;48;2;44;122;0m▄\x1b[0m\x1b[38;2;40;158;0;48;2;31;122;0m▄\x1b[0m\x1b[38;2;22;158;0;48;2;17;122;0m▄\x1b[0m\x1b[38;2;5;158;0;48;2;4;122;0m▄\x1b[0m\x1b[38;2;0;158;11;48;2;0;122;8m▄\x1b[0m\x1b[38;2;0;158;28;48;2;0;122;22m▄\x1b[0m\x1b[38;2;0;158;45;48;2;0;122;35m▄\x1b[0m\x1b[38;2;0;158;63;48;2;0;122;48m▄\x1b[0m\x1b[38;2;0;158;80;48;2;0;122;62m▄\x1b[0m\x1b[38;2;0;158;97;48;2;0;122;75m▄\x1b[0m\x1b[38;2;0;158;114;48;2;0;122;89m▄\x1b[0m\x1b[38;2;0;158;132;48;2;0;122;102m▄\x1b[0m\x1b[38;2;0;158;149;48;2;0;122;115m▄\x1b[0m\x1b[38;2;0;149;158;48;2;0;115;122m▄\x1b[0m\x1b[38;2;0;132;158;48;2;0;102;122m▄\x1b[0m\x1b[38;2;0;114;158;48;2;0;89;122m▄\x1b[0m\x1b[38;2;0;97;158;48;2;0;75;122m▄\x1b[0m\x1b[38;2;0;80;158;48;2;0;62;122m▄\x1b[0m\x1b[38;2;0;63;158;48;2;0;48;122m▄\x1b[0m\x1b[38;2;0;45;158;48;2;0;35;122m▄\x1b[0m\x1b[38;2;0;28;158;48;2;0;22;122m▄\x1b[0m\x1b[38;2;0;11;158;48;2;0;8;122m▄\x1b[0m\x1b[38;2;5;0;158;48;2;4;0;122m▄\x1b[0m\x1b[38;2;22;0;158;48;2;17;0;122m▄\x1b[0m\x1b[38;2;40;0;158;48;2;31;0;122m▄\x1b[0m\x1b[38;2;57;0;158;48;2;44;0;122m▄\x1b[0m\x1b[38;2;74;0;158;48;2;57;0;122m▄\x1b[0m\x1b[38;2;91;0;158;48;2;71;0;122m▄\x1b[0m\x1b[38;2;109;0;158;48;2;84;0;122m▄\x1b[0m\x1b[38;2;126;0;158;48;2;97;0;122m▄\x1b[0m\x1b[38;2;143;0;158;48;2;111;0;122m▄\x1b[0m\x1b[38;2;158;0;155;48;2;122;0;120m▄\x1b[0m\x1b[38;2;158;0;137;48;2;122;0;106m▄\x1b[0m\x1b[38;2;158;0;120;48;2;122;0;93m▄\x1b[0m\x1b[38;2;158;0;103;48;2;122;0;80m▄\x1b[0m\x1b[38;2;158;0;86;48;2;122;0;66m▄\x1b[0m\x1b[38;2;158;0;68;48;2;122;0;53m▄\x1b[0m\x1b[38;2;158;0;51;48;2;122;0;40m▄\x1b[0m\x1b[38;2;158;0;34;48;2;122;0;26m▄\x1b[0m\x1b[38;2;158;0;17;48;2;122;0;13m▄\x1b[0m \n ✓ \x1b[1;35mTruecolor (16.7 million)\x1b[0m \x1b[38;2;229;0;0;48;2;193;0;0m▄\x1b[0m\x1b[38;2;229;25;0;48;2;193;21;0m▄\x1b[0m\x1b[38;2;229;50;0;48;2;193;42;0m▄\x1b[0m\x1b[38;2;229;75;0;48;2;193;63;0m▄\x1b[0m\x1b[38;2;229;100;0;48;2;193;84;0m▄\x1b[0m\x1b[38;2;229;125;0;48;2;193;105;0m▄\x1b[0m\x1b[38;2;229;150;0;48;2;193;126;0m▄\x1b[0m\x1b[38;2;229;175;0;48;2;193;147;0m▄\x1b[0m\x1b[38;2;229;200;0;48;2;193;169;0m▄\x1b[0m\x1b[38;2;229;225;0;48;2;193;190;0m▄\x1b[0m\x1b[38;2;208;229;0;48;2;176;193;0m▄\x1b[0m\x1b[38;2;183;229;0;48;2;155;193;0m▄\x1b[0m\x1b[38;2;158;229;0;48;2;133;193;0m▄\x1b[0m\x1b[38;2;133;229;0;48;2;112;193;0m▄\x1b[0m\x1b[38;2;108;229;0;48;2;91;193;0m▄\x1b[0m\x1b[38;2;83;229;0;48;2;70;193;0m▄\x1b[0m\x1b[38;2;58;229;0;48;2;49;193;0m▄\x1b[0m\x1b[38;2;33;229;0;48;2;28;193;0m▄\x1b[0m\x1b[38;2;8;229;0;48;2;7;193;0m▄\x1b[0m\x1b[38;2;0;229;16;48;2;0;193;14m▄\x1b[0m\x1b[38;2;0;229;41;48;2;0;193;35m▄\x1b[0m\x1b[38;2;0;229;66;48;2;0;193;56m▄\x1b[0m\x1b[38;2;0;229;91;48;2;0;193;77m▄\x1b[0m\x1b[38;2;0;229;116;48;2;0;193;98m▄\x1b[0m\x1b[38;2;0;229;141;48;2;0;193;119m▄\x1b[0m\x1b[38;2;0;229;166;48;2;0;193;140m▄\x1b[0m\x1b[38;2;0;229;191;48;2;0;193;162m▄\x1b[0m\x1b[38;2;0;229;216;48;2;0;193;183m▄\x1b[0m\x1b[38;2;0;216;229;48;2;0;183;193m▄\x1b[0m\x1b[38;2;0;191;229;48;2;0;162;193m▄\x1b[0m\x1b[38;2;0;166;229;48;2;0;140;193m▄\x1b[0m\x1b[38;2;0;141;229;48;2;0;119;193m▄\x1b[0m\x1b[38;2;0;116;229;48;2;0;98;193m▄\x1b[0m\x1b[38;2;0;91;229;48;2;0;77;193m▄\x1b[0m\x1b[38;2;0;66;229;48;2;0;56;193m▄\x1b[0m\x1b[38;2;0;41;229;48;2;0;35;193m▄\x1b[0m\x1b[38;2;0;16;229;48;2;0;14;193m▄\x1b[0m\x1b[38;2;8;0;229;48;2;7;0;193m▄\x1b[0m\x1b[38;2;33;0;229;48;2;28;0;193m▄\x1b[0m\x1b[38;2;58;0;229;48;2;49;0;193m▄\x1b[0m\x1b[38;2;83;0;229;48;2;70;0;193m▄\x1b[0m\x1b[38;2;108;0;229;48;2;91;0;193m▄\x1b[0m\x1b[38;2;133;0;229;48;2;112;0;193m▄\x1b[0m\x1b[38;2;158;0;229;48;2;133;0;193m▄\x1b[0m\x1b[38;2;183;0;229;48;2;155;0;193m▄\x1b[0m\x1b[38;2;208;0;229;48;2;176;0;193m▄\x1b[0m\x1b[38;2;229;0;225;48;2;193;0;190m▄\x1b[0m\x1b[38;2;229;0;200;48;2;193;0;169m▄\x1b[0m\x1b[38;2;229;0;175;48;2;193;0;147m▄\x1b[0m\x1b[38;2;229;0;150;48;2;193;0;126m▄\x1b[0m\x1b[38;2;229;0;125;48;2;193;0;105m▄\x1b[0m\x1b[38;2;229;0;100;48;2;193;0;84m▄\x1b[0m\x1b[38;2;229;0;75;48;2;193;0;63m▄\x1b[0m\x1b[38;2;229;0;50;48;2;193;0;42m▄\x1b[0m\x1b[38;2;229;0;25;48;2;193;0;21m▄\x1b[0m \n ✓ \x1b[1;33mDumb terminals\x1b[0m \x1b[38;2;254;45;45;48;2;255;10;10m▄\x1b[0m\x1b[38;2;254;68;45;48;2;255;36;10m▄\x1b[0m\x1b[38;2;254;91;45;48;2;255;63;10m▄\x1b[0m\x1b[38;2;254;114;45;48;2;255;90;10m▄\x1b[0m\x1b[38;2;254;137;45;48;2;255;117;10m▄\x1b[0m\x1b[38;2;254;159;45;48;2;255;143;10m▄\x1b[0m\x1b[38;2;254;182;45;48;2;255;170;10m▄\x1b[0m\x1b[38;2;254;205;45;48;2;255;197;10m▄\x1b[0m\x1b[38;2;254;228;45;48;2;255;223;10m▄\x1b[0m\x1b[38;2;254;251;45;48;2;255;250;10m▄\x1b[0m\x1b[38;2;235;254;45;48;2;232;255;10m▄\x1b[0m\x1b[38;2;213;254;45;48;2;206;255;10m▄\x1b[0m\x1b[38;2;190;254;45;48;2;179;255;10m▄\x1b[0m\x1b[38;2;167;254;45;48;2;152;255;10m▄\x1b[0m\x1b[38;2;144;254;45;48;2;125;255;10m▄\x1b[0m\x1b[38;2;121;254;45;48;2;99;255;10m▄\x1b[0m\x1b[38;2;99;254;45;48;2;72;255;10m▄\x1b[0m\x1b[38;2;76;254;45;48;2;45;255;10m▄\x1b[0m\x1b[38;2;53;254;45;48;2;19;255;10m▄\x1b[0m\x1b[38;2;45;254;61;48;2;10;255;28m▄\x1b[0m\x1b[38;2;45;254;83;48;2;10;255;54m▄\x1b[0m\x1b[38;2;45;254;106;48;2;10;255;81m▄\x1b[0m\x1b[38;2;45;254;129;48;2;10;255;108m▄\x1b[0m\x1b[38;2;45;254;152;48;2;10;255;134m▄\x1b[0m\x1b[38;2;45;254;175;48;2;10;255;161m▄\x1b[0m\x1b[38;2;45;254;197;48;2;10;255;188m▄\x1b[0m\x1b[38;2;45;254;220;48;2;10;255;214m▄\x1b[0m\x1b[38;2;45;254;243;48;2;10;255;241m▄\x1b[0m\x1b[38;2;45;243;254;48;2;10;241;255m▄\x1b[0m\x1b[38;2;45;220;254;48;2;10;214;255m▄\x1b[0m\x1b[38;2;45;197;254;48;2;10;188;255m▄\x1b[0m\x1b[38;2;45;175;254;48;2;10;161;255m▄\x1b[0m\x1b[38;2;45;152;254;48;2;10;134;255m▄\x1b[0m\x1b[38;2;45;129;254;48;2;10;108;255m▄\x1b[0m\x1b[38;2;45;106;254;48;2;10;81;255m▄\x1b[0m\x1b[38;2;45;83;254;48;2;10;54;255m▄\x1b[0m\x1b[38;2;45;61;254;48;2;10;28;255m▄\x1b[0m\x1b[38;2;53;45;254;48;2;19;10;255m▄\x1b[0m\x1b[38;2;76;45;254;48;2;45;10;255m▄\x1b[0m\x1b[38;2;99;45;254;48;2;72;10;255m▄\x1b[0m\x1b[38;2;121;45;254;48;2;99;10;255m▄\x1b[0m\x1b[38;2;144;45;254;48;2;125;10;255m▄\x1b[0m\x1b[38;2;167;45;254;48;2;152;10;255m▄\x1b[0m\x1b[38;2;190;45;254;48;2;179;10;255m▄\x1b[0m\x1b[38;2;213;45;254;48;2;206;10;255m▄\x1b[0m\x1b[38;2;235;45;254;48;2;232;10;255m▄\x1b[0m\x1b[38;2;254;45;251;48;2;255;10;250m▄\x1b[0m\x1b[38;2;254;45;228;48;2;255;10;223m▄\x1b[0m\x1b[38;2;254;45;205;48;2;255;10;197m▄\x1b[0m\x1b[38;2;254;45;182;48;2;255;10;170m▄\x1b[0m\x1b[38;2;254;45;159;48;2;255;10;143m▄\x1b[0m\x1b[38;2;254;45;137;48;2;255;10;117m▄\x1b[0m\x1b[38;2;254;45;114;48;2;255;10;90m▄\x1b[0m\x1b[38;2;254;45;91;48;2;255;10;63m▄\x1b[0m\x1b[38;2;254;45;68;48;2;255;10;36m▄\x1b[0m \n ✓ \x1b[1;36mAutomatic color conversion\x1b[0m \x1b[38;2;255;117;117;48;2;255;81;81m▄\x1b[0m\x1b[38;2;255;132;117;48;2;255;100;81m▄\x1b[0m\x1b[38;2;255;147;117;48;2;255;119;81m▄\x1b[0m\x1b[38;2;255;162;117;48;2;255;138;81m▄\x1b[0m\x1b[38;2;255;177;117;48;2;255;157;81m▄\x1b[0m\x1b[38;2;255;192;117;48;2;255;176;81m▄\x1b[0m\x1b[38;2;255;207;117;48;2;255;195;81m▄\x1b[0m\x1b[38;2;255;222;117;48;2;255;214;81m▄\x1b[0m\x1b[38;2;255;237;117;48;2;255;232;81m▄\x1b[0m\x1b[38;2;255;252;117;48;2;255;251;81m▄\x1b[0m\x1b[38;2;242;255;117;48;2;239;255;81m▄\x1b[0m\x1b[38;2;227;255;117;48;2;220;255;81m▄\x1b[0m\x1b[38;2;212;255;117;48;2;201;255;81m▄\x1b[0m\x1b[38;2;197;255;117;48;2;182;255;81m▄\x1b[0m\x1b[38;2;182;255;117;48;2;163;255;81m▄\x1b[0m\x1b[38;2;167;255;117;48;2;144;255;81m▄\x1b[0m\x1b[38;2;152;255;117;48;2;125;255;81m▄\x1b[0m\x1b[38;2;137;255;117;48;2;106;255;81m▄\x1b[0m\x1b[38;2;122;255;117;48;2;87;255;81m▄\x1b[0m\x1b[38;2;117;255;127;48;2;81;255;94m▄\x1b[0m\x1b[38;2;117;255;142;48;2;81;255;113m▄\x1b[0m\x1b[38;2;117;255;157;48;2;81;255;132m▄\x1b[0m\x1b[38;2;117;255;172;48;2;81;255;150m▄\x1b[0m\x1b[38;2;117;255;187;48;2;81;255;169m▄\x1b[0m\x1b[38;2;117;255;202;48;2;81;255;188m▄\x1b[0m\x1b[38;2;117;255;217;48;2;81;255;207m▄\x1b[0m\x1b[38;2;117;255;232;48;2;81;255;226m▄\x1b[0m\x1b[38;2;117;255;247;48;2;81;255;245m▄\x1b[0m\x1b[38;2;117;247;255;48;2;81;245;255m▄\x1b[0m\x1b[38;2;117;232;255;48;2;81;226;255m▄\x1b[0m\x1b[38;2;117;217;255;48;2;81;207;255m▄\x1b[0m\x1b[38;2;117;202;255;48;2;81;188;255m▄\x1b[0m\x1b[38;2;117;187;255;48;2;81;169;255m▄\x1b[0m\x1b[38;2;117;172;255;48;2;81;150;255m▄\x1b[0m\x1b[38;2;117;157;255;48;2;81;132;255m▄\x1b[0m\x1b[38;2;117;142;255;48;2;81;113;255m▄\x1b[0m\x1b[38;2;117;127;255;48;2;81;94;255m▄\x1b[0m\x1b[38;2;122;117;255;48;2;87;81;255m▄\x1b[0m\x1b[38;2;137;117;255;48;2;106;81;255m▄\x1b[0m\x1b[38;2;152;117;255;48;2;125;81;255m▄\x1b[0m\x1b[38;2;167;117;255;48;2;144;81;255m▄\x1b[0m\x1b[38;2;182;117;255;48;2;163;81;255m▄\x1b[0m\x1b[38;2;197;117;255;48;2;182;81;255m▄\x1b[0m\x1b[38;2;212;117;255;48;2;201;81;255m▄\x1b[0m\x1b[38;2;227;117;255;48;2;220;81;255m▄\x1b[0m\x1b[38;2;242;117;255;48;2;239;81;255m▄\x1b[0m\x1b[38;2;255;117;252;48;2;255;81;251m▄\x1b[0m\x1b[38;2;255;117;237;48;2;255;81;232m▄\x1b[0m\x1b[38;2;255;117;222;48;2;255;81;214m▄\x1b[0m\x1b[38;2;255;117;207;48;2;255;81;195m▄\x1b[0m\x1b[38;2;255;117;192;48;2;255;81;176m▄\x1b[0m\x1b[38;2;255;117;177;48;2;255;81;157m▄\x1b[0m\x1b[38;2;255;117;162;48;2;255;81;138m▄\x1b[0m\x1b[38;2;255;117;147;48;2;255;81;119m▄\x1b[0m\x1b[38;2;255;117;132;48;2;255;81;100m▄\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Styles \x1b[0m\x1b[1;31m \x1b[0mAll ansi styles: \x1b[1mbold\x1b[0m, \x1b[2mdim\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[4munderline\x1b[0m, \x1b[9mstrikethrough\x1b[0m, \x1b[7mreverse\x1b[0m, and even \n \x1b[5mblink\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Text \x1b[0m\x1b[1;31m \x1b[0mWord wrap text. Justify \x1b[32mleft\x1b[0m, \x1b[33mcenter\x1b[0m, \x1b[34mright\x1b[0m or \x1b[31mfull\x1b[0m. \n \n \x1b[32mLorem ipsum dolor \x1b[0m \x1b[33m Lorem ipsum dolor \x1b[0m \x1b[34m Lorem ipsum dolor\x1b[0m \x1b[31mLorem\x1b[0m\x1b[31m \x1b[0m\x1b[31mipsum\x1b[0m\x1b[31m \x1b[0m\x1b[31mdolor\x1b[0m\x1b[31m \x1b[0m\x1b[31msit\x1b[0m \n \x1b[32msit amet, \x1b[0m \x1b[33m sit amet, \x1b[0m \x1b[34m sit amet,\x1b[0m \x1b[31mamet,\x1b[0m\x1b[31m \x1b[0m\x1b[31mconsectetur\x1b[0m \n \x1b[32mconsectetur \x1b[0m \x1b[33m consectetur \x1b[0m \x1b[34m consectetur\x1b[0m \x1b[31madipiscing\x1b[0m\x1b[31m \x1b[0m\x1b[31melit.\x1b[0m \n \x1b[32madipiscing elit. \x1b[0m \x1b[33m adipiscing elit. \x1b[0m \x1b[34m adipiscing elit.\x1b[0m \x1b[31mQuisque\x1b[0m\x1b[31m \x1b[0m\x1b[31min\x1b[0m\x1b[31m \x1b[0m\x1b[31mmetus\x1b[0m\x1b[31m \x1b[0m\x1b[31msed\x1b[0m \n \x1b[32mQuisque in metus sed\x1b[0m \x1b[33mQuisque in metus sed\x1b[0m \x1b[34mQuisque in metus sed\x1b[0m \x1b[31msapien\x1b[0m\x1b[31m \x1b[0m\x1b[31multricies\x1b[0m \n \x1b[32msapien ultricies \x1b[0m \x1b[33m sapien ultricies \x1b[0m \x1b[34m sapien ultricies\x1b[0m \x1b[31mpretium\x1b[0m\x1b[31m \x1b[0m\x1b[31ma\x1b[0m\x1b[31m \x1b[0m\x1b[31mat\x1b[0m\x1b[31m \x1b[0m\x1b[31mjusto.\x1b[0m \n \x1b[32mpretium a at justo. \x1b[0m \x1b[33mpretium a at justo. \x1b[0m \x1b[34m pretium a at justo.\x1b[0m \x1b[31mMaecenas\x1b[0m\x1b[31m \x1b[0m\x1b[31mluctus\x1b[0m\x1b[31m \x1b[0m\x1b[31mvelit\x1b[0m \n \x1b[32mMaecenas luctus \x1b[0m \x1b[33m Maecenas luctus \x1b[0m \x1b[34m Maecenas luctus\x1b[0m \x1b[31met auctor maximus.\x1b[0m \n \x1b[32mvelit et auctor \x1b[0m \x1b[33m velit et auctor \x1b[0m \x1b[34m velit et auctor\x1b[0m \n \x1b[32mmaximus. \x1b[0m \x1b[33m maximus. \x1b[0m \x1b[34m maximus.\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Asian \x1b[0m\x1b[1;31m \x1b[0m🇨🇳 该库支持中文,日文和韩文文本! \n\x1b[1;31m \x1b[0m\x1b[1;31m language \x1b[0m\x1b[1;31m \x1b[0m🇯🇵 ライブラリは中国語、日本語、韓国語のテキストをサポートしています \n\x1b[1;31m \x1b[0m\x1b[1;31m support \x1b[0m\x1b[1;31m \x1b[0m🇰🇷 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markup \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;35mRich\x1b[0m supports a simple \x1b[3mbbcode\x1b[0m-like \x1b[1mmarkup\x1b[0m for \x1b[33mcolor\x1b[0m, \x1b[4mstyle\x1b[0m, and emoji! 👍 🍎 🐜 🐻 … \n 🚌 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Tables \x1b[0m\x1b[1;31m \x1b[0m\x1b[1m \x1b[0m\x1b[1;32mDate\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;34mTitle\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;36mProduction Budget\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m \x1b[0m\x1b[1;35mBox Office\x1b[0m\x1b[1m \x1b[0m \n ───────────────────────────────────────────────────────────────────────────────────── \n \x1b[32m \x1b[0m\x1b[32mDec 20, 2019\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars: The Rise of \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $275,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[35m $375,126,118\x1b[0m\x1b[35m \x1b[0m \n \x1b[34m \x1b[0m\x1b[34mSkywalker \x1b[0m\x1b[34m \x1b[0m \n \x1b[2;32m \x1b[0m\x1b[2;32mMay 25, 2018\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[1;2;34mSolo\x1b[0m\x1b[2;34m: A Star Wars Story \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $275,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m $393,151,347\x1b[0m\x1b[2;35m \x1b[0m \n \x1b[32m \x1b[0m\x1b[32mDec 15, 2017\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars Ep. VIII: The Last \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $262,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[1;35m$1,332,539,889\x1b[0m\x1b[35m \x1b[0m \n \x1b[34m \x1b[0m\x1b[34mJedi \x1b[0m\x1b[34m \x1b[0m \n \x1b[2;32m \x1b[0m\x1b[2;32mMay 19, 1999\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;34mStar Wars Ep. \x1b[0m\x1b[1;2;34mI\x1b[0m\x1b[2;34m: \x1b[0m\x1b[2;3;34mThe phantom \x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $115,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m$1,027,044,677\x1b[0m\x1b[2;35m \x1b[0m \n \x1b[2m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;3;34mMenace\x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2m \x1b[0m \x1b[2m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Syntax \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 1 \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34miter_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m \x1b[1m{\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31mhighlighting\x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m\"""Iterate and generate a tuple w\x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m\'foo\'\x1b[0m: \x1b[1m[\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m & \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1;36m3.1427\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;31m pretty \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m(\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m printing \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_va\x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m\'Paul Atreides\'\x1b[0m, \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m\'Vladimir Harkonnen\'\x1b[0m, \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m\'Thufir Hawat\'\x1b[0m \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m)\x1b[0m \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[1m]\x1b[0m, \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m\'atomic\'\x1b[0m: \x1b[1m(\x1b[0m\x1b[3;91mFalse\x1b[0m, \x1b[3;92mTrue\x1b[0m, \x1b[3;35mNone\x1b[0m\x1b[1m)\x1b[0m \n \x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m11 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[1m}\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markdown \x1b[0m\x1b[1;31m \x1b[0m\x1b[36m# Markdown\x1b[0m ╔═══════════════════════════════════════╗ \n ║ \x1b[1mMarkdown\x1b[0m ║ \n \x1b[36mSupports much of the *markdown* \x1b[0m ╚═══════════════════════════════════════╝ \n \x1b[36m__syntax__!\x1b[0m \n Supports much of the \x1b[3mmarkdown\x1b[0m \x1b[1msyntax\x1b[0m! \n \x1b[36m- Headers\x1b[0m \n \x1b[36m- Basic formatting: **bold**, *italic*, \x1b[0m \x1b[1;33m • \x1b[0mHeaders \n \x1b[36m`code`\x1b[0m \x1b[1;33m • \x1b[0mBasic formatting: \x1b[1mbold\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[97;40mcode\x1b[0m \n \x1b[36m- Block quotes\x1b[0m \x1b[1;33m • \x1b[0mBlock quotes \n \x1b[36m- Lists, and more...\x1b[0m \x1b[1;33m • \x1b[0mLists, and more... \n \x1b[36m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m +more! \x1b[0m\x1b[1;31m \x1b[0mProgress bars, columns, styled logging handler, tracebacks, etc... \n\x1b[1;31m \x1b[0m \n""" +expected = "\x1b[3m Rich features \x1b[0m\n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Colors \x1b[0m\x1b[1;31m \x1b[0m✓ \x1b[1;32m4-bit color\x1b[0m \x1b[38;2;86;0;0;48;2;51;0;0m▄\x1b[0m\x1b[38;2;86;9;0;48;2;51;5;0m▄\x1b[0m\x1b[38;2;86;18;0;48;2;51;11;0m▄\x1b[0m\x1b[38;2;86;28;0;48;2;51;16;0m▄\x1b[0m\x1b[38;2;86;37;0;48;2;51;22;0m▄\x1b[0m\x1b[38;2;86;47;0;48;2;51;27;0m▄\x1b[0m\x1b[38;2;86;56;0;48;2;51;33;0m▄\x1b[0m\x1b[38;2;86;66;0;48;2;51;38;0m▄\x1b[0m\x1b[38;2;86;75;0;48;2;51;44;0m▄\x1b[0m\x1b[38;2;86;85;0;48;2;51;50;0m▄\x1b[0m\x1b[38;2;78;86;0;48;2;46;51;0m▄\x1b[0m\x1b[38;2;69;86;0;48;2;40;51;0m▄\x1b[0m\x1b[38;2;59;86;0;48;2;35;51;0m▄\x1b[0m\x1b[38;2;50;86;0;48;2;29;51;0m▄\x1b[0m\x1b[38;2;40;86;0;48;2;24;51;0m▄\x1b[0m\x1b[38;2;31;86;0;48;2;18;51;0m▄\x1b[0m\x1b[38;2;22;86;0;48;2;12;51;0m▄\x1b[0m\x1b[38;2;12;86;0;48;2;7;51;0m▄\x1b[0m\x1b[38;2;3;86;0;48;2;1;51;0m▄\x1b[0m\x1b[38;2;0;86;6;48;2;0;51;3m▄\x1b[0m\x1b[38;2;0;86;15;48;2;0;51;9m▄\x1b[0m\x1b[38;2;0;86;25;48;2;0;51;14m▄\x1b[0m\x1b[38;2;0;86;34;48;2;0;51;20m▄\x1b[0m\x1b[38;2;0;86;44;48;2;0;51;25m▄\x1b[0m\x1b[38;2;0;86;53;48;2;0;51;31m▄\x1b[0m\x1b[38;2;0;86;63;48;2;0;51;37m▄\x1b[0m\x1b[38;2;0;86;72;48;2;0;51;42m▄\x1b[0m\x1b[38;2;0;86;81;48;2;0;51;48m▄\x1b[0m\x1b[38;2;0;81;86;48;2;0;48;51m▄\x1b[0m\x1b[38;2;0;72;86;48;2;0;42;51m▄\x1b[0m\x1b[38;2;0;63;86;48;2;0;37;51m▄\x1b[0m\x1b[38;2;0;53;86;48;2;0;31;51m▄\x1b[0m\x1b[38;2;0;44;86;48;2;0;25;51m▄\x1b[0m\x1b[38;2;0;34;86;48;2;0;20;51m▄\x1b[0m\x1b[38;2;0;25;86;48;2;0;14;51m▄\x1b[0m\x1b[38;2;0;15;86;48;2;0;9;51m▄\x1b[0m\x1b[38;2;0;6;86;48;2;0;3;51m▄\x1b[0m\x1b[38;2;3;0;86;48;2;1;0;51m▄\x1b[0m\x1b[38;2;12;0;86;48;2;7;0;51m▄\x1b[0m\x1b[38;2;22;0;86;48;2;12;0;51m▄\x1b[0m\x1b[38;2;31;0;86;48;2;18;0;51m▄\x1b[0m\x1b[38;2;40;0;86;48;2;24;0;51m▄\x1b[0m\x1b[38;2;50;0;86;48;2;29;0;51m▄\x1b[0m\x1b[38;2;59;0;86;48;2;35;0;51m▄\x1b[0m\x1b[38;2;69;0;86;48;2;40;0;51m▄\x1b[0m\x1b[38;2;78;0;86;48;2;46;0;51m▄\x1b[0m\x1b[38;2;86;0;85;48;2;51;0;50m▄\x1b[0m\x1b[38;2;86;0;75;48;2;51;0;44m▄\x1b[0m\x1b[38;2;86;0;66;48;2;51;0;38m▄\x1b[0m\x1b[38;2;86;0;56;48;2;51;0;33m▄\x1b[0m\x1b[38;2;86;0;47;48;2;51;0;27m▄\x1b[0m\x1b[38;2;86;0;37;48;2;51;0;22m▄\x1b[0m\x1b[38;2;86;0;28;48;2;51;0;16m▄\x1b[0m\x1b[38;2;86;0;18;48;2;51;0;11m▄\x1b[0m\x1b[38;2;86;0;9;48;2;51;0;5m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;34m8-bit color\x1b[0m \x1b[38;2;158;0;0;48;2;122;0;0m▄\x1b[0m\x1b[38;2;158;17;0;48;2;122;13;0m▄\x1b[0m\x1b[38;2;158;34;0;48;2;122;26;0m▄\x1b[0m\x1b[38;2;158;51;0;48;2;122;40;0m▄\x1b[0m\x1b[38;2;158;68;0;48;2;122;53;0m▄\x1b[0m\x1b[38;2;158;86;0;48;2;122;66;0m▄\x1b[0m\x1b[38;2;158;103;0;48;2;122;80;0m▄\x1b[0m\x1b[38;2;158;120;0;48;2;122;93;0m▄\x1b[0m\x1b[38;2;158;137;0;48;2;122;106;0m▄\x1b[0m\x1b[38;2;158;155;0;48;2;122;120;0m▄\x1b[0m\x1b[38;2;143;158;0;48;2;111;122;0m▄\x1b[0m\x1b[38;2;126;158;0;48;2;97;122;0m▄\x1b[0m\x1b[38;2;109;158;0;48;2;84;122;0m▄\x1b[0m\x1b[38;2;91;158;0;48;2;71;122;0m▄\x1b[0m\x1b[38;2;74;158;0;48;2;57;122;0m▄\x1b[0m\x1b[38;2;57;158;0;48;2;44;122;0m▄\x1b[0m\x1b[38;2;40;158;0;48;2;31;122;0m▄\x1b[0m\x1b[38;2;22;158;0;48;2;17;122;0m▄\x1b[0m\x1b[38;2;5;158;0;48;2;4;122;0m▄\x1b[0m\x1b[38;2;0;158;11;48;2;0;122;8m▄\x1b[0m\x1b[38;2;0;158;28;48;2;0;122;22m▄\x1b[0m\x1b[38;2;0;158;45;48;2;0;122;35m▄\x1b[0m\x1b[38;2;0;158;63;48;2;0;122;48m▄\x1b[0m\x1b[38;2;0;158;80;48;2;0;122;62m▄\x1b[0m\x1b[38;2;0;158;97;48;2;0;122;75m▄\x1b[0m\x1b[38;2;0;158;114;48;2;0;122;89m▄\x1b[0m\x1b[38;2;0;158;132;48;2;0;122;102m▄\x1b[0m\x1b[38;2;0;158;149;48;2;0;122;115m▄\x1b[0m\x1b[38;2;0;149;158;48;2;0;115;122m▄\x1b[0m\x1b[38;2;0;132;158;48;2;0;102;122m▄\x1b[0m\x1b[38;2;0;114;158;48;2;0;89;122m▄\x1b[0m\x1b[38;2;0;97;158;48;2;0;75;122m▄\x1b[0m\x1b[38;2;0;80;158;48;2;0;62;122m▄\x1b[0m\x1b[38;2;0;63;158;48;2;0;48;122m▄\x1b[0m\x1b[38;2;0;45;158;48;2;0;35;122m▄\x1b[0m\x1b[38;2;0;28;158;48;2;0;22;122m▄\x1b[0m\x1b[38;2;0;11;158;48;2;0;8;122m▄\x1b[0m\x1b[38;2;5;0;158;48;2;4;0;122m▄\x1b[0m\x1b[38;2;22;0;158;48;2;17;0;122m▄\x1b[0m\x1b[38;2;40;0;158;48;2;31;0;122m▄\x1b[0m\x1b[38;2;57;0;158;48;2;44;0;122m▄\x1b[0m\x1b[38;2;74;0;158;48;2;57;0;122m▄\x1b[0m\x1b[38;2;91;0;158;48;2;71;0;122m▄\x1b[0m\x1b[38;2;109;0;158;48;2;84;0;122m▄\x1b[0m\x1b[38;2;126;0;158;48;2;97;0;122m▄\x1b[0m\x1b[38;2;143;0;158;48;2;111;0;122m▄\x1b[0m\x1b[38;2;158;0;155;48;2;122;0;120m▄\x1b[0m\x1b[38;2;158;0;137;48;2;122;0;106m▄\x1b[0m\x1b[38;2;158;0;120;48;2;122;0;93m▄\x1b[0m\x1b[38;2;158;0;103;48;2;122;0;80m▄\x1b[0m\x1b[38;2;158;0;86;48;2;122;0;66m▄\x1b[0m\x1b[38;2;158;0;68;48;2;122;0;53m▄\x1b[0m\x1b[38;2;158;0;51;48;2;122;0;40m▄\x1b[0m\x1b[38;2;158;0;34;48;2;122;0;26m▄\x1b[0m\x1b[38;2;158;0;17;48;2;122;0;13m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;35mTruecolor (16.7 million)\x1b[0m \x1b[38;2;229;0;0;48;2;193;0;0m▄\x1b[0m\x1b[38;2;229;25;0;48;2;193;21;0m▄\x1b[0m\x1b[38;2;229;50;0;48;2;193;42;0m▄\x1b[0m\x1b[38;2;229;75;0;48;2;193;63;0m▄\x1b[0m\x1b[38;2;229;100;0;48;2;193;84;0m▄\x1b[0m\x1b[38;2;229;125;0;48;2;193;105;0m▄\x1b[0m\x1b[38;2;229;150;0;48;2;193;126;0m▄\x1b[0m\x1b[38;2;229;175;0;48;2;193;147;0m▄\x1b[0m\x1b[38;2;229;200;0;48;2;193;169;0m▄\x1b[0m\x1b[38;2;229;225;0;48;2;193;190;0m▄\x1b[0m\x1b[38;2;208;229;0;48;2;176;193;0m▄\x1b[0m\x1b[38;2;183;229;0;48;2;155;193;0m▄\x1b[0m\x1b[38;2;158;229;0;48;2;133;193;0m▄\x1b[0m\x1b[38;2;133;229;0;48;2;112;193;0m▄\x1b[0m\x1b[38;2;108;229;0;48;2;91;193;0m▄\x1b[0m\x1b[38;2;83;229;0;48;2;70;193;0m▄\x1b[0m\x1b[38;2;58;229;0;48;2;49;193;0m▄\x1b[0m\x1b[38;2;33;229;0;48;2;28;193;0m▄\x1b[0m\x1b[38;2;8;229;0;48;2;7;193;0m▄\x1b[0m\x1b[38;2;0;229;16;48;2;0;193;14m▄\x1b[0m\x1b[38;2;0;229;41;48;2;0;193;35m▄\x1b[0m\x1b[38;2;0;229;66;48;2;0;193;56m▄\x1b[0m\x1b[38;2;0;229;91;48;2;0;193;77m▄\x1b[0m\x1b[38;2;0;229;116;48;2;0;193;98m▄\x1b[0m\x1b[38;2;0;229;141;48;2;0;193;119m▄\x1b[0m\x1b[38;2;0;229;166;48;2;0;193;140m▄\x1b[0m\x1b[38;2;0;229;191;48;2;0;193;162m▄\x1b[0m\x1b[38;2;0;229;216;48;2;0;193;183m▄\x1b[0m\x1b[38;2;0;216;229;48;2;0;183;193m▄\x1b[0m\x1b[38;2;0;191;229;48;2;0;162;193m▄\x1b[0m\x1b[38;2;0;166;229;48;2;0;140;193m▄\x1b[0m\x1b[38;2;0;141;229;48;2;0;119;193m▄\x1b[0m\x1b[38;2;0;116;229;48;2;0;98;193m▄\x1b[0m\x1b[38;2;0;91;229;48;2;0;77;193m▄\x1b[0m\x1b[38;2;0;66;229;48;2;0;56;193m▄\x1b[0m\x1b[38;2;0;41;229;48;2;0;35;193m▄\x1b[0m\x1b[38;2;0;16;229;48;2;0;14;193m▄\x1b[0m\x1b[38;2;8;0;229;48;2;7;0;193m▄\x1b[0m\x1b[38;2;33;0;229;48;2;28;0;193m▄\x1b[0m\x1b[38;2;58;0;229;48;2;49;0;193m▄\x1b[0m\x1b[38;2;83;0;229;48;2;70;0;193m▄\x1b[0m\x1b[38;2;108;0;229;48;2;91;0;193m▄\x1b[0m\x1b[38;2;133;0;229;48;2;112;0;193m▄\x1b[0m\x1b[38;2;158;0;229;48;2;133;0;193m▄\x1b[0m\x1b[38;2;183;0;229;48;2;155;0;193m▄\x1b[0m\x1b[38;2;208;0;229;48;2;176;0;193m▄\x1b[0m\x1b[38;2;229;0;225;48;2;193;0;190m▄\x1b[0m\x1b[38;2;229;0;200;48;2;193;0;169m▄\x1b[0m\x1b[38;2;229;0;175;48;2;193;0;147m▄\x1b[0m\x1b[38;2;229;0;150;48;2;193;0;126m▄\x1b[0m\x1b[38;2;229;0;125;48;2;193;0;105m▄\x1b[0m\x1b[38;2;229;0;100;48;2;193;0;84m▄\x1b[0m\x1b[38;2;229;0;75;48;2;193;0;63m▄\x1b[0m\x1b[38;2;229;0;50;48;2;193;0;42m▄\x1b[0m\x1b[38;2;229;0;25;48;2;193;0;21m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;33mDumb terminals\x1b[0m \x1b[38;2;254;45;45;48;2;255;10;10m▄\x1b[0m\x1b[38;2;254;68;45;48;2;255;36;10m▄\x1b[0m\x1b[38;2;254;91;45;48;2;255;63;10m▄\x1b[0m\x1b[38;2;254;114;45;48;2;255;90;10m▄\x1b[0m\x1b[38;2;254;137;45;48;2;255;117;10m▄\x1b[0m\x1b[38;2;254;159;45;48;2;255;143;10m▄\x1b[0m\x1b[38;2;254;182;45;48;2;255;170;10m▄\x1b[0m\x1b[38;2;254;205;45;48;2;255;197;10m▄\x1b[0m\x1b[38;2;254;228;45;48;2;255;223;10m▄\x1b[0m\x1b[38;2;254;251;45;48;2;255;250;10m▄\x1b[0m\x1b[38;2;235;254;45;48;2;232;255;10m▄\x1b[0m\x1b[38;2;213;254;45;48;2;206;255;10m▄\x1b[0m\x1b[38;2;190;254;45;48;2;179;255;10m▄\x1b[0m\x1b[38;2;167;254;45;48;2;152;255;10m▄\x1b[0m\x1b[38;2;144;254;45;48;2;125;255;10m▄\x1b[0m\x1b[38;2;121;254;45;48;2;99;255;10m▄\x1b[0m\x1b[38;2;99;254;45;48;2;72;255;10m▄\x1b[0m\x1b[38;2;76;254;45;48;2;45;255;10m▄\x1b[0m\x1b[38;2;53;254;45;48;2;19;255;10m▄\x1b[0m\x1b[38;2;45;254;61;48;2;10;255;28m▄\x1b[0m\x1b[38;2;45;254;83;48;2;10;255;54m▄\x1b[0m\x1b[38;2;45;254;106;48;2;10;255;81m▄\x1b[0m\x1b[38;2;45;254;129;48;2;10;255;108m▄\x1b[0m\x1b[38;2;45;254;152;48;2;10;255;134m▄\x1b[0m\x1b[38;2;45;254;175;48;2;10;255;161m▄\x1b[0m\x1b[38;2;45;254;197;48;2;10;255;188m▄\x1b[0m\x1b[38;2;45;254;220;48;2;10;255;214m▄\x1b[0m\x1b[38;2;45;254;243;48;2;10;255;241m▄\x1b[0m\x1b[38;2;45;243;254;48;2;10;241;255m▄\x1b[0m\x1b[38;2;45;220;254;48;2;10;214;255m▄\x1b[0m\x1b[38;2;45;197;254;48;2;10;188;255m▄\x1b[0m\x1b[38;2;45;175;254;48;2;10;161;255m▄\x1b[0m\x1b[38;2;45;152;254;48;2;10;134;255m▄\x1b[0m\x1b[38;2;45;129;254;48;2;10;108;255m▄\x1b[0m\x1b[38;2;45;106;254;48;2;10;81;255m▄\x1b[0m\x1b[38;2;45;83;254;48;2;10;54;255m▄\x1b[0m\x1b[38;2;45;61;254;48;2;10;28;255m▄\x1b[0m\x1b[38;2;53;45;254;48;2;19;10;255m▄\x1b[0m\x1b[38;2;76;45;254;48;2;45;10;255m▄\x1b[0m\x1b[38;2;99;45;254;48;2;72;10;255m▄\x1b[0m\x1b[38;2;121;45;254;48;2;99;10;255m▄\x1b[0m\x1b[38;2;144;45;254;48;2;125;10;255m▄\x1b[0m\x1b[38;2;167;45;254;48;2;152;10;255m▄\x1b[0m\x1b[38;2;190;45;254;48;2;179;10;255m▄\x1b[0m\x1b[38;2;213;45;254;48;2;206;10;255m▄\x1b[0m\x1b[38;2;235;45;254;48;2;232;10;255m▄\x1b[0m\x1b[38;2;254;45;251;48;2;255;10;250m▄\x1b[0m\x1b[38;2;254;45;228;48;2;255;10;223m▄\x1b[0m\x1b[38;2;254;45;205;48;2;255;10;197m▄\x1b[0m\x1b[38;2;254;45;182;48;2;255;10;170m▄\x1b[0m\x1b[38;2;254;45;159;48;2;255;10;143m▄\x1b[0m\x1b[38;2;254;45;137;48;2;255;10;117m▄\x1b[0m\x1b[38;2;254;45;114;48;2;255;10;90m▄\x1b[0m\x1b[38;2;254;45;91;48;2;255;10;63m▄\x1b[0m\x1b[38;2;254;45;68;48;2;255;10;36m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;36mAutomatic color conversion\x1b[0m \x1b[38;2;255;117;117;48;2;255;81;81m▄\x1b[0m\x1b[38;2;255;132;117;48;2;255;100;81m▄\x1b[0m\x1b[38;2;255;147;117;48;2;255;119;81m▄\x1b[0m\x1b[38;2;255;162;117;48;2;255;138;81m▄\x1b[0m\x1b[38;2;255;177;117;48;2;255;157;81m▄\x1b[0m\x1b[38;2;255;192;117;48;2;255;176;81m▄\x1b[0m\x1b[38;2;255;207;117;48;2;255;195;81m▄\x1b[0m\x1b[38;2;255;222;117;48;2;255;214;81m▄\x1b[0m\x1b[38;2;255;237;117;48;2;255;232;81m▄\x1b[0m\x1b[38;2;255;252;117;48;2;255;251;81m▄\x1b[0m\x1b[38;2;242;255;117;48;2;239;255;81m▄\x1b[0m\x1b[38;2;227;255;117;48;2;220;255;81m▄\x1b[0m\x1b[38;2;212;255;117;48;2;201;255;81m▄\x1b[0m\x1b[38;2;197;255;117;48;2;182;255;81m▄\x1b[0m\x1b[38;2;182;255;117;48;2;163;255;81m▄\x1b[0m\x1b[38;2;167;255;117;48;2;144;255;81m▄\x1b[0m\x1b[38;2;152;255;117;48;2;125;255;81m▄\x1b[0m\x1b[38;2;137;255;117;48;2;106;255;81m▄\x1b[0m\x1b[38;2;122;255;117;48;2;87;255;81m▄\x1b[0m\x1b[38;2;117;255;127;48;2;81;255;94m▄\x1b[0m\x1b[38;2;117;255;142;48;2;81;255;113m▄\x1b[0m\x1b[38;2;117;255;157;48;2;81;255;132m▄\x1b[0m\x1b[38;2;117;255;172;48;2;81;255;150m▄\x1b[0m\x1b[38;2;117;255;187;48;2;81;255;169m▄\x1b[0m\x1b[38;2;117;255;202;48;2;81;255;188m▄\x1b[0m\x1b[38;2;117;255;217;48;2;81;255;207m▄\x1b[0m\x1b[38;2;117;255;232;48;2;81;255;226m▄\x1b[0m\x1b[38;2;117;255;247;48;2;81;255;245m▄\x1b[0m\x1b[38;2;117;247;255;48;2;81;245;255m▄\x1b[0m\x1b[38;2;117;232;255;48;2;81;226;255m▄\x1b[0m\x1b[38;2;117;217;255;48;2;81;207;255m▄\x1b[0m\x1b[38;2;117;202;255;48;2;81;188;255m▄\x1b[0m\x1b[38;2;117;187;255;48;2;81;169;255m▄\x1b[0m\x1b[38;2;117;172;255;48;2;81;150;255m▄\x1b[0m\x1b[38;2;117;157;255;48;2;81;132;255m▄\x1b[0m\x1b[38;2;117;142;255;48;2;81;113;255m▄\x1b[0m\x1b[38;2;117;127;255;48;2;81;94;255m▄\x1b[0m\x1b[38;2;122;117;255;48;2;87;81;255m▄\x1b[0m\x1b[38;2;137;117;255;48;2;106;81;255m▄\x1b[0m\x1b[38;2;152;117;255;48;2;125;81;255m▄\x1b[0m\x1b[38;2;167;117;255;48;2;144;81;255m▄\x1b[0m\x1b[38;2;182;117;255;48;2;163;81;255m▄\x1b[0m\x1b[38;2;197;117;255;48;2;182;81;255m▄\x1b[0m\x1b[38;2;212;117;255;48;2;201;81;255m▄\x1b[0m\x1b[38;2;227;117;255;48;2;220;81;255m▄\x1b[0m\x1b[38;2;242;117;255;48;2;239;81;255m▄\x1b[0m\x1b[38;2;255;117;252;48;2;255;81;251m▄\x1b[0m\x1b[38;2;255;117;237;48;2;255;81;232m▄\x1b[0m\x1b[38;2;255;117;222;48;2;255;81;214m▄\x1b[0m\x1b[38;2;255;117;207;48;2;255;81;195m▄\x1b[0m\x1b[38;2;255;117;192;48;2;255;81;176m▄\x1b[0m\x1b[38;2;255;117;177;48;2;255;81;157m▄\x1b[0m\x1b[38;2;255;117;162;48;2;255;81;138m▄\x1b[0m\x1b[38;2;255;117;147;48;2;255;81;119m▄\x1b[0m\x1b[38;2;255;117;132;48;2;255;81;100m▄\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Styles \x1b[0m\x1b[1;31m \x1b[0mAll ansi styles: \x1b[1mbold\x1b[0m, \x1b[2mdim\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[4munderline\x1b[0m, \x1b[9mstrikethrough\x1b[0m, \x1b[7mreverse\x1b[0m, and even \n\x1b[1;31m \x1b[0m\x1b[5mblink\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Text \x1b[0m\x1b[1;31m \x1b[0mWord wrap text. Justify \x1b[32mleft\x1b[0m, \x1b[33mcenter\x1b[0m, \x1b[34mright\x1b[0m or \x1b[31mfull\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mLorem ipsum dolor \x1b[0m \x1b[33m Lorem ipsum dolor \x1b[0m \x1b[34m Lorem ipsum dolor\x1b[0m \x1b[31mLorem\x1b[0m\x1b[31m \x1b[0m\x1b[31mipsum\x1b[0m\x1b[31m \x1b[0m\x1b[31mdolor\x1b[0m\x1b[31m \x1b[0m\x1b[31msit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msit amet, \x1b[0m \x1b[33m sit amet, \x1b[0m \x1b[34m sit amet,\x1b[0m \x1b[31mamet,\x1b[0m\x1b[31m \x1b[0m\x1b[31mconsectetur\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mconsectetur \x1b[0m \x1b[33m consectetur \x1b[0m \x1b[34m consectetur\x1b[0m \x1b[31madipiscing\x1b[0m\x1b[31m \x1b[0m\x1b[31melit.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32madipiscing elit. \x1b[0m \x1b[33m adipiscing elit. \x1b[0m \x1b[34m adipiscing elit.\x1b[0m \x1b[31mQuisque\x1b[0m\x1b[31m \x1b[0m\x1b[31min\x1b[0m\x1b[31m \x1b[0m\x1b[31mmetus\x1b[0m\x1b[31m \x1b[0m\x1b[31msed\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mQuisque in metus sed\x1b[0m \x1b[33mQuisque in metus sed\x1b[0m \x1b[34mQuisque in metus sed\x1b[0m \x1b[31msapien\x1b[0m\x1b[31m \x1b[0m\x1b[31multricies\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msapien ultricies \x1b[0m \x1b[33m sapien ultricies \x1b[0m \x1b[34m sapien ultricies\x1b[0m \x1b[31mpretium\x1b[0m\x1b[31m \x1b[0m\x1b[31ma\x1b[0m\x1b[31m \x1b[0m\x1b[31mat\x1b[0m\x1b[31m \x1b[0m\x1b[31mjusto.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mpretium a at justo. \x1b[0m \x1b[33mpretium a at justo. \x1b[0m \x1b[34m pretium a at justo.\x1b[0m \x1b[31mMaecenas\x1b[0m\x1b[31m \x1b[0m\x1b[31mluctus\x1b[0m\x1b[31m \x1b[0m\x1b[31mvelit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mMaecenas luctus \x1b[0m \x1b[33m Maecenas luctus \x1b[0m \x1b[34m Maecenas luctus\x1b[0m \x1b[31met auctor maximus.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mvelit et auctor \x1b[0m \x1b[33m velit et auctor \x1b[0m \x1b[34m velit et auctor\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mmaximus. \x1b[0m \x1b[33m maximus. \x1b[0m \x1b[34m maximus.\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Asian \x1b[0m\x1b[1;31m \x1b[0m🇨🇳 该库支持中文,日文和韩文文本! \n\x1b[1;31m \x1b[0m\x1b[1;31m language \x1b[0m\x1b[1;31m \x1b[0m🇯🇵 ライブラリは中国語、日本語、韓国語のテキストをサポートしています \n\x1b[1;31m \x1b[0m\x1b[1;31m support \x1b[0m\x1b[1;31m \x1b[0m🇰🇷 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markup \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;35mRich\x1b[0m supports a simple \x1b[3mbbcode\x1b[0m-like \x1b[1mmarkup\x1b[0m for \x1b[33mcolor\x1b[0m, \x1b[4mstyle\x1b[0m, and emoji! 👍 🍎 🐜 🐻 … \n\x1b[1;31m \x1b[0m🚌 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Tables \x1b[0m\x1b[1;31m \x1b[0m\x1b[1m \x1b[0m\x1b[1;32mDate\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;34mTitle\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;36mProduction Budget\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m \x1b[0m\x1b[1;35mBox Office\x1b[0m\x1b[1m \x1b[0m \n\x1b[1;31m \x1b[0m───────────────────────────────────────────────────────────────────────────────────── \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 20, 2019\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars: The Rise of \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $275,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[35m $375,126,118\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mSkywalker \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 25, 2018\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[1;2;34mSolo\x1b[0m\x1b[2;34m: A Star Wars Story \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $275,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m $393,151,347\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 15, 2017\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars Ep. VIII: The Last \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $262,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[1;35m$1,332,539,889\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mJedi \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 19, 1999\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;34mStar Wars Ep. \x1b[0m\x1b[1;2;34mI\x1b[0m\x1b[2;34m: \x1b[0m\x1b[2;3;34mThe phantom \x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $115,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m$1,027,044,677\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;3;34mMenace\x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Syntax \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 1 \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34miter_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m \x1b[1m{\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31mhighlighting\x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m\"\"\"Iterate and generate a tuple w\x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'foo'\x1b[0m: \x1b[1m[\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m & \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1;36m3.1427\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;31m pretty \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m(\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m printing \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_va\x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Paul Atreides'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Vladimir Harkonnen'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Thufir Hawat'\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[1m]\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'atomic'\x1b[0m: \x1b[1m(\x1b[0m\x1b[3;91mFalse\x1b[0m, \x1b[3;92mTrue\x1b[0m, \x1b[3;35mNone\x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m11 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[1m}\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markdown \x1b[0m\x1b[1;31m \x1b[0m\x1b[36m# Markdown\x1b[0m ╔═══════════════════════════════════════╗ \n\x1b[1;31m \x1b[0m ║ \x1b[1mMarkdown\x1b[0m ║ \n\x1b[1;31m \x1b[0m\x1b[36mSupports much of the *markdown* \x1b[0m ╚═══════════════════════════════════════╝ \n\x1b[1;31m \x1b[0m\x1b[36m__syntax__!\x1b[0m \n\x1b[1;31m \x1b[0m Supports much of the \x1b[3mmarkdown\x1b[0m \x1b[1msyntax\x1b[0m! \n\x1b[1;31m \x1b[0m\x1b[36m- Headers\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Basic formatting: **bold**, *italic*, \x1b[0m \x1b[1;33m • \x1b[0mHeaders \n\x1b[1;31m \x1b[0m\x1b[36m`code`\x1b[0m \x1b[1;33m • \x1b[0mBasic formatting: \x1b[1mbold\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[97;40mcode\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Block quotes\x1b[0m \x1b[1;33m • \x1b[0mBlock quotes \n\x1b[1;31m \x1b[0m\x1b[36m- Lists, and more...\x1b[0m \x1b[1;33m • \x1b[0mLists, and more... \n\x1b[1;31m \x1b[0m\x1b[36m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m +more! \x1b[0m\x1b[1;31m \x1b[0mProgress bars, columns, styled logging handler, tracebacks, etc... \n\x1b[1;31m \x1b[0m \n" diff --git a/tests/test_log.py b/tests/test_log.py index 94a1f9e17b..9e7010a6c0 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -6,7 +6,6 @@ from rich.console import Console - re_link_ids = re.compile(r"id=[\d\.\-]*?;.*?\x1b") @@ -38,7 +37,7 @@ def render_log(): def test_log(): expected = replace_link_ids( - "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m35\x1b[0m\x1b]8;;\x1b\\\n \x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \n \x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \n \x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \n" + "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m35\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \x1b[2m \x1b[0m\n" ) rendered = render_log() print(repr(rendered)) diff --git a/tests/test_segment.py b/tests/test_segment.py index 9aff243a83..9adf103299 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -2,8 +2,7 @@ import pytest -from rich.segment import ControlType -from rich.segment import Segment, Segments, SegmentLines +from rich.segment import ControlType, Segment, SegmentLines, Segments from rich.style import Style @@ -179,8 +178,8 @@ def test_divide_complex(): "[on orange4] \n" " [on green]XX[on orange4] \n" ) - from rich.text import Text from rich.console import Console + from rich.text import Text text = Text.from_markup(MAP) console = Console( @@ -299,3 +298,33 @@ def test_segment_lines_renderable(): Segment("foo"), Segment("\n"), ] + + +def test_align_top(): + lines = [[Segment("X")]] + assert Segment.align_top(lines, 3, 1, Style()) == lines + assert Segment.align_top(lines, 3, 3, Style()) == [ + [Segment("X")], + [Segment(" ", Style())], + [Segment(" ", Style())], + ] + + +def test_align_middle(): + lines = [[Segment("X")]] + assert Segment.align_middle(lines, 3, 1, Style()) == lines + assert Segment.align_middle(lines, 3, 3, Style()) == [ + [Segment(" ", Style())], + [Segment("X")], + [Segment(" ", Style())], + ] + + +def test_align_bottom(): + lines = [[Segment("X")]] + assert Segment.align_bottom(lines, 3, 1, Style()) == lines + assert Segment.align_bottom(lines, 3, 3, Style()) == [ + [Segment(" ", Style())], + [Segment(" ", Style())], + [Segment("X")], + ] diff --git a/tests/test_table.py b/tests/test_table.py index 29826e1182..8d23492883 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -4,11 +4,12 @@ import pytest -from rich import errors +from rich import box, errors +from rich.align import VerticalAlignMethod from rich.console import Console from rich.measure import Measurement from rich.style import Style -from rich.table import Table, Column +from rich.table import Column, Table from rich.text import Text @@ -158,6 +159,29 @@ def test_get_row_style(): assert table.get_row_style(console, 1) == Style.parse("on red") +def test_vertical_align_top(): + console = Console(_environ={}) + + def make_table(vertical_align): + table = Table(show_header=False, box=box.SQUARE) + table.add_column(vertical_align=vertical_align) + table.add_row("foo", "\n".join(["bar"] * 5)) + + return table + + with console.capture() as capture: + console.print(make_table("top")) + console.print() + console.print(make_table("middle")) + console.print() + console.print(make_table("bottom")) + console.print() + result = capture.get() + print(repr(result)) + expected = "┌─────┬─────┐\n│ foo │ bar │\n│ │ bar │\n│ │ bar │\n│ │ bar │\n│ │ bar │\n└─────┴─────┘\n\n┌─────┬─────┐\n│ │ bar │\n│ │ bar │\n│ foo │ bar │\n│ │ bar │\n│ │ bar │\n└─────┴─────┘\n\n┌─────┬─────┐\n│ │ bar │\n│ │ bar │\n│ │ bar │\n│ │ bar │\n│ foo │ bar │\n└─────┴─────┘\n\n" + assert result == expected + + if __name__ == "__main__": render = render_tables() print(render) From 96e87bb99af006291f6c73590fc6f9a36d7be0b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 13:30:44 +0000 Subject: [PATCH 212/287] Bump types-dataclasses from 0.6.2 to 0.6.3 Bumps [types-dataclasses](https://github.com/python/typeshed) from 0.6.2 to 0.6.3. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-dataclasses dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- poetry.lock | 53 ++++++++++++++++++++++++++++++++++++++++++++++---- pyproject.toml | 2 +- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 98253e38e4..fd7783ecfc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -974,7 +974,7 @@ python-versions = "*" [[package]] name = "types-dataclasses" -version = "0.6.2" +version = "0.6.3" description = "Typing stubs for dataclasses" category = "dev" optional = false @@ -1053,7 +1053,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "020be391dbd668426ce6c2c3b98366d3bc4612dee16f75208ed298c27130013b" +content-hash = "230d724bf180e628ff242b220bbc92431ddb15547f4790d685af63a77ff2bf6f" [metadata.files] appnope = [ @@ -1313,12 +1313,28 @@ jupyterlab-widgets = [ {file = "jupyterlab_widgets-1.0.2.tar.gz", hash = "sha256:7885092b2b96bf189c3a705cc3c412a4472ec5e8382d0b47219a66cccae73cfa"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1327,14 +1343,27 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1344,6 +1373,12 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1562,24 +1597,32 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, + {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, + {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, + {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, + {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, @@ -1587,6 +1630,8 @@ pyzmq = [ {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, + {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, @@ -1699,8 +1744,8 @@ typed-ast = [ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] types-dataclasses = [ - {file = "types-dataclasses-0.6.2.tar.gz", hash = "sha256:d74876d7a5e39ae6285765dd871e3b85d8186251f7b48e18130a35024c78bf73"}, - {file = "types_dataclasses-0.6.2-py3-none-any.whl", hash = "sha256:19ea746937b82bfa0d3bba1dd78858eca2ed81932eae888c3f2966aa3fd0aec6"}, + {file = "types-dataclasses-0.6.3.tar.gz", hash = "sha256:dfda22409c0e514f8b5c2ff6d0ccf5f404ee84c680e9e28521ea61978ca4dc70"}, + {file = "types_dataclasses-0.6.3-py3-none-any.whl", hash = "sha256:645b511230b00e90bd6a24725f316a7e992d9f118e78d25de60d38aa07260928"}, ] typing-extensions = [ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, diff --git a/pyproject.toml b/pyproject.toml index 42b60550f5..afb7244fda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ black = "^21.11b1" mypy = "^0.930" pytest-cov = "^3.0.0" attrs = "^21.4.0" -types-dataclasses = "^0.6.2" +types-dataclasses = "^0.6.3" pre-commit = "^2.16.0" [build-system] From 1e7778806ce58b601021e469fb0947d51fdaffa3 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 14:58:29 +0000 Subject: [PATCH 213/287] test fix --- tests/test_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_log.py b/tests/test_log.py index 9e7010a6c0..22bb8b7b83 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -37,7 +37,7 @@ def render_log(): def test_log(): expected = replace_link_ids( - "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m35\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \x1b[2m \x1b[0m\n" + "\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m32\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0mHello from \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m ! \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m33\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[2;36m \x1b[0m\x1b[1m[\x1b[0m\x1b[1;36m1\x1b[0m, \x1b[1;36m2\x1b[0m, \x1b[1;36m3\x1b[0m\x1b[1m]\x1b[0m \x1b]8;id=0;foo\x1b\\\x1b[2msource.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:\x1b[0m\x1b]8;id=0;foo\x1b\\\x1b[2m34\x1b[0m\x1b]8;;\x1b\\\n\x1b[2;36m \x1b[0m\x1b[34m╭─\x1b[0m\x1b[34m───────────────────── \x1b[0m\x1b[3;34mlocals\x1b[0m\x1b[34m ─────────────────────\x1b[0m\x1b[34m─╮\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m│\x1b[0m \x1b[3;33mconsole\x1b[0m\x1b[31m =\x1b[0m \x1b[1m<\x1b[0m\x1b[1;95mconsole\x1b[0m\x1b[39m \x1b[0m\x1b[33mwidth\x1b[0m\x1b[39m=\x1b[0m\x1b[1;36m80\x1b[0m\x1b[39m ColorSystem.TRUECOLOR\x1b[0m\x1b[1m>\x1b[0m \x1b[34m│\x1b[0m \x1b[2m \x1b[0m\n\x1b[2;36m \x1b[0m\x1b[34m╰────────────────────────────────────────────────────╯\x1b[0m \x1b[2m \x1b[0m\n" ) rendered = render_log() print(repr(rendered)) From 369e95a0517e0e0dedf9a613480b8c4cfec048bc Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 15:00:30 +0000 Subject: [PATCH 214/287] changelog --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe01b9d04..5350b9f386 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,16 @@ 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). - ## [11.0.0] - Unreleased ### Added -- Fixed issue with pretty repr in jupyter notebook https://github.com/Textualize/rich/issues/1717 - Added max_depth arg to pretty printing +- Added `vertical_align` to Table.add_row + +### Fixed + +- Fixed issue with pretty repr in jupyter notebook https://github.com/Textualize/rich/issues/1717 - Fix Traceback theme defaults override user supplied styles https://github.com/Textualize/rich/issues/1786 ## [10.16.2] - 2021-01-02 From e57f4729b03c82e2966581c584009bb00b174ebf Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 15:31:50 +0000 Subject: [PATCH 215/287] set shape tweak --- rich/segment.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/rich/segment.py b/rich/segment.py index dac9f655c1..edb9ffc9fe 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -391,32 +391,19 @@ def set_shape( Returns: List[List[Segment]]: New list of lines. """ - if height is None: - height = len(lines) + _height = height or len(lines) + blank = ( - [Segment(" " * width, style), Segment("\n")] - if new_lines - else [Segment(" " * width, style)] + [cls(" " * width + "\n", style)] if new_lines else [cls(" " * width, style)] ) adjust_line_length = cls.adjust_line_length - shaped_lines = [ - adjust_line_length(line, width, style=style) for line in lines[:height] + shaped_lines = lines[:_height] + shaped_lines[:] = [ + adjust_line_length(line, width, style=style) for line in lines ] - if len(shaped_lines) < height: - shaped_lines.extend([blank] * (height - len(shaped_lines))) - return shaped_lines - - append = shaped_lines.append - adjust_line_length = cls.adjust_line_length - line: Optional[List[Segment]] - iter_lines = iter(lines) - for _ in range(height): - line = next(iter_lines, None) - if line is None: - append(pad_line) - else: - append(adjust_line_length(line, width, style=style)) + if len(shaped_lines) < _height: + shaped_lines.extend([blank] * (_height - len(shaped_lines))) return shaped_lines @classmethod From 5b8f4fbe23d525b0496ad544b69fe23e858ee08a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 20:38:23 +0000 Subject: [PATCH 216/287] added per cell alignment --- rich/segment.py | 6 +++--- rich/table.py | 32 +++++++++++++++++++++----------- tests/test_table.py | 2 +- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/rich/segment.py b/rich/segment.py index edb9ffc9fe..97679cefc0 100644 --- a/rich/segment.py +++ b/rich/segment.py @@ -421,7 +421,7 @@ def align_top( lines (List[List[Segment]]): A list of lines. width (int): Desired width. height (int, optional): Desired height or None for no change. - style (Style, optional): Style of any padding added. + style (Style): Style of any padding added. new_lines (bool, optional): Padded lines should include "\n". Defaults to False. Returns: @@ -450,7 +450,7 @@ def align_bottom( lines (List[List[Segment]]): A list of lines. width (int): Desired width. height (int, optional): Desired height or None for no change. - style (Style, optional): Style of any padding added. Defaults to None. + style (Style): Style of any padding added. Defaults to None. new_lines (bool, optional): Padded lines should include "\n". Defaults to False. Returns: @@ -479,7 +479,7 @@ def align_middle( lines (List[List[Segment]]): A list of lines. width (int): Desired width. height (int, optional): Desired height or None for no change. - style (Style, optional): Style of any padding added. + style (Style): Style of any padding added. new_lines (bool, optional): Padded lines should include "\n". Defaults to False. Returns: diff --git a/rich/table.py b/rich/table.py index 2b11fbd38b..36fdde86ac 100644 --- a/rich/table.py +++ b/rich/table.py @@ -57,7 +57,7 @@ class Column: justify: "JustifyMethod" = "left" """str: How to justify text within the column ("left", "center", "right", or "full")""" - vertical_align: "VerticalAlignMethod" = "top" + vertical: "VerticalAlignMethod" = "top" """str: How to vertically align content ("top", "middle", or "bottom")""" overflow: "OverflowMethod" = "ellipsis" @@ -116,7 +116,7 @@ class _Cell(NamedTuple): """Style to apply to cell.""" renderable: "RenderableType" """Cell renderable.""" - vertical_align: VerticalAlignMethod + vertical: VerticalAlignMethod """Cell vertical alignment.""" @@ -341,7 +341,7 @@ def add_column( footer_style: Optional[StyleType] = None, style: Optional[StyleType] = None, justify: "JustifyMethod" = "left", - vertical_align: "VerticalAlignMethod" = "top", + vertical: "VerticalAlignMethod" = "top", overflow: "OverflowMethod" = "ellipsis", width: Optional[int] = None, min_width: Optional[int] = None, @@ -360,7 +360,7 @@ def add_column( footer_style (Union[str, Style], optional): Style for the footer, or None for default. Defaults to None. style (Union[str, Style], optional): Style for the column cells, or None for default. Defaults to None. justify (JustifyMethod, optional): Alignment for cells. Defaults to "left". - vertical_align (VerticalAlignMethod, optional): Vertical alignment, one of "top", "middle", or "bottom". Defaults to "top". + vertical (VerticalAlignMethod, optional): Vertical alignment, one of "top", "middle", or "bottom". Defaults to "top". overflow (OverflowMethod): Overflow method: "crop", "fold", "ellipsis". Defaults to "ellipsis". width (int, optional): Desired width of column in characters, or None to fit to contents. Defaults to None. min_width (Optional[int], optional): Minimum width of column, or ``None`` for no minimum. Defaults to None. @@ -377,7 +377,7 @@ def add_column( footer_style=footer_style or "", style=style or "", justify=justify, - vertical_align=vertical_align, + vertical=vertical, overflow=overflow, width=width, min_width=min_width, @@ -648,11 +648,15 @@ def get_padding(first_row: bool, last_row: bool) -> Tuple[int, int, int, int]: yield _Cell( style, _Padding(renderable, get_padding(first, last)), - column.vertical_align, + getattr(renderable, "vertical", None) or column.vertical, ) else: for (style, renderable) in raw_cells: - yield _Cell(style, renderable, column.vertical_align) + yield _Cell( + style, + renderable, + getattr(renderable, "vertical", None) or column.vertical, + ) def _get_padding_width(self, column_index: int) -> int: """Get extra width from padding.""" @@ -795,20 +799,26 @@ def _render( def align_cell( cell: List[List[Segment]], - vertical_align: "VerticalAlignMethod", + vertical: "VerticalAlignMethod", style: Style, ) -> List[List[Segment]]: + if header_row: + vertical = "bottom" + elif footer_row: + vertical = "top" - if vertical_align == "top": + if vertical == "top": return _Segment.align_top(cell, width, row_height, style) - elif vertical_align == "middle": + elif vertical == "middle": return _Segment.align_middle(cell, width, row_height, style) return _Segment.align_bottom(cell, width, row_height, style) cells[:] = [ _Segment.set_shape( align_cell( - cell, column.vertical_align, get_style(_cell.style) + row_style + cell, + _cell.vertical, + get_style(_cell.style) + row_style, ), width, max_height, diff --git a/tests/test_table.py b/tests/test_table.py index 8d23492883..6fc863f20c 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -164,7 +164,7 @@ def test_vertical_align_top(): def make_table(vertical_align): table = Table(show_header=False, box=box.SQUARE) - table.add_column(vertical_align=vertical_align) + table.add_column(vertical=vertical_align) table.add_row("foo", "\n".join(["bar"] * 5)) return table From 65bd4ce48b9725a01f56b71314dc957ac38575f8 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 7 Jan 2022 21:03:02 +0000 Subject: [PATCH 217/287] isorted --- rich/__main__.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/rich/__main__.py b/rich/__main__.py index 5d1abd10d5..132e809412 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -4,13 +4,7 @@ from rich import box from rich.color import Color -from rich.console import ( - Console, - ConsoleOptions, - Group, - RenderResult, - RenderableType, -) +from rich.console import Console, ConsoleOptions, Group, RenderableType, RenderResult from rich.markdown import Markdown from rich.measure import Measurement from rich.pretty import Pretty @@ -247,13 +241,10 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: sponsor_message = Table.grid(padding=1) sponsor_message.add_column(style="green", justify="right") sponsor_message.add_column(no_wrap=True) + sponsor_message.add_row( - "Sponsor me", - "[u blue link=https://github.com/sponsors/willmcgugan]https://github.com/sponsors/willmcgugan", - ) - sponsor_message.add_row( - "Buy me a :coffee:", - "[u blue link=https://ko-fi.com/willmcgugan]https://ko-fi.com/willmcgugan", + "Buy devs a :coffee:", + "[u blue link=https://ko-fi.com/textualize]https://ko-fi.com/textualize", ) sponsor_message.add_row( "Twitter", @@ -265,9 +256,9 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: intro_message = Text.from_markup( """\ -It takes a lot of time to develop Rich and to provide support. +We hope you enjoy using Rich! -Consider supporting my work via Github Sponsors (ask your company / organization), or buy me a coffee to say thanks. +Rich is maintained with :heart: by [link=https://www.textualize.io]Textualize.io[/] - Will McGugan""" ) From 408b3bc688ddcf748bba18197faaa9ad09f5cf53 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 8 Jan 2022 10:48:06 +0000 Subject: [PATCH 218/287] whitespace --- docs/source/tables.rst | 72 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/docs/source/tables.rst b/docs/source/tables.rst index 2603e7912a..967a573825 100644 --- a/docs/source/tables.rst +++ b/docs/source/tables.rst @@ -40,7 +40,44 @@ This produces the following output: -Rich is quite smart about rendering the table. It will adjust the column widths to fit the contents and will wrap text if it doesn't fit. You can also add anything that Rich knows how to render as a title or row cell (even another table)! +Rich will calculate the optimal column sizes to fit your content, and will wrap text to fit if the terminal is not wide enough to fit the contents. + +.. note:: + You are not limited to adding text in the ``add_row`` method. You can add anything that Rich knows how to render (including another table). + +Table Options +~~~~~~~~~~~~~ + +There are a number of keyword arguments on the Table constructor you can use to define how a table should look. + +- ``title`` Sets the title of the table (text show above the table). +- ``caption`` Sets the table caption (text show below the table). +- ``width`` Sets the desired width of the table (disables automatic width calculation). +- ``min_width`` Sets a minimum width for the table. +- ``box`` Sets one of the :ref:`appendix_box` styles for the table grid, or ``None`` for no grid. +- ``safe_box`` Set to ``True`` to force the table to generate ASCII characters rather than unicode. +- ``padding`` A integer, or tuple of 1, 2, or 4 values to set the padding on cells. +- ``collapse_padding`` If True the padding of neighboring cells will be merged. +- ``pad_edge`` Set to False to remove padding around the edge of the table. +- ``expand`` Set to True to expand the table to the full available size. +- ``show_header`` Set to True to show a header, False to disable it. +- ``show_footer`` Set to True to show a footer, False to disable it. +- ``show edge`` Set to False to disable the edge line around the table. +- ``show_lines`` Set to True to show lines between rows as well as header / footer. +- ``leading`` Additional space between rows. +- ``style`` A Style to apply to the entire table, e.g. "on blue" +- ``row_styles`` Set to a list of styles to style alternating rows. e.g. ``["dim", ""]`` to create *zebra stripes* +- ``header_style`` Set the default style for the header. +- ``footer_style`` Set the default style for the footer. +- ``border style`` Set a style for border characters. +- ``title_style`` Set a style for the title. +- ``caption_style`` Set a style for the caption. +- ``title_justify`` Set the title justify method ("left", "right", "center", or "full") +- ``caption_justify`` Set the caption justify method ("left", "right", "center", or "full") +- ``highlight`` Set to True to enable automatic highlighting of cell contents. + +Border Styles +~~~~~~~~~~~~~ You can set the border style by importing one of the preset :class:`~rich.box.Box` objects and setting the ``box`` argument in the table constructor. Here's an example that modifies the look of the Star Wars table:: @@ -49,9 +86,17 @@ You can set the border style by importing one of the preset :class:`~rich.box.Bo See :ref:`appendix_box` for other box styles. +You can also set ``box=None`` to remove borders entirely. + The :class:`~rich.table.Table` class offers a number of configuration options to set the look and feel of the table, including how borders are rendered and the style and alignment of the columns. +Lines +~~~~~ + +By default, Tables will show a line under the header only. If you want to show lines between all rows add ``show_lines=True`` to the constructor. + + Empty Tables ~~~~~~~~~~~~ @@ -80,10 +125,29 @@ This allows you to specify the text of the column only. If you want to set other title="Star Wars Movies" ) -Lines -~~~~~ +Column Options +~~~~~~~~~~~~~~ -By default, Tables will show a line under the header only. If you want to show lines between all rows add ``show_lines=True`` to the constructor. +There are a number of options you can set on a column to modify how it will look. + +- ``header_style`` Sets the style of the header, e.g. "bold magenta". +- ``footer_style`` Sets the style of the footer. +- ``style`` Sets a style that applies to the column. You could use this to highlight a column by setting the background with "on green" for example. +- ``justify`` Sets the text justify to one of "left", "center", "right", or "full". +- ``vertical`` Sets the vertical alignment of the cells in a column, to one of "top", "middle", or "bottom". +- ``width`` Explicitly set the width of a row to a given number of characters (disables automatic calculation). +- ``min_width`` When set to an integer will prevent the column from shrinking below this amount. +- ``max_width`` When set to an integer will prevent the column from growing beyond this amount. +- ``ratio`` Defines a ratio to set the column width. For instance, if there are 3 columns with a total of 6 ratio, and ``ratio=2`` then the column will be a third of the available size. +- ``no_wrap`` Set to False to prevent this column from wrapping. + +Vertical Alignment +~~~~~~~~~~~~~~~~~~ + +You can define the vertical alignment of a column by setting the ``vertical`` parameter of the column. You can also do this per-cell by wrapping your text or renderable with a :class:`~rich.align.Align` class:: + + + table.add_row(Align("Title", vertical="middle")) Grids ~~~~~ From 7b851516cba7ea1ea08db1af0507996303040294 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 8 Jan 2022 11:55:12 +0000 Subject: [PATCH 219/287] rendergroup --- CHANGELOG.md | 5 ++++- rich/console.py | 14 ++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe01b9d04..76a9f528f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ 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). - ## [11.0.0] - Unreleased ### Added @@ -14,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added max_depth arg to pretty printing - Fix Traceback theme defaults override user supplied styles https://github.com/Textualize/rich/issues/1786 +### Changed + +- **breaking** Deprecated rich.console.RenderGroup, now named rich.console.Group + ## [10.16.2] - 2021-01-02 ### Fixed diff --git a/rich/console.py b/rich/console.py index b6a661061f..6fdc7403f7 100644 --- a/rich/console.py +++ b/rich/console.py @@ -11,9 +11,9 @@ from html import escape from inspect import isclass from itertools import islice -from time import monotonic from threading import RLock -from types import FrameType, TracebackType, ModuleType +from time import monotonic +from types import FrameType, ModuleType, TracebackType from typing import ( IO, TYPE_CHECKING, @@ -258,11 +258,12 @@ def __rich_console__( ... +# A type that may be rendered by Console. RenderableType = Union[ConsoleRenderable, RichCast, str] -"""A type that may be rendered by Console.""" + +# The result of calling a __rich_console__ method. RenderResult = Iterable[Union[RenderableType, Segment]] -"""The result of calling a __rich_console__ method.""" _null_highlighter = NullHighlighter() @@ -475,9 +476,6 @@ def __rich_console__( yield from self.renderables -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. @@ -488,7 +486,7 @@ def group(fit: bool = True) -> Callable[..., Callable[..., Group]]: def decorator( method: Callable[..., Iterable[RenderableType]] ) -> Callable[..., Group]: - """Convert a method that returns an iterable of renderables in to a RenderGroup.""" + """Convert a method that returns an iterable of renderables in to a Group.""" @wraps(method) def _replace(*args: Any, **kwargs: Any) -> Group: From ad9debf2eb5a04cea709d35a7bc03f316bf0431c Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 8 Jan 2022 13:08:59 +0000 Subject: [PATCH 220/287] remove render_group --- rich/console.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/rich/console.py b/rich/console.py index 6fdc7403f7..fbf87bd5c1 100644 --- a/rich/console.py +++ b/rich/console.py @@ -498,9 +498,6 @@ def _replace(*args: Any, **kwargs: Any) -> Group: return decorator -render_group = group - - def _is_jupyter() -> bool: # pragma: no cover """Check if we're running in a Jupyter notebook.""" try: From 4abbbd1390423e581ab8f050ec7cb574c682d0b2 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 8 Jan 2022 13:32:46 +0000 Subject: [PATCH 221/287] eof --- rich/table.py | 2 ++ tests/_card_render.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rich/table.py b/rich/table.py index 36fdde86ac..0271d5fc66 100644 --- a/rich/table.py +++ b/rich/table.py @@ -800,6 +800,7 @@ def _render( def align_cell( cell: List[List[Segment]], vertical: "VerticalAlignMethod", + width: int, style: Style, ) -> List[List[Segment]]: if header_row: @@ -818,6 +819,7 @@ def align_cell( align_cell( cell, _cell.vertical, + width, get_style(_cell.style) + row_style, ), width, diff --git a/tests/_card_render.py b/tests/_card_render.py index bc713103b0..ac8d7d42df 100644 --- a/tests/_card_render.py +++ b/tests/_card_render.py @@ -1 +1 @@ -expected = "\x1b[3m Rich features \x1b[0m\n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Colors \x1b[0m\x1b[1;31m \x1b[0m✓ \x1b[1;32m4-bit color\x1b[0m \x1b[38;2;86;0;0;48;2;51;0;0m▄\x1b[0m\x1b[38;2;86;9;0;48;2;51;5;0m▄\x1b[0m\x1b[38;2;86;18;0;48;2;51;11;0m▄\x1b[0m\x1b[38;2;86;28;0;48;2;51;16;0m▄\x1b[0m\x1b[38;2;86;37;0;48;2;51;22;0m▄\x1b[0m\x1b[38;2;86;47;0;48;2;51;27;0m▄\x1b[0m\x1b[38;2;86;56;0;48;2;51;33;0m▄\x1b[0m\x1b[38;2;86;66;0;48;2;51;38;0m▄\x1b[0m\x1b[38;2;86;75;0;48;2;51;44;0m▄\x1b[0m\x1b[38;2;86;85;0;48;2;51;50;0m▄\x1b[0m\x1b[38;2;78;86;0;48;2;46;51;0m▄\x1b[0m\x1b[38;2;69;86;0;48;2;40;51;0m▄\x1b[0m\x1b[38;2;59;86;0;48;2;35;51;0m▄\x1b[0m\x1b[38;2;50;86;0;48;2;29;51;0m▄\x1b[0m\x1b[38;2;40;86;0;48;2;24;51;0m▄\x1b[0m\x1b[38;2;31;86;0;48;2;18;51;0m▄\x1b[0m\x1b[38;2;22;86;0;48;2;12;51;0m▄\x1b[0m\x1b[38;2;12;86;0;48;2;7;51;0m▄\x1b[0m\x1b[38;2;3;86;0;48;2;1;51;0m▄\x1b[0m\x1b[38;2;0;86;6;48;2;0;51;3m▄\x1b[0m\x1b[38;2;0;86;15;48;2;0;51;9m▄\x1b[0m\x1b[38;2;0;86;25;48;2;0;51;14m▄\x1b[0m\x1b[38;2;0;86;34;48;2;0;51;20m▄\x1b[0m\x1b[38;2;0;86;44;48;2;0;51;25m▄\x1b[0m\x1b[38;2;0;86;53;48;2;0;51;31m▄\x1b[0m\x1b[38;2;0;86;63;48;2;0;51;37m▄\x1b[0m\x1b[38;2;0;86;72;48;2;0;51;42m▄\x1b[0m\x1b[38;2;0;86;81;48;2;0;51;48m▄\x1b[0m\x1b[38;2;0;81;86;48;2;0;48;51m▄\x1b[0m\x1b[38;2;0;72;86;48;2;0;42;51m▄\x1b[0m\x1b[38;2;0;63;86;48;2;0;37;51m▄\x1b[0m\x1b[38;2;0;53;86;48;2;0;31;51m▄\x1b[0m\x1b[38;2;0;44;86;48;2;0;25;51m▄\x1b[0m\x1b[38;2;0;34;86;48;2;0;20;51m▄\x1b[0m\x1b[38;2;0;25;86;48;2;0;14;51m▄\x1b[0m\x1b[38;2;0;15;86;48;2;0;9;51m▄\x1b[0m\x1b[38;2;0;6;86;48;2;0;3;51m▄\x1b[0m\x1b[38;2;3;0;86;48;2;1;0;51m▄\x1b[0m\x1b[38;2;12;0;86;48;2;7;0;51m▄\x1b[0m\x1b[38;2;22;0;86;48;2;12;0;51m▄\x1b[0m\x1b[38;2;31;0;86;48;2;18;0;51m▄\x1b[0m\x1b[38;2;40;0;86;48;2;24;0;51m▄\x1b[0m\x1b[38;2;50;0;86;48;2;29;0;51m▄\x1b[0m\x1b[38;2;59;0;86;48;2;35;0;51m▄\x1b[0m\x1b[38;2;69;0;86;48;2;40;0;51m▄\x1b[0m\x1b[38;2;78;0;86;48;2;46;0;51m▄\x1b[0m\x1b[38;2;86;0;85;48;2;51;0;50m▄\x1b[0m\x1b[38;2;86;0;75;48;2;51;0;44m▄\x1b[0m\x1b[38;2;86;0;66;48;2;51;0;38m▄\x1b[0m\x1b[38;2;86;0;56;48;2;51;0;33m▄\x1b[0m\x1b[38;2;86;0;47;48;2;51;0;27m▄\x1b[0m\x1b[38;2;86;0;37;48;2;51;0;22m▄\x1b[0m\x1b[38;2;86;0;28;48;2;51;0;16m▄\x1b[0m\x1b[38;2;86;0;18;48;2;51;0;11m▄\x1b[0m\x1b[38;2;86;0;9;48;2;51;0;5m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;34m8-bit color\x1b[0m \x1b[38;2;158;0;0;48;2;122;0;0m▄\x1b[0m\x1b[38;2;158;17;0;48;2;122;13;0m▄\x1b[0m\x1b[38;2;158;34;0;48;2;122;26;0m▄\x1b[0m\x1b[38;2;158;51;0;48;2;122;40;0m▄\x1b[0m\x1b[38;2;158;68;0;48;2;122;53;0m▄\x1b[0m\x1b[38;2;158;86;0;48;2;122;66;0m▄\x1b[0m\x1b[38;2;158;103;0;48;2;122;80;0m▄\x1b[0m\x1b[38;2;158;120;0;48;2;122;93;0m▄\x1b[0m\x1b[38;2;158;137;0;48;2;122;106;0m▄\x1b[0m\x1b[38;2;158;155;0;48;2;122;120;0m▄\x1b[0m\x1b[38;2;143;158;0;48;2;111;122;0m▄\x1b[0m\x1b[38;2;126;158;0;48;2;97;122;0m▄\x1b[0m\x1b[38;2;109;158;0;48;2;84;122;0m▄\x1b[0m\x1b[38;2;91;158;0;48;2;71;122;0m▄\x1b[0m\x1b[38;2;74;158;0;48;2;57;122;0m▄\x1b[0m\x1b[38;2;57;158;0;48;2;44;122;0m▄\x1b[0m\x1b[38;2;40;158;0;48;2;31;122;0m▄\x1b[0m\x1b[38;2;22;158;0;48;2;17;122;0m▄\x1b[0m\x1b[38;2;5;158;0;48;2;4;122;0m▄\x1b[0m\x1b[38;2;0;158;11;48;2;0;122;8m▄\x1b[0m\x1b[38;2;0;158;28;48;2;0;122;22m▄\x1b[0m\x1b[38;2;0;158;45;48;2;0;122;35m▄\x1b[0m\x1b[38;2;0;158;63;48;2;0;122;48m▄\x1b[0m\x1b[38;2;0;158;80;48;2;0;122;62m▄\x1b[0m\x1b[38;2;0;158;97;48;2;0;122;75m▄\x1b[0m\x1b[38;2;0;158;114;48;2;0;122;89m▄\x1b[0m\x1b[38;2;0;158;132;48;2;0;122;102m▄\x1b[0m\x1b[38;2;0;158;149;48;2;0;122;115m▄\x1b[0m\x1b[38;2;0;149;158;48;2;0;115;122m▄\x1b[0m\x1b[38;2;0;132;158;48;2;0;102;122m▄\x1b[0m\x1b[38;2;0;114;158;48;2;0;89;122m▄\x1b[0m\x1b[38;2;0;97;158;48;2;0;75;122m▄\x1b[0m\x1b[38;2;0;80;158;48;2;0;62;122m▄\x1b[0m\x1b[38;2;0;63;158;48;2;0;48;122m▄\x1b[0m\x1b[38;2;0;45;158;48;2;0;35;122m▄\x1b[0m\x1b[38;2;0;28;158;48;2;0;22;122m▄\x1b[0m\x1b[38;2;0;11;158;48;2;0;8;122m▄\x1b[0m\x1b[38;2;5;0;158;48;2;4;0;122m▄\x1b[0m\x1b[38;2;22;0;158;48;2;17;0;122m▄\x1b[0m\x1b[38;2;40;0;158;48;2;31;0;122m▄\x1b[0m\x1b[38;2;57;0;158;48;2;44;0;122m▄\x1b[0m\x1b[38;2;74;0;158;48;2;57;0;122m▄\x1b[0m\x1b[38;2;91;0;158;48;2;71;0;122m▄\x1b[0m\x1b[38;2;109;0;158;48;2;84;0;122m▄\x1b[0m\x1b[38;2;126;0;158;48;2;97;0;122m▄\x1b[0m\x1b[38;2;143;0;158;48;2;111;0;122m▄\x1b[0m\x1b[38;2;158;0;155;48;2;122;0;120m▄\x1b[0m\x1b[38;2;158;0;137;48;2;122;0;106m▄\x1b[0m\x1b[38;2;158;0;120;48;2;122;0;93m▄\x1b[0m\x1b[38;2;158;0;103;48;2;122;0;80m▄\x1b[0m\x1b[38;2;158;0;86;48;2;122;0;66m▄\x1b[0m\x1b[38;2;158;0;68;48;2;122;0;53m▄\x1b[0m\x1b[38;2;158;0;51;48;2;122;0;40m▄\x1b[0m\x1b[38;2;158;0;34;48;2;122;0;26m▄\x1b[0m\x1b[38;2;158;0;17;48;2;122;0;13m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;35mTruecolor (16.7 million)\x1b[0m \x1b[38;2;229;0;0;48;2;193;0;0m▄\x1b[0m\x1b[38;2;229;25;0;48;2;193;21;0m▄\x1b[0m\x1b[38;2;229;50;0;48;2;193;42;0m▄\x1b[0m\x1b[38;2;229;75;0;48;2;193;63;0m▄\x1b[0m\x1b[38;2;229;100;0;48;2;193;84;0m▄\x1b[0m\x1b[38;2;229;125;0;48;2;193;105;0m▄\x1b[0m\x1b[38;2;229;150;0;48;2;193;126;0m▄\x1b[0m\x1b[38;2;229;175;0;48;2;193;147;0m▄\x1b[0m\x1b[38;2;229;200;0;48;2;193;169;0m▄\x1b[0m\x1b[38;2;229;225;0;48;2;193;190;0m▄\x1b[0m\x1b[38;2;208;229;0;48;2;176;193;0m▄\x1b[0m\x1b[38;2;183;229;0;48;2;155;193;0m▄\x1b[0m\x1b[38;2;158;229;0;48;2;133;193;0m▄\x1b[0m\x1b[38;2;133;229;0;48;2;112;193;0m▄\x1b[0m\x1b[38;2;108;229;0;48;2;91;193;0m▄\x1b[0m\x1b[38;2;83;229;0;48;2;70;193;0m▄\x1b[0m\x1b[38;2;58;229;0;48;2;49;193;0m▄\x1b[0m\x1b[38;2;33;229;0;48;2;28;193;0m▄\x1b[0m\x1b[38;2;8;229;0;48;2;7;193;0m▄\x1b[0m\x1b[38;2;0;229;16;48;2;0;193;14m▄\x1b[0m\x1b[38;2;0;229;41;48;2;0;193;35m▄\x1b[0m\x1b[38;2;0;229;66;48;2;0;193;56m▄\x1b[0m\x1b[38;2;0;229;91;48;2;0;193;77m▄\x1b[0m\x1b[38;2;0;229;116;48;2;0;193;98m▄\x1b[0m\x1b[38;2;0;229;141;48;2;0;193;119m▄\x1b[0m\x1b[38;2;0;229;166;48;2;0;193;140m▄\x1b[0m\x1b[38;2;0;229;191;48;2;0;193;162m▄\x1b[0m\x1b[38;2;0;229;216;48;2;0;193;183m▄\x1b[0m\x1b[38;2;0;216;229;48;2;0;183;193m▄\x1b[0m\x1b[38;2;0;191;229;48;2;0;162;193m▄\x1b[0m\x1b[38;2;0;166;229;48;2;0;140;193m▄\x1b[0m\x1b[38;2;0;141;229;48;2;0;119;193m▄\x1b[0m\x1b[38;2;0;116;229;48;2;0;98;193m▄\x1b[0m\x1b[38;2;0;91;229;48;2;0;77;193m▄\x1b[0m\x1b[38;2;0;66;229;48;2;0;56;193m▄\x1b[0m\x1b[38;2;0;41;229;48;2;0;35;193m▄\x1b[0m\x1b[38;2;0;16;229;48;2;0;14;193m▄\x1b[0m\x1b[38;2;8;0;229;48;2;7;0;193m▄\x1b[0m\x1b[38;2;33;0;229;48;2;28;0;193m▄\x1b[0m\x1b[38;2;58;0;229;48;2;49;0;193m▄\x1b[0m\x1b[38;2;83;0;229;48;2;70;0;193m▄\x1b[0m\x1b[38;2;108;0;229;48;2;91;0;193m▄\x1b[0m\x1b[38;2;133;0;229;48;2;112;0;193m▄\x1b[0m\x1b[38;2;158;0;229;48;2;133;0;193m▄\x1b[0m\x1b[38;2;183;0;229;48;2;155;0;193m▄\x1b[0m\x1b[38;2;208;0;229;48;2;176;0;193m▄\x1b[0m\x1b[38;2;229;0;225;48;2;193;0;190m▄\x1b[0m\x1b[38;2;229;0;200;48;2;193;0;169m▄\x1b[0m\x1b[38;2;229;0;175;48;2;193;0;147m▄\x1b[0m\x1b[38;2;229;0;150;48;2;193;0;126m▄\x1b[0m\x1b[38;2;229;0;125;48;2;193;0;105m▄\x1b[0m\x1b[38;2;229;0;100;48;2;193;0;84m▄\x1b[0m\x1b[38;2;229;0;75;48;2;193;0;63m▄\x1b[0m\x1b[38;2;229;0;50;48;2;193;0;42m▄\x1b[0m\x1b[38;2;229;0;25;48;2;193;0;21m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;33mDumb terminals\x1b[0m \x1b[38;2;254;45;45;48;2;255;10;10m▄\x1b[0m\x1b[38;2;254;68;45;48;2;255;36;10m▄\x1b[0m\x1b[38;2;254;91;45;48;2;255;63;10m▄\x1b[0m\x1b[38;2;254;114;45;48;2;255;90;10m▄\x1b[0m\x1b[38;2;254;137;45;48;2;255;117;10m▄\x1b[0m\x1b[38;2;254;159;45;48;2;255;143;10m▄\x1b[0m\x1b[38;2;254;182;45;48;2;255;170;10m▄\x1b[0m\x1b[38;2;254;205;45;48;2;255;197;10m▄\x1b[0m\x1b[38;2;254;228;45;48;2;255;223;10m▄\x1b[0m\x1b[38;2;254;251;45;48;2;255;250;10m▄\x1b[0m\x1b[38;2;235;254;45;48;2;232;255;10m▄\x1b[0m\x1b[38;2;213;254;45;48;2;206;255;10m▄\x1b[0m\x1b[38;2;190;254;45;48;2;179;255;10m▄\x1b[0m\x1b[38;2;167;254;45;48;2;152;255;10m▄\x1b[0m\x1b[38;2;144;254;45;48;2;125;255;10m▄\x1b[0m\x1b[38;2;121;254;45;48;2;99;255;10m▄\x1b[0m\x1b[38;2;99;254;45;48;2;72;255;10m▄\x1b[0m\x1b[38;2;76;254;45;48;2;45;255;10m▄\x1b[0m\x1b[38;2;53;254;45;48;2;19;255;10m▄\x1b[0m\x1b[38;2;45;254;61;48;2;10;255;28m▄\x1b[0m\x1b[38;2;45;254;83;48;2;10;255;54m▄\x1b[0m\x1b[38;2;45;254;106;48;2;10;255;81m▄\x1b[0m\x1b[38;2;45;254;129;48;2;10;255;108m▄\x1b[0m\x1b[38;2;45;254;152;48;2;10;255;134m▄\x1b[0m\x1b[38;2;45;254;175;48;2;10;255;161m▄\x1b[0m\x1b[38;2;45;254;197;48;2;10;255;188m▄\x1b[0m\x1b[38;2;45;254;220;48;2;10;255;214m▄\x1b[0m\x1b[38;2;45;254;243;48;2;10;255;241m▄\x1b[0m\x1b[38;2;45;243;254;48;2;10;241;255m▄\x1b[0m\x1b[38;2;45;220;254;48;2;10;214;255m▄\x1b[0m\x1b[38;2;45;197;254;48;2;10;188;255m▄\x1b[0m\x1b[38;2;45;175;254;48;2;10;161;255m▄\x1b[0m\x1b[38;2;45;152;254;48;2;10;134;255m▄\x1b[0m\x1b[38;2;45;129;254;48;2;10;108;255m▄\x1b[0m\x1b[38;2;45;106;254;48;2;10;81;255m▄\x1b[0m\x1b[38;2;45;83;254;48;2;10;54;255m▄\x1b[0m\x1b[38;2;45;61;254;48;2;10;28;255m▄\x1b[0m\x1b[38;2;53;45;254;48;2;19;10;255m▄\x1b[0m\x1b[38;2;76;45;254;48;2;45;10;255m▄\x1b[0m\x1b[38;2;99;45;254;48;2;72;10;255m▄\x1b[0m\x1b[38;2;121;45;254;48;2;99;10;255m▄\x1b[0m\x1b[38;2;144;45;254;48;2;125;10;255m▄\x1b[0m\x1b[38;2;167;45;254;48;2;152;10;255m▄\x1b[0m\x1b[38;2;190;45;254;48;2;179;10;255m▄\x1b[0m\x1b[38;2;213;45;254;48;2;206;10;255m▄\x1b[0m\x1b[38;2;235;45;254;48;2;232;10;255m▄\x1b[0m\x1b[38;2;254;45;251;48;2;255;10;250m▄\x1b[0m\x1b[38;2;254;45;228;48;2;255;10;223m▄\x1b[0m\x1b[38;2;254;45;205;48;2;255;10;197m▄\x1b[0m\x1b[38;2;254;45;182;48;2;255;10;170m▄\x1b[0m\x1b[38;2;254;45;159;48;2;255;10;143m▄\x1b[0m\x1b[38;2;254;45;137;48;2;255;10;117m▄\x1b[0m\x1b[38;2;254;45;114;48;2;255;10;90m▄\x1b[0m\x1b[38;2;254;45;91;48;2;255;10;63m▄\x1b[0m\x1b[38;2;254;45;68;48;2;255;10;36m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;36mAutomatic color conversion\x1b[0m \x1b[38;2;255;117;117;48;2;255;81;81m▄\x1b[0m\x1b[38;2;255;132;117;48;2;255;100;81m▄\x1b[0m\x1b[38;2;255;147;117;48;2;255;119;81m▄\x1b[0m\x1b[38;2;255;162;117;48;2;255;138;81m▄\x1b[0m\x1b[38;2;255;177;117;48;2;255;157;81m▄\x1b[0m\x1b[38;2;255;192;117;48;2;255;176;81m▄\x1b[0m\x1b[38;2;255;207;117;48;2;255;195;81m▄\x1b[0m\x1b[38;2;255;222;117;48;2;255;214;81m▄\x1b[0m\x1b[38;2;255;237;117;48;2;255;232;81m▄\x1b[0m\x1b[38;2;255;252;117;48;2;255;251;81m▄\x1b[0m\x1b[38;2;242;255;117;48;2;239;255;81m▄\x1b[0m\x1b[38;2;227;255;117;48;2;220;255;81m▄\x1b[0m\x1b[38;2;212;255;117;48;2;201;255;81m▄\x1b[0m\x1b[38;2;197;255;117;48;2;182;255;81m▄\x1b[0m\x1b[38;2;182;255;117;48;2;163;255;81m▄\x1b[0m\x1b[38;2;167;255;117;48;2;144;255;81m▄\x1b[0m\x1b[38;2;152;255;117;48;2;125;255;81m▄\x1b[0m\x1b[38;2;137;255;117;48;2;106;255;81m▄\x1b[0m\x1b[38;2;122;255;117;48;2;87;255;81m▄\x1b[0m\x1b[38;2;117;255;127;48;2;81;255;94m▄\x1b[0m\x1b[38;2;117;255;142;48;2;81;255;113m▄\x1b[0m\x1b[38;2;117;255;157;48;2;81;255;132m▄\x1b[0m\x1b[38;2;117;255;172;48;2;81;255;150m▄\x1b[0m\x1b[38;2;117;255;187;48;2;81;255;169m▄\x1b[0m\x1b[38;2;117;255;202;48;2;81;255;188m▄\x1b[0m\x1b[38;2;117;255;217;48;2;81;255;207m▄\x1b[0m\x1b[38;2;117;255;232;48;2;81;255;226m▄\x1b[0m\x1b[38;2;117;255;247;48;2;81;255;245m▄\x1b[0m\x1b[38;2;117;247;255;48;2;81;245;255m▄\x1b[0m\x1b[38;2;117;232;255;48;2;81;226;255m▄\x1b[0m\x1b[38;2;117;217;255;48;2;81;207;255m▄\x1b[0m\x1b[38;2;117;202;255;48;2;81;188;255m▄\x1b[0m\x1b[38;2;117;187;255;48;2;81;169;255m▄\x1b[0m\x1b[38;2;117;172;255;48;2;81;150;255m▄\x1b[0m\x1b[38;2;117;157;255;48;2;81;132;255m▄\x1b[0m\x1b[38;2;117;142;255;48;2;81;113;255m▄\x1b[0m\x1b[38;2;117;127;255;48;2;81;94;255m▄\x1b[0m\x1b[38;2;122;117;255;48;2;87;81;255m▄\x1b[0m\x1b[38;2;137;117;255;48;2;106;81;255m▄\x1b[0m\x1b[38;2;152;117;255;48;2;125;81;255m▄\x1b[0m\x1b[38;2;167;117;255;48;2;144;81;255m▄\x1b[0m\x1b[38;2;182;117;255;48;2;163;81;255m▄\x1b[0m\x1b[38;2;197;117;255;48;2;182;81;255m▄\x1b[0m\x1b[38;2;212;117;255;48;2;201;81;255m▄\x1b[0m\x1b[38;2;227;117;255;48;2;220;81;255m▄\x1b[0m\x1b[38;2;242;117;255;48;2;239;81;255m▄\x1b[0m\x1b[38;2;255;117;252;48;2;255;81;251m▄\x1b[0m\x1b[38;2;255;117;237;48;2;255;81;232m▄\x1b[0m\x1b[38;2;255;117;222;48;2;255;81;214m▄\x1b[0m\x1b[38;2;255;117;207;48;2;255;81;195m▄\x1b[0m\x1b[38;2;255;117;192;48;2;255;81;176m▄\x1b[0m\x1b[38;2;255;117;177;48;2;255;81;157m▄\x1b[0m\x1b[38;2;255;117;162;48;2;255;81;138m▄\x1b[0m\x1b[38;2;255;117;147;48;2;255;81;119m▄\x1b[0m\x1b[38;2;255;117;132;48;2;255;81;100m▄\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Styles \x1b[0m\x1b[1;31m \x1b[0mAll ansi styles: \x1b[1mbold\x1b[0m, \x1b[2mdim\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[4munderline\x1b[0m, \x1b[9mstrikethrough\x1b[0m, \x1b[7mreverse\x1b[0m, and even \n\x1b[1;31m \x1b[0m\x1b[5mblink\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Text \x1b[0m\x1b[1;31m \x1b[0mWord wrap text. Justify \x1b[32mleft\x1b[0m, \x1b[33mcenter\x1b[0m, \x1b[34mright\x1b[0m or \x1b[31mfull\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mLorem ipsum dolor \x1b[0m \x1b[33m Lorem ipsum dolor \x1b[0m \x1b[34m Lorem ipsum dolor\x1b[0m \x1b[31mLorem\x1b[0m\x1b[31m \x1b[0m\x1b[31mipsum\x1b[0m\x1b[31m \x1b[0m\x1b[31mdolor\x1b[0m\x1b[31m \x1b[0m\x1b[31msit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msit amet, \x1b[0m \x1b[33m sit amet, \x1b[0m \x1b[34m sit amet,\x1b[0m \x1b[31mamet,\x1b[0m\x1b[31m \x1b[0m\x1b[31mconsectetur\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mconsectetur \x1b[0m \x1b[33m consectetur \x1b[0m \x1b[34m consectetur\x1b[0m \x1b[31madipiscing\x1b[0m\x1b[31m \x1b[0m\x1b[31melit.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32madipiscing elit. \x1b[0m \x1b[33m adipiscing elit. \x1b[0m \x1b[34m adipiscing elit.\x1b[0m \x1b[31mQuisque\x1b[0m\x1b[31m \x1b[0m\x1b[31min\x1b[0m\x1b[31m \x1b[0m\x1b[31mmetus\x1b[0m\x1b[31m \x1b[0m\x1b[31msed\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mQuisque in metus sed\x1b[0m \x1b[33mQuisque in metus sed\x1b[0m \x1b[34mQuisque in metus sed\x1b[0m \x1b[31msapien\x1b[0m\x1b[31m \x1b[0m\x1b[31multricies\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msapien ultricies \x1b[0m \x1b[33m sapien ultricies \x1b[0m \x1b[34m sapien ultricies\x1b[0m \x1b[31mpretium\x1b[0m\x1b[31m \x1b[0m\x1b[31ma\x1b[0m\x1b[31m \x1b[0m\x1b[31mat\x1b[0m\x1b[31m \x1b[0m\x1b[31mjusto.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mpretium a at justo. \x1b[0m \x1b[33mpretium a at justo. \x1b[0m \x1b[34m pretium a at justo.\x1b[0m \x1b[31mMaecenas\x1b[0m\x1b[31m \x1b[0m\x1b[31mluctus\x1b[0m\x1b[31m \x1b[0m\x1b[31mvelit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mMaecenas luctus \x1b[0m \x1b[33m Maecenas luctus \x1b[0m \x1b[34m Maecenas luctus\x1b[0m \x1b[31met auctor maximus.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mvelit et auctor \x1b[0m \x1b[33m velit et auctor \x1b[0m \x1b[34m velit et auctor\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mmaximus. \x1b[0m \x1b[33m maximus. \x1b[0m \x1b[34m maximus.\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Asian \x1b[0m\x1b[1;31m \x1b[0m🇨🇳 该库支持中文,日文和韩文文本! \n\x1b[1;31m \x1b[0m\x1b[1;31m language \x1b[0m\x1b[1;31m \x1b[0m🇯🇵 ライブラリは中国語、日本語、韓国語のテキストをサポートしています \n\x1b[1;31m \x1b[0m\x1b[1;31m support \x1b[0m\x1b[1;31m \x1b[0m🇰🇷 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markup \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;35mRich\x1b[0m supports a simple \x1b[3mbbcode\x1b[0m-like \x1b[1mmarkup\x1b[0m for \x1b[33mcolor\x1b[0m, \x1b[4mstyle\x1b[0m, and emoji! 👍 🍎 🐜 🐻 … \n\x1b[1;31m \x1b[0m🚌 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Tables \x1b[0m\x1b[1;31m \x1b[0m\x1b[1m \x1b[0m\x1b[1;32mDate\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;34mTitle\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;36mProduction Budget\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m \x1b[0m\x1b[1;35mBox Office\x1b[0m\x1b[1m \x1b[0m \n\x1b[1;31m \x1b[0m───────────────────────────────────────────────────────────────────────────────────── \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 20, 2019\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars: The Rise of \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $275,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[35m $375,126,118\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mSkywalker \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 25, 2018\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[1;2;34mSolo\x1b[0m\x1b[2;34m: A Star Wars Story \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $275,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m $393,151,347\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 15, 2017\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars Ep. VIII: The Last \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $262,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[1;35m$1,332,539,889\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mJedi \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 19, 1999\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;34mStar Wars Ep. \x1b[0m\x1b[1;2;34mI\x1b[0m\x1b[2;34m: \x1b[0m\x1b[2;3;34mThe phantom \x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $115,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m$1,027,044,677\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;3;34mMenace\x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Syntax \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 1 \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34miter_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m \x1b[1m{\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31mhighlighting\x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m\"\"\"Iterate and generate a tuple w\x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'foo'\x1b[0m: \x1b[1m[\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m & \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1;36m3.1427\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;31m pretty \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m(\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m printing \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_va\x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Paul Atreides'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Vladimir Harkonnen'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Thufir Hawat'\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[1m]\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'atomic'\x1b[0m: \x1b[1m(\x1b[0m\x1b[3;91mFalse\x1b[0m, \x1b[3;92mTrue\x1b[0m, \x1b[3;35mNone\x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m11 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[1m}\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markdown \x1b[0m\x1b[1;31m \x1b[0m\x1b[36m# Markdown\x1b[0m ╔═══════════════════════════════════════╗ \n\x1b[1;31m \x1b[0m ║ \x1b[1mMarkdown\x1b[0m ║ \n\x1b[1;31m \x1b[0m\x1b[36mSupports much of the *markdown* \x1b[0m ╚═══════════════════════════════════════╝ \n\x1b[1;31m \x1b[0m\x1b[36m__syntax__!\x1b[0m \n\x1b[1;31m \x1b[0m Supports much of the \x1b[3mmarkdown\x1b[0m \x1b[1msyntax\x1b[0m! \n\x1b[1;31m \x1b[0m\x1b[36m- Headers\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Basic formatting: **bold**, *italic*, \x1b[0m \x1b[1;33m • \x1b[0mHeaders \n\x1b[1;31m \x1b[0m\x1b[36m`code`\x1b[0m \x1b[1;33m • \x1b[0mBasic formatting: \x1b[1mbold\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[97;40mcode\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Block quotes\x1b[0m \x1b[1;33m • \x1b[0mBlock quotes \n\x1b[1;31m \x1b[0m\x1b[36m- Lists, and more...\x1b[0m \x1b[1;33m • \x1b[0mLists, and more... \n\x1b[1;31m \x1b[0m\x1b[36m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m +more! \x1b[0m\x1b[1;31m \x1b[0mProgress bars, columns, styled logging handler, tracebacks, etc... \n\x1b[1;31m \x1b[0m \n" +expected = "\x1b[3m Rich features \x1b[0m\n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Colors \x1b[0m\x1b[1;31m \x1b[0m✓ \x1b[1;32m4-bit color\x1b[0m \x1b[38;2;86;0;0;48;2;51;0;0m▄\x1b[0m\x1b[38;2;86;9;0;48;2;51;5;0m▄\x1b[0m\x1b[38;2;86;18;0;48;2;51;11;0m▄\x1b[0m\x1b[38;2;86;28;0;48;2;51;16;0m▄\x1b[0m\x1b[38;2;86;37;0;48;2;51;22;0m▄\x1b[0m\x1b[38;2;86;47;0;48;2;51;27;0m▄\x1b[0m\x1b[38;2;86;56;0;48;2;51;33;0m▄\x1b[0m\x1b[38;2;86;66;0;48;2;51;38;0m▄\x1b[0m\x1b[38;2;86;75;0;48;2;51;44;0m▄\x1b[0m\x1b[38;2;86;85;0;48;2;51;50;0m▄\x1b[0m\x1b[38;2;78;86;0;48;2;46;51;0m▄\x1b[0m\x1b[38;2;69;86;0;48;2;40;51;0m▄\x1b[0m\x1b[38;2;59;86;0;48;2;35;51;0m▄\x1b[0m\x1b[38;2;50;86;0;48;2;29;51;0m▄\x1b[0m\x1b[38;2;40;86;0;48;2;24;51;0m▄\x1b[0m\x1b[38;2;31;86;0;48;2;18;51;0m▄\x1b[0m\x1b[38;2;22;86;0;48;2;12;51;0m▄\x1b[0m\x1b[38;2;12;86;0;48;2;7;51;0m▄\x1b[0m\x1b[38;2;3;86;0;48;2;1;51;0m▄\x1b[0m\x1b[38;2;0;86;6;48;2;0;51;3m▄\x1b[0m\x1b[38;2;0;86;15;48;2;0;51;9m▄\x1b[0m\x1b[38;2;0;86;25;48;2;0;51;14m▄\x1b[0m\x1b[38;2;0;86;34;48;2;0;51;20m▄\x1b[0m\x1b[38;2;0;86;44;48;2;0;51;25m▄\x1b[0m\x1b[38;2;0;86;53;48;2;0;51;31m▄\x1b[0m\x1b[38;2;0;86;63;48;2;0;51;37m▄\x1b[0m\x1b[38;2;0;86;72;48;2;0;51;42m▄\x1b[0m\x1b[38;2;0;86;81;48;2;0;51;48m▄\x1b[0m\x1b[38;2;0;81;86;48;2;0;48;51m▄\x1b[0m\x1b[38;2;0;72;86;48;2;0;42;51m▄\x1b[0m\x1b[38;2;0;63;86;48;2;0;37;51m▄\x1b[0m\x1b[38;2;0;53;86;48;2;0;31;51m▄\x1b[0m\x1b[38;2;0;44;86;48;2;0;25;51m▄\x1b[0m\x1b[38;2;0;34;86;48;2;0;20;51m▄\x1b[0m\x1b[38;2;0;25;86;48;2;0;14;51m▄\x1b[0m\x1b[38;2;0;15;86;48;2;0;9;51m▄\x1b[0m\x1b[38;2;0;6;86;48;2;0;3;51m▄\x1b[0m\x1b[38;2;3;0;86;48;2;1;0;51m▄\x1b[0m\x1b[38;2;12;0;86;48;2;7;0;51m▄\x1b[0m\x1b[38;2;22;0;86;48;2;12;0;51m▄\x1b[0m\x1b[38;2;31;0;86;48;2;18;0;51m▄\x1b[0m\x1b[38;2;40;0;86;48;2;24;0;51m▄\x1b[0m\x1b[38;2;50;0;86;48;2;29;0;51m▄\x1b[0m\x1b[38;2;59;0;86;48;2;35;0;51m▄\x1b[0m\x1b[38;2;69;0;86;48;2;40;0;51m▄\x1b[0m\x1b[38;2;78;0;86;48;2;46;0;51m▄\x1b[0m\x1b[38;2;86;0;85;48;2;51;0;50m▄\x1b[0m\x1b[38;2;86;0;75;48;2;51;0;44m▄\x1b[0m\x1b[38;2;86;0;66;48;2;51;0;38m▄\x1b[0m\x1b[38;2;86;0;56;48;2;51;0;33m▄\x1b[0m\x1b[38;2;86;0;47;48;2;51;0;27m▄\x1b[0m\x1b[38;2;86;0;37;48;2;51;0;22m▄\x1b[0m\x1b[38;2;86;0;28;48;2;51;0;16m▄\x1b[0m\x1b[38;2;86;0;18;48;2;51;0;11m▄\x1b[0m\x1b[38;2;86;0;9;48;2;51;0;5m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;34m8-bit color\x1b[0m \x1b[38;2;158;0;0;48;2;122;0;0m▄\x1b[0m\x1b[38;2;158;17;0;48;2;122;13;0m▄\x1b[0m\x1b[38;2;158;34;0;48;2;122;26;0m▄\x1b[0m\x1b[38;2;158;51;0;48;2;122;40;0m▄\x1b[0m\x1b[38;2;158;68;0;48;2;122;53;0m▄\x1b[0m\x1b[38;2;158;86;0;48;2;122;66;0m▄\x1b[0m\x1b[38;2;158;103;0;48;2;122;80;0m▄\x1b[0m\x1b[38;2;158;120;0;48;2;122;93;0m▄\x1b[0m\x1b[38;2;158;137;0;48;2;122;106;0m▄\x1b[0m\x1b[38;2;158;155;0;48;2;122;120;0m▄\x1b[0m\x1b[38;2;143;158;0;48;2;111;122;0m▄\x1b[0m\x1b[38;2;126;158;0;48;2;97;122;0m▄\x1b[0m\x1b[38;2;109;158;0;48;2;84;122;0m▄\x1b[0m\x1b[38;2;91;158;0;48;2;71;122;0m▄\x1b[0m\x1b[38;2;74;158;0;48;2;57;122;0m▄\x1b[0m\x1b[38;2;57;158;0;48;2;44;122;0m▄\x1b[0m\x1b[38;2;40;158;0;48;2;31;122;0m▄\x1b[0m\x1b[38;2;22;158;0;48;2;17;122;0m▄\x1b[0m\x1b[38;2;5;158;0;48;2;4;122;0m▄\x1b[0m\x1b[38;2;0;158;11;48;2;0;122;8m▄\x1b[0m\x1b[38;2;0;158;28;48;2;0;122;22m▄\x1b[0m\x1b[38;2;0;158;45;48;2;0;122;35m▄\x1b[0m\x1b[38;2;0;158;63;48;2;0;122;48m▄\x1b[0m\x1b[38;2;0;158;80;48;2;0;122;62m▄\x1b[0m\x1b[38;2;0;158;97;48;2;0;122;75m▄\x1b[0m\x1b[38;2;0;158;114;48;2;0;122;89m▄\x1b[0m\x1b[38;2;0;158;132;48;2;0;122;102m▄\x1b[0m\x1b[38;2;0;158;149;48;2;0;122;115m▄\x1b[0m\x1b[38;2;0;149;158;48;2;0;115;122m▄\x1b[0m\x1b[38;2;0;132;158;48;2;0;102;122m▄\x1b[0m\x1b[38;2;0;114;158;48;2;0;89;122m▄\x1b[0m\x1b[38;2;0;97;158;48;2;0;75;122m▄\x1b[0m\x1b[38;2;0;80;158;48;2;0;62;122m▄\x1b[0m\x1b[38;2;0;63;158;48;2;0;48;122m▄\x1b[0m\x1b[38;2;0;45;158;48;2;0;35;122m▄\x1b[0m\x1b[38;2;0;28;158;48;2;0;22;122m▄\x1b[0m\x1b[38;2;0;11;158;48;2;0;8;122m▄\x1b[0m\x1b[38;2;5;0;158;48;2;4;0;122m▄\x1b[0m\x1b[38;2;22;0;158;48;2;17;0;122m▄\x1b[0m\x1b[38;2;40;0;158;48;2;31;0;122m▄\x1b[0m\x1b[38;2;57;0;158;48;2;44;0;122m▄\x1b[0m\x1b[38;2;74;0;158;48;2;57;0;122m▄\x1b[0m\x1b[38;2;91;0;158;48;2;71;0;122m▄\x1b[0m\x1b[38;2;109;0;158;48;2;84;0;122m▄\x1b[0m\x1b[38;2;126;0;158;48;2;97;0;122m▄\x1b[0m\x1b[38;2;143;0;158;48;2;111;0;122m▄\x1b[0m\x1b[38;2;158;0;155;48;2;122;0;120m▄\x1b[0m\x1b[38;2;158;0;137;48;2;122;0;106m▄\x1b[0m\x1b[38;2;158;0;120;48;2;122;0;93m▄\x1b[0m\x1b[38;2;158;0;103;48;2;122;0;80m▄\x1b[0m\x1b[38;2;158;0;86;48;2;122;0;66m▄\x1b[0m\x1b[38;2;158;0;68;48;2;122;0;53m▄\x1b[0m\x1b[38;2;158;0;51;48;2;122;0;40m▄\x1b[0m\x1b[38;2;158;0;34;48;2;122;0;26m▄\x1b[0m\x1b[38;2;158;0;17;48;2;122;0;13m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;35mTruecolor (16.7 million)\x1b[0m \x1b[38;2;229;0;0;48;2;193;0;0m▄\x1b[0m\x1b[38;2;229;25;0;48;2;193;21;0m▄\x1b[0m\x1b[38;2;229;50;0;48;2;193;42;0m▄\x1b[0m\x1b[38;2;229;75;0;48;2;193;63;0m▄\x1b[0m\x1b[38;2;229;100;0;48;2;193;84;0m▄\x1b[0m\x1b[38;2;229;125;0;48;2;193;105;0m▄\x1b[0m\x1b[38;2;229;150;0;48;2;193;126;0m▄\x1b[0m\x1b[38;2;229;175;0;48;2;193;147;0m▄\x1b[0m\x1b[38;2;229;200;0;48;2;193;169;0m▄\x1b[0m\x1b[38;2;229;225;0;48;2;193;190;0m▄\x1b[0m\x1b[38;2;208;229;0;48;2;176;193;0m▄\x1b[0m\x1b[38;2;183;229;0;48;2;155;193;0m▄\x1b[0m\x1b[38;2;158;229;0;48;2;133;193;0m▄\x1b[0m\x1b[38;2;133;229;0;48;2;112;193;0m▄\x1b[0m\x1b[38;2;108;229;0;48;2;91;193;0m▄\x1b[0m\x1b[38;2;83;229;0;48;2;70;193;0m▄\x1b[0m\x1b[38;2;58;229;0;48;2;49;193;0m▄\x1b[0m\x1b[38;2;33;229;0;48;2;28;193;0m▄\x1b[0m\x1b[38;2;8;229;0;48;2;7;193;0m▄\x1b[0m\x1b[38;2;0;229;16;48;2;0;193;14m▄\x1b[0m\x1b[38;2;0;229;41;48;2;0;193;35m▄\x1b[0m\x1b[38;2;0;229;66;48;2;0;193;56m▄\x1b[0m\x1b[38;2;0;229;91;48;2;0;193;77m▄\x1b[0m\x1b[38;2;0;229;116;48;2;0;193;98m▄\x1b[0m\x1b[38;2;0;229;141;48;2;0;193;119m▄\x1b[0m\x1b[38;2;0;229;166;48;2;0;193;140m▄\x1b[0m\x1b[38;2;0;229;191;48;2;0;193;162m▄\x1b[0m\x1b[38;2;0;229;216;48;2;0;193;183m▄\x1b[0m\x1b[38;2;0;216;229;48;2;0;183;193m▄\x1b[0m\x1b[38;2;0;191;229;48;2;0;162;193m▄\x1b[0m\x1b[38;2;0;166;229;48;2;0;140;193m▄\x1b[0m\x1b[38;2;0;141;229;48;2;0;119;193m▄\x1b[0m\x1b[38;2;0;116;229;48;2;0;98;193m▄\x1b[0m\x1b[38;2;0;91;229;48;2;0;77;193m▄\x1b[0m\x1b[38;2;0;66;229;48;2;0;56;193m▄\x1b[0m\x1b[38;2;0;41;229;48;2;0;35;193m▄\x1b[0m\x1b[38;2;0;16;229;48;2;0;14;193m▄\x1b[0m\x1b[38;2;8;0;229;48;2;7;0;193m▄\x1b[0m\x1b[38;2;33;0;229;48;2;28;0;193m▄\x1b[0m\x1b[38;2;58;0;229;48;2;49;0;193m▄\x1b[0m\x1b[38;2;83;0;229;48;2;70;0;193m▄\x1b[0m\x1b[38;2;108;0;229;48;2;91;0;193m▄\x1b[0m\x1b[38;2;133;0;229;48;2;112;0;193m▄\x1b[0m\x1b[38;2;158;0;229;48;2;133;0;193m▄\x1b[0m\x1b[38;2;183;0;229;48;2;155;0;193m▄\x1b[0m\x1b[38;2;208;0;229;48;2;176;0;193m▄\x1b[0m\x1b[38;2;229;0;225;48;2;193;0;190m▄\x1b[0m\x1b[38;2;229;0;200;48;2;193;0;169m▄\x1b[0m\x1b[38;2;229;0;175;48;2;193;0;147m▄\x1b[0m\x1b[38;2;229;0;150;48;2;193;0;126m▄\x1b[0m\x1b[38;2;229;0;125;48;2;193;0;105m▄\x1b[0m\x1b[38;2;229;0;100;48;2;193;0;84m▄\x1b[0m\x1b[38;2;229;0;75;48;2;193;0;63m▄\x1b[0m\x1b[38;2;229;0;50;48;2;193;0;42m▄\x1b[0m\x1b[38;2;229;0;25;48;2;193;0;21m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;33mDumb terminals\x1b[0m \x1b[38;2;254;45;45;48;2;255;10;10m▄\x1b[0m\x1b[38;2;254;68;45;48;2;255;36;10m▄\x1b[0m\x1b[38;2;254;91;45;48;2;255;63;10m▄\x1b[0m\x1b[38;2;254;114;45;48;2;255;90;10m▄\x1b[0m\x1b[38;2;254;137;45;48;2;255;117;10m▄\x1b[0m\x1b[38;2;254;159;45;48;2;255;143;10m▄\x1b[0m\x1b[38;2;254;182;45;48;2;255;170;10m▄\x1b[0m\x1b[38;2;254;205;45;48;2;255;197;10m▄\x1b[0m\x1b[38;2;254;228;45;48;2;255;223;10m▄\x1b[0m\x1b[38;2;254;251;45;48;2;255;250;10m▄\x1b[0m\x1b[38;2;235;254;45;48;2;232;255;10m▄\x1b[0m\x1b[38;2;213;254;45;48;2;206;255;10m▄\x1b[0m\x1b[38;2;190;254;45;48;2;179;255;10m▄\x1b[0m\x1b[38;2;167;254;45;48;2;152;255;10m▄\x1b[0m\x1b[38;2;144;254;45;48;2;125;255;10m▄\x1b[0m\x1b[38;2;121;254;45;48;2;99;255;10m▄\x1b[0m\x1b[38;2;99;254;45;48;2;72;255;10m▄\x1b[0m\x1b[38;2;76;254;45;48;2;45;255;10m▄\x1b[0m\x1b[38;2;53;254;45;48;2;19;255;10m▄\x1b[0m\x1b[38;2;45;254;61;48;2;10;255;28m▄\x1b[0m\x1b[38;2;45;254;83;48;2;10;255;54m▄\x1b[0m\x1b[38;2;45;254;106;48;2;10;255;81m▄\x1b[0m\x1b[38;2;45;254;129;48;2;10;255;108m▄\x1b[0m\x1b[38;2;45;254;152;48;2;10;255;134m▄\x1b[0m\x1b[38;2;45;254;175;48;2;10;255;161m▄\x1b[0m\x1b[38;2;45;254;197;48;2;10;255;188m▄\x1b[0m\x1b[38;2;45;254;220;48;2;10;255;214m▄\x1b[0m\x1b[38;2;45;254;243;48;2;10;255;241m▄\x1b[0m\x1b[38;2;45;243;254;48;2;10;241;255m▄\x1b[0m\x1b[38;2;45;220;254;48;2;10;214;255m▄\x1b[0m\x1b[38;2;45;197;254;48;2;10;188;255m▄\x1b[0m\x1b[38;2;45;175;254;48;2;10;161;255m▄\x1b[0m\x1b[38;2;45;152;254;48;2;10;134;255m▄\x1b[0m\x1b[38;2;45;129;254;48;2;10;108;255m▄\x1b[0m\x1b[38;2;45;106;254;48;2;10;81;255m▄\x1b[0m\x1b[38;2;45;83;254;48;2;10;54;255m▄\x1b[0m\x1b[38;2;45;61;254;48;2;10;28;255m▄\x1b[0m\x1b[38;2;53;45;254;48;2;19;10;255m▄\x1b[0m\x1b[38;2;76;45;254;48;2;45;10;255m▄\x1b[0m\x1b[38;2;99;45;254;48;2;72;10;255m▄\x1b[0m\x1b[38;2;121;45;254;48;2;99;10;255m▄\x1b[0m\x1b[38;2;144;45;254;48;2;125;10;255m▄\x1b[0m\x1b[38;2;167;45;254;48;2;152;10;255m▄\x1b[0m\x1b[38;2;190;45;254;48;2;179;10;255m▄\x1b[0m\x1b[38;2;213;45;254;48;2;206;10;255m▄\x1b[0m\x1b[38;2;235;45;254;48;2;232;10;255m▄\x1b[0m\x1b[38;2;254;45;251;48;2;255;10;250m▄\x1b[0m\x1b[38;2;254;45;228;48;2;255;10;223m▄\x1b[0m\x1b[38;2;254;45;205;48;2;255;10;197m▄\x1b[0m\x1b[38;2;254;45;182;48;2;255;10;170m▄\x1b[0m\x1b[38;2;254;45;159;48;2;255;10;143m▄\x1b[0m\x1b[38;2;254;45;137;48;2;255;10;117m▄\x1b[0m\x1b[38;2;254;45;114;48;2;255;10;90m▄\x1b[0m\x1b[38;2;254;45;91;48;2;255;10;63m▄\x1b[0m\x1b[38;2;254;45;68;48;2;255;10;36m▄\x1b[0m \n\x1b[1;31m \x1b[0m✓ \x1b[1;36mAutomatic color conversion\x1b[0m \x1b[38;2;255;117;117;48;2;255;81;81m▄\x1b[0m\x1b[38;2;255;132;117;48;2;255;100;81m▄\x1b[0m\x1b[38;2;255;147;117;48;2;255;119;81m▄\x1b[0m\x1b[38;2;255;162;117;48;2;255;138;81m▄\x1b[0m\x1b[38;2;255;177;117;48;2;255;157;81m▄\x1b[0m\x1b[38;2;255;192;117;48;2;255;176;81m▄\x1b[0m\x1b[38;2;255;207;117;48;2;255;195;81m▄\x1b[0m\x1b[38;2;255;222;117;48;2;255;214;81m▄\x1b[0m\x1b[38;2;255;237;117;48;2;255;232;81m▄\x1b[0m\x1b[38;2;255;252;117;48;2;255;251;81m▄\x1b[0m\x1b[38;2;242;255;117;48;2;239;255;81m▄\x1b[0m\x1b[38;2;227;255;117;48;2;220;255;81m▄\x1b[0m\x1b[38;2;212;255;117;48;2;201;255;81m▄\x1b[0m\x1b[38;2;197;255;117;48;2;182;255;81m▄\x1b[0m\x1b[38;2;182;255;117;48;2;163;255;81m▄\x1b[0m\x1b[38;2;167;255;117;48;2;144;255;81m▄\x1b[0m\x1b[38;2;152;255;117;48;2;125;255;81m▄\x1b[0m\x1b[38;2;137;255;117;48;2;106;255;81m▄\x1b[0m\x1b[38;2;122;255;117;48;2;87;255;81m▄\x1b[0m\x1b[38;2;117;255;127;48;2;81;255;94m▄\x1b[0m\x1b[38;2;117;255;142;48;2;81;255;113m▄\x1b[0m\x1b[38;2;117;255;157;48;2;81;255;132m▄\x1b[0m\x1b[38;2;117;255;172;48;2;81;255;150m▄\x1b[0m\x1b[38;2;117;255;187;48;2;81;255;169m▄\x1b[0m\x1b[38;2;117;255;202;48;2;81;255;188m▄\x1b[0m\x1b[38;2;117;255;217;48;2;81;255;207m▄\x1b[0m\x1b[38;2;117;255;232;48;2;81;255;226m▄\x1b[0m\x1b[38;2;117;255;247;48;2;81;255;245m▄\x1b[0m\x1b[38;2;117;247;255;48;2;81;245;255m▄\x1b[0m\x1b[38;2;117;232;255;48;2;81;226;255m▄\x1b[0m\x1b[38;2;117;217;255;48;2;81;207;255m▄\x1b[0m\x1b[38;2;117;202;255;48;2;81;188;255m▄\x1b[0m\x1b[38;2;117;187;255;48;2;81;169;255m▄\x1b[0m\x1b[38;2;117;172;255;48;2;81;150;255m▄\x1b[0m\x1b[38;2;117;157;255;48;2;81;132;255m▄\x1b[0m\x1b[38;2;117;142;255;48;2;81;113;255m▄\x1b[0m\x1b[38;2;117;127;255;48;2;81;94;255m▄\x1b[0m\x1b[38;2;122;117;255;48;2;87;81;255m▄\x1b[0m\x1b[38;2;137;117;255;48;2;106;81;255m▄\x1b[0m\x1b[38;2;152;117;255;48;2;125;81;255m▄\x1b[0m\x1b[38;2;167;117;255;48;2;144;81;255m▄\x1b[0m\x1b[38;2;182;117;255;48;2;163;81;255m▄\x1b[0m\x1b[38;2;197;117;255;48;2;182;81;255m▄\x1b[0m\x1b[38;2;212;117;255;48;2;201;81;255m▄\x1b[0m\x1b[38;2;227;117;255;48;2;220;81;255m▄\x1b[0m\x1b[38;2;242;117;255;48;2;239;81;255m▄\x1b[0m\x1b[38;2;255;117;252;48;2;255;81;251m▄\x1b[0m\x1b[38;2;255;117;237;48;2;255;81;232m▄\x1b[0m\x1b[38;2;255;117;222;48;2;255;81;214m▄\x1b[0m\x1b[38;2;255;117;207;48;2;255;81;195m▄\x1b[0m\x1b[38;2;255;117;192;48;2;255;81;176m▄\x1b[0m\x1b[38;2;255;117;177;48;2;255;81;157m▄\x1b[0m\x1b[38;2;255;117;162;48;2;255;81;138m▄\x1b[0m\x1b[38;2;255;117;147;48;2;255;81;119m▄\x1b[0m\x1b[38;2;255;117;132;48;2;255;81;100m▄\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Styles \x1b[0m\x1b[1;31m \x1b[0mAll ansi styles: \x1b[1mbold\x1b[0m, \x1b[2mdim\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[4munderline\x1b[0m, \x1b[9mstrikethrough\x1b[0m, \x1b[7mreverse\x1b[0m, and even \n\x1b[1;31m \x1b[0m\x1b[5mblink\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Text \x1b[0m\x1b[1;31m \x1b[0mWord wrap text. Justify \x1b[32mleft\x1b[0m, \x1b[33mcenter\x1b[0m, \x1b[34mright\x1b[0m or \x1b[31mfull\x1b[0m. \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mLorem ipsum dolor \x1b[0m \x1b[33m Lorem ipsum dolor \x1b[0m \x1b[34m Lorem ipsum dolor\x1b[0m \x1b[31mLorem\x1b[0m\x1b[31m \x1b[0m\x1b[31mipsum\x1b[0m\x1b[31m \x1b[0m\x1b[31mdolor\x1b[0m\x1b[31m \x1b[0m\x1b[31msit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msit amet, \x1b[0m \x1b[33m sit amet, \x1b[0m \x1b[34m sit amet,\x1b[0m \x1b[31mamet,\x1b[0m\x1b[31m \x1b[0m\x1b[31mconsectetur\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mconsectetur \x1b[0m \x1b[33m consectetur \x1b[0m \x1b[34m consectetur\x1b[0m \x1b[31madipiscing\x1b[0m\x1b[31m \x1b[0m\x1b[31melit.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32madipiscing elit. \x1b[0m \x1b[33m adipiscing elit. \x1b[0m \x1b[34m adipiscing elit.\x1b[0m \x1b[31mQuisque\x1b[0m\x1b[31m \x1b[0m\x1b[31min\x1b[0m\x1b[31m \x1b[0m\x1b[31mmetus\x1b[0m\x1b[31m \x1b[0m\x1b[31msed\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mQuisque in metus sed\x1b[0m \x1b[33mQuisque in metus sed\x1b[0m \x1b[34mQuisque in metus sed\x1b[0m \x1b[31msapien\x1b[0m\x1b[31m \x1b[0m\x1b[31multricies\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32msapien ultricies \x1b[0m \x1b[33m sapien ultricies \x1b[0m \x1b[34m sapien ultricies\x1b[0m \x1b[31mpretium\x1b[0m\x1b[31m \x1b[0m\x1b[31ma\x1b[0m\x1b[31m \x1b[0m\x1b[31mat\x1b[0m\x1b[31m \x1b[0m\x1b[31mjusto.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mpretium a at justo. \x1b[0m \x1b[33mpretium a at justo. \x1b[0m \x1b[34m pretium a at justo.\x1b[0m \x1b[31mMaecenas\x1b[0m\x1b[31m \x1b[0m\x1b[31mluctus\x1b[0m\x1b[31m \x1b[0m\x1b[31mvelit\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mMaecenas luctus \x1b[0m \x1b[33m Maecenas luctus \x1b[0m \x1b[34m Maecenas luctus\x1b[0m \x1b[31met auctor maximus.\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mvelit et auctor \x1b[0m \x1b[33m velit et auctor \x1b[0m \x1b[34m velit et auctor\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32mmaximus. \x1b[0m \x1b[33m maximus. \x1b[0m \x1b[34m maximus.\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Asian \x1b[0m\x1b[1;31m \x1b[0m🇨🇳 该库支持中文,日文和韩文文本! \n\x1b[1;31m \x1b[0m\x1b[1;31m language \x1b[0m\x1b[1;31m \x1b[0m🇯🇵 ライブラリは中国語、日本語、韓国語のテキストをサポートしています \n\x1b[1;31m \x1b[0m\x1b[1;31m support \x1b[0m\x1b[1;31m \x1b[0m🇰🇷 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markup \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;35mRich\x1b[0m supports a simple \x1b[3mbbcode\x1b[0m-like \x1b[1mmarkup\x1b[0m for \x1b[33mcolor\x1b[0m, \x1b[4mstyle\x1b[0m, and emoji! 👍 🍎 🐜 🐻 … \n\x1b[1;31m \x1b[0m🚌 \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Tables \x1b[0m\x1b[1;31m \x1b[0m\x1b[1m \x1b[0m\x1b[1;32mDate\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;34mTitle\x1b[0m\x1b[1m \x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1;36mProduction Budget\x1b[0m\x1b[1m \x1b[0m \x1b[1m \x1b[0m\x1b[1m \x1b[0m\x1b[1;35mBox Office\x1b[0m\x1b[1m \x1b[0m \n\x1b[1;31m \x1b[0m───────────────────────────────────────────────────────────────────────────────────── \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 20, 2019\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars: The Rise of \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $275,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[35m $375,126,118\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mSkywalker \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 25, 2018\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[1;2;34mSolo\x1b[0m\x1b[2;34m: A Star Wars Story \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $275,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m $393,151,347\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m\x1b[32mDec 15, 2017\x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mStar Wars Ep. VIII: The Last \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m\x1b[36m $262,000,000\x1b[0m\x1b[36m \x1b[0m \x1b[35m \x1b[0m\x1b[1;35m$1,332,539,889\x1b[0m\x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[32m \x1b[0m \x1b[34m \x1b[0m\x1b[34mJedi \x1b[0m\x1b[34m \x1b[0m \x1b[36m \x1b[0m \x1b[35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m\x1b[2;32mMay 19, 1999\x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;34mStar Wars Ep. \x1b[0m\x1b[1;2;34mI\x1b[0m\x1b[2;34m: \x1b[0m\x1b[2;3;34mThe phantom \x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m\x1b[2;36m $115,000,000\x1b[0m\x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m\x1b[2;35m$1,027,044,677\x1b[0m\x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[2;32m \x1b[0m \x1b[2;34m \x1b[0m\x1b[2;3;34mMenace\x1b[0m\x1b[2;34m \x1b[0m\x1b[2;34m \x1b[0m \x1b[2;36m \x1b[0m \x1b[2;35m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Syntax \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 1 \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mdef\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34miter_last\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mIterable\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m[\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mT\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m]\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m-\x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m>\x1b[0m \x1b[1m{\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31mhighlighting\x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 2 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;230;219;116;48;2;39;40;34m\"\"\"Iterate and generate a tuple w\x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'foo'\x1b[0m: \x1b[1m[\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m & \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 3 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalues\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m)\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1;36m3.1427\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;31m pretty \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 4 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mtry\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m(\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m printing \x1b[0m\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 5 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mnext\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m(\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_va\x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Paul Atreides'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 6 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mexcept\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;166;226;46;48;2;39;40;34mStopIteration\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Vladimir Harkonnen'\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 7 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mreturn\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ │ \x1b[0m\x1b[32m'Thufir Hawat'\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 8 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mfor\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34min\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34miter_values\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m:\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ │ \x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m 9 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mFalse\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[1m]\x1b[0m, \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m10 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ │ \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;249;38;114;48;2;39;40;34m=\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mvalue\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[2;32m│ \x1b[0m\x1b[32m'atomic'\x1b[0m: \x1b[1m(\x1b[0m\x1b[3;91mFalse\x1b[0m, \x1b[3;92mTrue\x1b[0m, \x1b[3;35mNone\x1b[0m\x1b[1m)\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;38;2;227;227;221;48;2;39;40;34m \x1b[0m\x1b[38;2;101;102;96;48;2;39;40;34m11 \x1b[0m\x1b[2;38;2;117;113;94;48;2;39;40;34m│ \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34myield\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;102;217;239;48;2;39;40;34mTrue\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m,\x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34m \x1b[0m\x1b[38;2;248;248;242;48;2;39;40;34mprevious_value\x1b[0m\x1b[48;2;39;40;34m \x1b[0m \x1b[1m}\x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m Markdown \x1b[0m\x1b[1;31m \x1b[0m\x1b[36m# Markdown\x1b[0m ╔═══════════════════════════════════════╗ \n\x1b[1;31m \x1b[0m ║ \x1b[1mMarkdown\x1b[0m ║ \n\x1b[1;31m \x1b[0m\x1b[36mSupports much of the *markdown* \x1b[0m ╚═══════════════════════════════════════╝ \n\x1b[1;31m \x1b[0m\x1b[36m__syntax__!\x1b[0m \n\x1b[1;31m \x1b[0m Supports much of the \x1b[3mmarkdown\x1b[0m \x1b[1msyntax\x1b[0m! \n\x1b[1;31m \x1b[0m\x1b[36m- Headers\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Basic formatting: **bold**, *italic*, \x1b[0m \x1b[1;33m • \x1b[0mHeaders \n\x1b[1;31m \x1b[0m\x1b[36m`code`\x1b[0m \x1b[1;33m • \x1b[0mBasic formatting: \x1b[1mbold\x1b[0m, \x1b[3mitalic\x1b[0m, \x1b[97;40mcode\x1b[0m \n\x1b[1;31m \x1b[0m\x1b[36m- Block quotes\x1b[0m \x1b[1;33m • \x1b[0mBlock quotes \n\x1b[1;31m \x1b[0m\x1b[36m- Lists, and more...\x1b[0m \x1b[1;33m • \x1b[0mLists, and more... \n\x1b[1;31m \x1b[0m\x1b[36m \x1b[0m \n\x1b[1;31m \x1b[0m \n\x1b[1;31m \x1b[0m\x1b[1;31m +more! \x1b[0m\x1b[1;31m \x1b[0mProgress bars, columns, styled logging handler, tracebacks, etc... \n\x1b[1;31m \x1b[0m \n" From d81cef7850f1571e2702f3d87338bee9f71a1bec Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 9 Jan 2022 10:14:48 +0000 Subject: [PATCH 222/287] changelog --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 219e7c4640..4d15e5f3ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,12 @@ 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). -## [11.0.0] - Unreleased +## [11.0.0] - 2022-01-09 ### Added -- Added max_depth arg to pretty printing -- Added `vertical_align` to Table.add_row +- Added max_depth arg to pretty printing https://github.com/Textualize/rich/issues/1585 +- Added `vertical_align` to Table.add_row https://github.com/Textualize/rich/issues/1590 ### Fixed @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **breaking** Deprecated rich.console.RenderGroup, now named rich.console.Group +- **breaking** `Syntax.__init__` parameter `lexer_name` renamed to `lexer` +- Syntax constructor accepts both str and now a pygments lexer https://github.com/Textualize/rich/pull/1748 ## [10.16.2] - 2021-01-02 From fb4f424e1cf58e2da41036d23c079bf8bd379598 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 9 Jan 2022 10:34:15 +0000 Subject: [PATCH 223/287] Version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 42b60550f5..d767145704 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.2" +version = "11.0.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From 0eec69bc2c56e9a760e84eae9fff11c1aa844845 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jan 2022 13:32:43 +0000 Subject: [PATCH 224/287] Bump types-dataclasses from 0.6.3 to 0.6.4 Bumps [types-dataclasses](https://github.com/python/typeshed) from 0.6.3 to 0.6.4. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-dataclasses dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index fd7783ecfc..ee2eaa39e1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -974,7 +974,7 @@ python-versions = "*" [[package]] name = "types-dataclasses" -version = "0.6.3" +version = "0.6.4" description = "Typing stubs for dataclasses" category = "dev" optional = false @@ -1053,7 +1053,7 @@ jupyter = ["ipywidgets"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "230d724bf180e628ff242b220bbc92431ddb15547f4790d685af63a77ff2bf6f" +content-hash = "d642a2a33643ec67d8ec48fef8ac01b7226829d0dcc3a14b10c3140005cbd0f0" [metadata.files] appnope = [ @@ -1744,8 +1744,8 @@ typed-ast = [ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] types-dataclasses = [ - {file = "types-dataclasses-0.6.3.tar.gz", hash = "sha256:dfda22409c0e514f8b5c2ff6d0ccf5f404ee84c680e9e28521ea61978ca4dc70"}, - {file = "types_dataclasses-0.6.3-py3-none-any.whl", hash = "sha256:645b511230b00e90bd6a24725f316a7e992d9f118e78d25de60d38aa07260928"}, + {file = "types-dataclasses-0.6.4.tar.gz", hash = "sha256:2f7ab6c565cf05cc7f27f31a4c2fcc803384e319aab292807b857ddf1473429f"}, + {file = "types_dataclasses-0.6.4-py3-none-any.whl", hash = "sha256:fef6ed4742ca27996530c6d549cd704772a4a86e4781841c9bb387001e369ec3"}, ] typing-extensions = [ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, diff --git a/pyproject.toml b/pyproject.toml index 30046fbdaa..4a0a6d29fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ black = "^21.11b1" mypy = "^0.930" pytest-cov = "^3.0.0" attrs = "^21.4.0" -types-dataclasses = "^0.6.3" +types-dataclasses = "^0.6.4" pre-commit = "^2.16.0" [build-system] From 98628051519a0921f152c017759dc0867edd6a1e Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 14:23:15 +0000 Subject: [PATCH 225/287] Treat all Emoji Presentation Sequences as East Asian Wide (2 term cells) --- rich/_cell_widths.py | 132 ++++++++--- rich/cells.py | 3 +- rich/emoji.py | 10 +- tools/emoji_variation_sequences.py | 355 +++++++++++++++++++++++++++++ tools/make_terminal_widths.py | 20 +- 5 files changed, 475 insertions(+), 45 deletions(-) create mode 100644 tools/emoji_variation_sequences.py diff --git a/rich/_cell_widths.py b/rich/_cell_widths.py index 36286df379..f96df929ac 100644 --- a/rich/_cell_widths.py +++ b/rich/_cell_widths.py @@ -3,7 +3,12 @@ CELL_WIDTHS = [ (0, 0, 0), (1, 31, -1), + (35, 35, 2), + (42, 42, 2), + (48, 57, 2), (127, 159, -1), + (169, 169, 2), + (174, 174, 2), (768, 879, 0), (1155, 1161, 0), (1425, 1469, 0), @@ -170,39 +175,85 @@ (7675, 7679, 0), (8203, 8207, 0), (8232, 8238, 0), + (8252, 8252, 2), + (8265, 8265, 2), (8288, 8291, 0), (8400, 8432, 0), + (8482, 8482, 2), + (8505, 8505, 2), + (8596, 8601, 2), + (8617, 8618, 2), (8986, 8987, 2), - (9001, 9002, 2), - (9193, 9196, 2), - (9200, 9200, 2), - (9203, 9203, 2), - (9725, 9726, 2), + (9000, 9002, 2), + (9167, 9167, 2), + (9193, 9203, 2), + (9208, 9210, 2), + (9410, 9410, 2), + (9642, 9643, 2), + (9654, 9654, 2), + (9664, 9664, 2), + (9723, 9726, 2), + (9728, 9732, 2), + (9742, 9742, 2), + (9745, 9745, 2), (9748, 9749, 2), + (9752, 9752, 2), + (9757, 9757, 2), + (9760, 9760, 2), + (9762, 9763, 2), + (9766, 9766, 2), + (9770, 9770, 2), + (9774, 9775, 2), + (9784, 9786, 2), + (9792, 9792, 2), + (9794, 9794, 2), (9800, 9811, 2), - (9855, 9855, 2), - (9875, 9875, 2), - (9889, 9889, 2), + (9823, 9824, 2), + (9827, 9827, 2), + (9829, 9830, 2), + (9832, 9832, 2), + (9851, 9851, 2), + (9854, 9855, 2), + (9874, 9879, 2), + (9881, 9881, 2), + (9883, 9884, 2), + (9888, 9889, 2), (9898, 9899, 2), + (9904, 9905, 2), (9917, 9918, 2), (9924, 9925, 2), - (9934, 9934, 2), - (9940, 9940, 2), - (9962, 9962, 2), - (9970, 9971, 2), - (9973, 9973, 2), - (9978, 9978, 2), + (9928, 9928, 2), + (9934, 9935, 2), + (9937, 9937, 2), + (9939, 9940, 2), + (9961, 9962, 2), + (9968, 9973, 2), + (9975, 9978, 2), (9981, 9981, 2), + (9986, 9986, 2), (9989, 9989, 2), - (9994, 9995, 2), + (9992, 9997, 2), + (9999, 9999, 2), + (10002, 10002, 2), + (10004, 10004, 2), + (10006, 10006, 2), + (10013, 10013, 2), + (10017, 10017, 2), (10024, 10024, 2), + (10035, 10036, 2), + (10052, 10052, 2), + (10055, 10055, 2), (10060, 10060, 2), (10062, 10062, 2), (10067, 10069, 2), (10071, 10071, 2), + (10083, 10084, 2), (10133, 10135, 2), + (10145, 10145, 2), (10160, 10160, 2), (10175, 10175, 2), + (10548, 10549, 2), + (11013, 11015, 2), (11035, 11036, 2), (11088, 11088, 2), (11093, 11093, 2), @@ -401,6 +452,8 @@ (125252, 125258, 0), (126980, 126980, 2), (127183, 127183, 2), + (127344, 127345, 2), + (127358, 127359, 2), (127374, 127374, 2), (127377, 127386, 2), (127488, 127490, 2), @@ -408,30 +461,43 @@ (127552, 127560, 2), (127568, 127569, 2), (127584, 127589, 2), - (127744, 127776, 2), - (127789, 127797, 2), - (127799, 127868, 2), - (127870, 127891, 2), - (127904, 127946, 2), - (127951, 127955, 2), - (127968, 127984, 2), - (127988, 127988, 2), - (127992, 128062, 2), - (128064, 128064, 2), - (128066, 128252, 2), + (127744, 127777, 2), + (127780, 127891, 2), + (127894, 127895, 2), + (127897, 127899, 2), + (127902, 127984, 2), + (127987, 127989, 2), + (127991, 128253, 2), (128255, 128317, 2), - (128331, 128334, 2), + (128329, 128334, 2), (128336, 128359, 2), - (128378, 128378, 2), + (128367, 128368, 2), + (128371, 128378, 2), + (128391, 128391, 2), + (128394, 128397, 2), + (128400, 128400, 2), (128405, 128406, 2), - (128420, 128420, 2), - (128507, 128591, 2), + (128420, 128421, 2), + (128424, 128424, 2), + (128433, 128434, 2), + (128444, 128444, 2), + (128450, 128452, 2), + (128465, 128467, 2), + (128476, 128478, 2), + (128481, 128481, 2), + (128483, 128483, 2), + (128488, 128488, 2), + (128495, 128495, 2), + (128499, 128499, 2), + (128506, 128591, 2), (128640, 128709, 2), - (128716, 128716, 2), - (128720, 128722, 2), + (128715, 128722, 2), (128725, 128727, 2), + (128736, 128741, 2), + (128745, 128745, 2), (128747, 128748, 2), - (128756, 128764, 2), + (128752, 128752, 2), + (128755, 128764, 2), (128992, 129003, 2), (129292, 129338, 2), (129340, 129349, 2), diff --git a/rich/cells.py b/rich/cells.py index e824ea2a6d..2099ee761c 100644 --- a/rich/cells.py +++ b/rich/cells.py @@ -1,5 +1,5 @@ -from functools import lru_cache import re +from functools import lru_cache from typing import Dict, List from ._cell_widths import CELL_WIDTHS @@ -138,6 +138,7 @@ def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]: if __name__ == "__main__": # pragma: no cover + print(get_character_cell_size("🛥")) print(get_character_cell_size("😽")) for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8): diff --git a/rich/emoji.py b/rich/emoji.py index d5a1062a96..b80a775e93 100644 --- a/rich/emoji.py +++ b/rich/emoji.py @@ -1,11 +1,11 @@ import sys from typing import TYPE_CHECKING, Optional, Union +from ._emoji_codes import EMOJI +from ._emoji_replace import _emoji_replace from .jupyter import JupyterMixin from .segment import Segment from .style import Style -from ._emoji_codes import EMOJI -from ._emoji_replace import _emoji_replace if sys.version_info >= (3, 8): from typing import Literal @@ -86,11 +86,15 @@ def __rich_console__( console = Console(record=True) + data = list( + f":{name}: {name}" for name, value in sorted(EMOJI.items()) if len(value) == 1 + ) columns = Columns( - (f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name), + data, column_first=True, ) console.print(columns) + console.print(len(data)) if len(sys.argv) > 1: console.save_html(sys.argv[1]) diff --git a/tools/emoji_variation_sequences.py b/tools/emoji_variation_sequences.py new file mode 100644 index 0000000000..23c18b3682 --- /dev/null +++ b/tools/emoji_variation_sequences.py @@ -0,0 +1,355 @@ +EMOJI_VARIATION_SEQUENCES = { + "♒", + "🕖", + "⏱", + "🔒", + "♻", + "☣", + "🔍", + "⛄", + "✡", + "🕳", + "🐿", + "▪", + "🗡", + "🚘", + "🌪", + "♟", + "✉", + "🛳", + "📺", + "↙", + "㊗", + "👆", + "♐", + "🎧", + "🌡", + "☂", + "8", + "⚕", + "♦", + "🗂", + "🏆", + "⏳", + "📥", + "🅰", + "🗓", + "™", + "📟", + "🚍", + "🌤", + "☯", + "7", + "🏊", + "⤴", + "🛥", + "⛳", + "🗞", + "📋", + "🕡", + "✏", + "♂", + "🛤", + "♏", + "◽", + "1", + "🚼", + "💣", + "🌨", + "⬜", + "🕷", + "⌨", + "♑", + "©", + "⚽", + "☀", + "🏞", + "🎛", + "🌦", + "♓", + "🎓", + "🕣", + "📭", + "㊙", + "👎", + "⛱", + "⛰", + "💳", + "⏭", + "⚛", + "☑", + "💻", + "⁉", + "⚱", + "6", + "⛷", + "⛽", + "♿", + "🏄", + "🚺", + "🛰", + "🖍", + "⚠", + "🚭", + "⬆", + "🌏", + "🏘", + "👍", + "🕰", + "📚", + "⏏", + "🕘", + "📽", + "🕵", + "🕓", + "☸", + "⛑", + "♎", + "✍", + "🕙", + "🗺", + "🕔", + "❓", + "📻", + "⚙", + "Ⓜ", + "♀", + "❤", + "🕸", + "🍸", + "🈚", + "🕞", + "🕦", + "⛴", + "🗑", + "▶", + "📤", + "🛍", + "🎬", + "🕕", + "🌥", + "🎚", + "♾", + "🛡", + "👪", + "♋", + "👽", + "⛔", + "☔", + "⛲", + "✌", + "🖱", + "🏳", + "👈", + "♣", + "🏚", + "🎟", + "☕", + "2", + "↪", + "⚡", + "♊", + "🕹", + "🏕", + "👁", + "⭕", + "♌", + "☄", + "🈯", + "🎮", + "‼", + "*", + "🛠", + "🅾", + "⏸", + "🕜", + "🛎", + "✔", + "☹", + "⌚", + "🗣", + "↗", + "⛅", + "⬛", + "4", + "🖊", + "☺", + "🀄", + "9", + "🖐", + "⛺", + "❗", + "🖋", + "☦", + "🚔", + "🅱", + "👉", + "♉", + "⚾", + "🛩", + "♥", + "☝", + "⏮", + "🔈", + "🏷", + "☘", + "☢", + "🗝", + "🖥", + "〰", + "📬", + "🖲", + "🗳", + "🕛", + "🕧", + "ℹ", + "🖼", + "⚰", + "🚹", + "#", + "🛋", + "🌧", + "🐦", + "🕊", + "🗄", + "🐟", + "🐕", + "⚔", + "⛏", + "3", + "🌬", + "🏂", + "⛓", + "🏗", + "💿", + "🛏", + "🏵", + "🎙", + "😐", + "☁", + "♠", + "⬇", + "🏝", + "🏜", + "📷", + "🗨", + "🖌", + "🚲", + "✂", + "🕯", + "🎭", + "🚑", + "®", + "♨", + "⏪", + "🗃", + "◼", + "🎖", + "🛣", + "🕗", + "👂", + "☪", + "◾", + "⚗", + "🚇", + "✝", + "📦", + "⏺", + "☮", + "⛵", + "🏠", + "✴", + "🏭", + "⏩", + "☎", + "⚖", + "🛢", + "↖", + "❣", + "🏛", + "🕒", + "↘", + "🏖", + "🌜", + "🕶", + "⛪", + "🕟", + "🖇", + "🐈", + "↔", + "🌩", + "⛩", + "❇", + "🏟", + "⏲", + "💰", + "⚒", + "🌍", + "◻", + "☠", + "⛹", + "♈", + "👓", + "✖", + "📹", + "🕴", + "🎞", + "⤵", + "▫", + "🍽", + "◀", + "🗜", + "➡", + "📫", + "🏋", + "⌛", + "🏍", + "⬅", + "⚫", + "🕐", + "🗯", + "🏔", + "🕑", + "🏙", + "❄", + "📪", + "🅿", + "🌶", + "〽", + "🔓", + "⏹", + "⭐", + "🕠", + "🕝", + "🈂", + "🕚", + "🗒", + "🈷", + "↩", + "☃", + "✈", + "🕉", + "5", + "⚪", + "⚜", + "🏎", + "🌫", + "🏌", + "⛈", + "✳", + "🕤", + "✒", + "🌎", + "🕥", + "🌕", + "⛸", + "0", + "↕", + "🎗", + "🖨", + "👇", + "⚓", + "🕢", + "♍", + "⏯", +} diff --git a/tools/make_terminal_widths.py b/tools/make_terminal_widths.py index 850f67a910..77391cef4c 100644 --- a/tools/make_terminal_widths.py +++ b/tools/make_terminal_widths.py @@ -1,11 +1,11 @@ import subprocess -from typing import List, Tuple import sys - -from rich.progress import Progress +from typing import List, Tuple from wcwidth import wcwidth +from rich.progress import Progress +from tools.emoji_variation_sequences import EMOJI_VARIATION_SEQUENCES progress = Progress() @@ -16,10 +16,15 @@ def make_widths_table() -> List[Tuple[int, int, int]]: make_table_task = progress.add_task("Calculating table...") - widths = ( - (codepoint, wcwidth(chr(codepoint))) - for codepoint in range(0, sys.maxunicode + 1) - ) + widths = [] + for codepoint in range(0, sys.maxunicode + 1): + # Emoji presentation sequences behave as though they were East Asian Wide, + # regardless of their assigned East_Asian_Width property value: + # http://www.unicode.org/reports/tr41/tr41-26.html#UTS51 + if chr(codepoint) in EMOJI_VARIATION_SEQUENCES: + widths.append((codepoint, 2)) + else: + widths.append((codepoint, wcwidth(chr(codepoint)))) _widths = [(codepoint, width) for codepoint, width in widths if width != 1] iter_widths = iter(_widths) @@ -40,7 +45,6 @@ def make_widths_table() -> List[Tuple[int, int, int]]: def get_cell_size(table: List[Tuple[int, int, int]], character: str) -> int: - codepoint = ord(character) lower_bound = 0 upper_bound = len(table) - 1 From fb55b1736db23f3c42280ea4e506618c4c9fee10 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 14:36:23 +0000 Subject: [PATCH 226/287] Fix tool script which tests Rich cell_len vs wcwidth widths --- tools/make_terminal_widths.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/make_terminal_widths.py b/tools/make_terminal_widths.py index 77391cef4c..63ec14df57 100644 --- a/tools/make_terminal_widths.py +++ b/tools/make_terminal_widths.py @@ -70,9 +70,11 @@ def test(widths_table): character = chr(codepoint) width1 = get_cell_size(widths_table, character) width2 = wcwidth(character) - if width1 != width2: + if width1 != width2 and character not in EMOJI_VARIATION_SEQUENCES: print(f"{width1} != {width2}") - break + raise Exception( + f"Width mismatch between Rich and wcwidth for character '{character}'" + ) def run(): From 6328aad6bb170eacc6e544143a02e38463b27d38 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 14:38:06 +0000 Subject: [PATCH 227/287] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d15e5f3ff..bdbec65975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## [Unreleased] + +### Added + +- Fix width measurement of 353 emoji variation sequences + ## [11.0.0] - 2022-01-09 ### Added From 45c1728cfd1005d9c663ebb20523744e3e811008 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 15:11:56 +0000 Subject: [PATCH 228/287] Ensure single digits dont appear in terminal cell with list --- rich/_cell_widths.py | 1 - tests/test_cells.py | 37 +++++++++++++++++++++++++++++++++++ tools/make_terminal_widths.py | 9 ++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/rich/_cell_widths.py b/rich/_cell_widths.py index f96df929ac..5fad15e05b 100644 --- a/rich/_cell_widths.py +++ b/rich/_cell_widths.py @@ -5,7 +5,6 @@ (1, 31, -1), (35, 35, 2), (42, 42, 2), - (48, 57, 2), (127, 159, -1), (169, 169, 2), (174, 174, 2), diff --git a/tests/test_cells.py b/tests/test_cells.py index d64317f3ba..8bcb29ff67 100644 --- a/tests/test_cells.py +++ b/tests/test_cells.py @@ -1,6 +1,43 @@ from rich import cells +def test_cell_len_empty_string(): + assert cells.cell_len("") == 0 + + +def test_cell_len_single_ascii_char(): + assert cells.cell_len("a") == 1 + + +def test_cell_len_single_ascii_num(): + assert cells.cell_len("5") == 1 + + +def test_cell_len_ascii_string(): + assert cells.cell_len("hello") == len("hello") + + +def test_cell_len_zero_width_character(): + assert cells.cell_len("\u0483") == 0 + + +def test_cell_len_single_width_non_ascii_character(): + assert cells.cell_len("\u0370") == 1 + + +def test_cell_len_japanese_hiragana(): + assert cells.cell_len("こんにちは") == 10 + + +def test_cell_len_poop_emoji_has_width_2(): + assert cells.cell_len("💩") == 2 + + +def test_cell_len_emoji_presentation_sequence(): + # Handled different from standard emoji - we vary from wcwidth here, which reports width 1. + assert cells.cell_len("🏵️") == 2 + + def test_set_cell_size(): assert cells.set_cell_size("foo", 0) == "" assert cells.set_cell_size("f", 0) == "" diff --git a/tools/make_terminal_widths.py b/tools/make_terminal_widths.py index 63ec14df57..e8b384c2d8 100644 --- a/tools/make_terminal_widths.py +++ b/tools/make_terminal_widths.py @@ -1,3 +1,4 @@ +import string import subprocess import sys from typing import List, Tuple @@ -21,7 +22,13 @@ def make_widths_table() -> List[Tuple[int, int, int]]: # Emoji presentation sequences behave as though they were East Asian Wide, # regardless of their assigned East_Asian_Width property value: # http://www.unicode.org/reports/tr41/tr41-26.html#UTS51 - if chr(codepoint) in EMOJI_VARIATION_SEQUENCES: + # Codepoints representing digits can appear at the start of EPSQs, but they + # are captured by a regex inside Rich which targets the most common codepoint ranges, + # so we don't need them in our lookup table. + if ( + chr(codepoint) in EMOJI_VARIATION_SEQUENCES + and chr(codepoint) not in string.digits + ): widths.append((codepoint, 2)) else: widths.append((codepoint, wcwidth(chr(codepoint)))) From 947e0b17d272a50f099ff7be3f52e88b1ee20978 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 15:19:06 +0000 Subject: [PATCH 229/287] Add PR link to changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdbec65975..0de277c2c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Fix width measurement of 353 emoji variation sequences +- Fix width measurement of 353 emoji variation sequences https://github.com/Textualize/rich/pull/1832 ## [11.0.0] - 2022-01-09 From 5aa024276396ea7511450741c5349c57d586c42f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 16:44:26 +0000 Subject: [PATCH 230/287] Stop using functools.lru_cache decorator on instance methods --- rich/color.py | 165 ++++++++++++++++++++++--------------------- rich/palette.py | 52 ++++++++------ rich/progress_bar.py | 96 ++++++++++++------------- rich/style.py | 79 +++++++++++---------- tests/test_bar.py | 4 +- 5 files changed, 205 insertions(+), 191 deletions(-) diff --git a/rich/color.py b/rich/color.py index f0fa026d64..2a68649622 100644 --- a/rich/color.py +++ b/rich/color.py @@ -1,3 +1,4 @@ +import functools import platform import re from colorsys import rgb_to_hls @@ -7,14 +8,13 @@ from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE from .color_triplet import ColorTriplet -from .repr import rich_repr, Result +from .repr import Result, rich_repr from .terminal_theme import DEFAULT_TERMINAL_THEME if TYPE_CHECKING: # pragma: no cover from .terminal_theme import TerminalTheme from .text import Text - WINDOWS = platform.system() == "Windows" @@ -279,8 +279,8 @@ class Color(NamedTuple): def __rich__(self) -> "Text": """Dispays the actual color if Rich printed.""" - from .text import Text from .style import Style + from .text import Text return Text.assemble( f" "Color": number=number, ) - else: # color_rgb: + else: # color_rgb: components = color_rgb.split(",") if len(components) != 3: raise ColorParseError( @@ -446,87 +446,94 @@ def parse(cls, color: str) -> "Color": ) return cls(color, ColorType.TRUECOLOR, triplet=triplet) - @lru_cache(maxsize=1024) def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]: """Get the ANSI escape codes for this color.""" - _type = self.type - if _type == ColorType.DEFAULT: - return ("39" if foreground else "49",) - - elif _type == ColorType.WINDOWS: - number = self.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.STANDARD: - number = self.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.EIGHT_BIT: - assert self.number is not None - return ("38" if foreground else "48", "5", str(self.number)) - - else: # self.standard == ColorStandard.TRUECOLOR: - assert self.triplet is not None - red, green, blue = self.triplet - return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) + return _get_ansi_codes_cached(color=self, foreground=foreground) - @lru_cache(maxsize=1024) def downgrade(self, system: ColorSystem) -> "Color": """Downgrade a color system to a system with fewer colors.""" + return _downgrade_cached(color=self, system=system) + + +@functools.lru_cache(maxsize=1024) +def _get_ansi_codes_cached(color: Color, foreground: bool) -> Tuple[str, ...]: + _type = color.type + if _type == ColorType.DEFAULT: + return ("39" if foreground else "49",) + + elif _type == ColorType.WINDOWS: + number = color.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.STANDARD: + number = color.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.EIGHT_BIT: + assert color.number is not None + return ("38" if foreground else "48", "5", str(color.number)) + + else: # color.standard == ColorStandard.TRUECOLOR: + assert color.triplet is not None + red, green, blue = color.triplet + return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) + + +@lru_cache(maxsize=1024) +def _downgrade_cached(color: Color, system: ColorSystem) -> Color: + if color.type in [ColorType.DEFAULT, system]: + return color + # Convert to 8-bit color from truecolor color + if system == ColorSystem.EIGHT_BIT and color.system == ColorSystem.TRUECOLOR: + assert color.triplet is not None + red, green, blue = color.triplet.normalized + _h, l, s = rgb_to_hls(red, green, blue) + # If saturation is under 10% assume it is grayscale + if s < 0.1: + gray = round(l * 25.0) + if gray == 0: + color_number = 16 + elif gray == 25: + color_number = 231 + else: + color_number = 231 + gray + return Color(color.name, ColorType.EIGHT_BIT, number=color_number) + + color_number = ( + 16 + 36 * round(red * 5.0) + 6 * round(green * 5.0) + round(blue * 5.0) + ) + return Color(color.name, ColorType.EIGHT_BIT, number=color_number) + + # Convert to standard from truecolor or 8-bit + elif system == ColorSystem.STANDARD: + if color.system == ColorSystem.TRUECOLOR: + assert color.triplet is not None + triplet = color.triplet + else: # color.system == ColorSystem.EIGHT_BIT + assert color.number is not None + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[color.number]) + + color_number = STANDARD_PALETTE.match(triplet) + return Color(color.name, ColorType.STANDARD, number=color_number) + + elif system == ColorSystem.WINDOWS: + if color.system == ColorSystem.TRUECOLOR: + assert color.triplet is not None + triplet = color.triplet + else: # color.system == ColorSystem.EIGHT_BIT + assert color.number is not None + if color.number < 16: + return Color(color.name, ColorType.WINDOWS, number=color.number) + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[color.number]) + + color_number = WINDOWS_PALETTE.match(triplet) + return Color(color.name, ColorType.WINDOWS, number=color_number) - 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: - gray = round(l * 25.0) - if gray == 0: - color_number = 16 - elif gray == 25: - color_number = 231 - else: - color_number = 231 + gray - return Color(self.name, ColorType.EIGHT_BIT, number=color_number) - - color_number = ( - 16 + 36 * round(red * 5.0) + 6 * round(green * 5.0) + round(blue * 5.0) - ) - return Color(self.name, ColorType.EIGHT_BIT, number=color_number) - - # Convert to standard from truecolor or 8-bit - elif system == ColorSystem.STANDARD: - if self.system == ColorSystem.TRUECOLOR: - assert self.triplet is not None - triplet = self.triplet - else: # self.system == ColorSystem.EIGHT_BIT - assert self.number is not None - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) - - color_number = STANDARD_PALETTE.match(triplet) - return Color(self.name, ColorType.STANDARD, number=color_number) - - elif system == ColorSystem.WINDOWS: - if self.system == ColorSystem.TRUECOLOR: - assert self.triplet is not None - triplet = self.triplet - else: # self.system == ColorSystem.EIGHT_BIT - assert self.number is not None - if self.number < 16: - return Color(self.name, ColorType.WINDOWS, number=self.number) - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) - - color_number = WINDOWS_PALETTE.match(triplet) - return Color(self.name, ColorType.WINDOWS, number=color_number) - - return self + return color def parse_rgb_hex(hex_color: str) -> ColorTriplet: diff --git a/rich/palette.py b/rich/palette.py index f29587945c..cd55dec9b8 100644 --- a/rich/palette.py +++ b/rich/palette.py @@ -1,6 +1,6 @@ -from math import sqrt from functools import lru_cache -from typing import Sequence, Tuple, TYPE_CHECKING +from math import sqrt +from typing import TYPE_CHECKING, Sequence, Tuple from .color_triplet import ColorTriplet @@ -20,8 +20,8 @@ def __getitem__(self, number: int) -> ColorTriplet: def __rich__(self) -> "Table": from rich.color import Color from rich.style import Style - from rich.text import Text from rich.table import Table + from rich.text import Text table = Table( "index", @@ -40,8 +40,6 @@ def __rich__(self) -> "Table": ) return table - # This is somewhat inefficient and needs caching - @lru_cache(maxsize=1024) def match(self, color: Tuple[int, int, int]) -> int: """Find a color from a palette that most closely matches a given color. @@ -51,30 +49,38 @@ def match(self, color: Tuple[int, int, int]) -> int: Returns: int: Index of closes matching color. """ - red1, green1, blue1 = color - _sqrt = sqrt - get_color = self._colors.__getitem__ - - def get_color_distance(index: int) -> float: - """Get the distance to a color.""" - red2, green2, blue2 = get_color(index) - red_mean = (red1 + red2) // 2 - red = red1 - red2 - green = green1 - green2 - blue = blue1 - blue2 - return _sqrt( - (((512 + red_mean) * red * red) >> 8) - + 4 * green * green - + (((767 - red_mean) * blue * blue) >> 8) - ) + return _match_palette_cached(color=color, available_colors=tuple(self._colors)) + + +@lru_cache(maxsize=1024) +def _match_palette_cached( + color: Tuple[int, int, int], available_colors: Tuple[Tuple[int, int, int]] +) -> int: + red1, green1, blue1 = color + _sqrt = sqrt + get_color = available_colors.__getitem__ + + def get_color_distance(index: int) -> float: + """Get the distance to a color.""" + red2, green2, blue2 = get_color(index) + red_mean = (red1 + red2) // 2 + red = red1 - red2 + green = green1 - green2 + blue = blue1 - blue2 + return _sqrt( + (((512 + red_mean) * red * red) >> 8) + + 4 * green * green + + (((767 - red_mean) * blue * blue) >> 8) + ) - min_index = min(range(len(self._colors)), key=get_color_distance) - return min_index + min_index = min(range(len(available_colors)), key=get_color_distance) + return min_index if __name__ == "__main__": # pragma: no cover import colorsys from typing import Iterable + from rich.color import Color from rich.console import Console, ConsoleOptions from rich.segment import Segment diff --git a/rich/progress_bar.py b/rich/progress_bar.py index 1797b5f786..ce51a86040 100644 --- a/rich/progress_bar.py +++ b/rich/progress_bar.py @@ -1,5 +1,5 @@ +import functools import math -from functools import lru_cache from time import monotonic from typing import Iterable, List, Optional @@ -15,6 +15,51 @@ PULSE_SIZE = 20 +@functools.lru_cache(maxsize=16) +def _get_pulse_segments( + fore_style: Style, + back_style: Style, + color_system: str, + no_color: bool, + ascii: bool = False, +) -> List[Segment]: + """Get a list of segments to render a pulse animation. + + Returns: + List[Segment]: A list of segments, one segment per character. + """ + bar = "-" if ascii else "━" + segments: List[Segment] = [] + if color_system not in ("standard", "eight_bit", "truecolor") or no_color: + segments += [Segment(bar, fore_style)] * (PULSE_SIZE // 2) + segments += [Segment(" " if no_color else bar, back_style)] * ( + PULSE_SIZE - (PULSE_SIZE // 2) + ) + return segments + + append = segments.append + fore_color = ( + fore_style.color.get_truecolor() + if fore_style.color + else ColorTriplet(255, 0, 255) + ) + back_color = ( + back_style.color.get_truecolor() if back_style.color else ColorTriplet(0, 0, 0) + ) + cos = math.cos + pi = math.pi + _Segment = Segment + _Style = Style + from_triplet = Color.from_triplet + + for index in range(PULSE_SIZE): + position = index / PULSE_SIZE + fade = 0.5 + cos((position * pi * 2)) / 2.0 + color = blend_rgb(fore_color, back_color, cross_fade=fade) + append(_Segment(bar, _Style(color=from_triplet(color)))) + return segments + + class ProgressBar(JupyterMixin): """Renders a (progress) bar. Used by rich.progress. @@ -64,53 +109,6 @@ def percentage_completed(self) -> float: completed = min(100, max(0.0, completed)) return completed - @lru_cache(maxsize=16) - def _get_pulse_segments( - self, - fore_style: Style, - back_style: Style, - color_system: str, - no_color: bool, - ascii: bool = False, - ) -> List[Segment]: - """Get a list of segments to render a pulse animation. - - Returns: - List[Segment]: A list of segments, one segment per character. - """ - bar = "-" if ascii else "━" - segments: List[Segment] = [] - if color_system not in ("standard", "eight_bit", "truecolor") or no_color: - segments += [Segment(bar, fore_style)] * (PULSE_SIZE // 2) - segments += [Segment(" " if no_color else bar, back_style)] * ( - PULSE_SIZE - (PULSE_SIZE // 2) - ) - return segments - - append = segments.append - fore_color = ( - fore_style.color.get_truecolor() - if fore_style.color - else ColorTriplet(255, 0, 255) - ) - back_color = ( - back_style.color.get_truecolor() - if back_style.color - else ColorTriplet(0, 0, 0) - ) - cos = math.cos - pi = math.pi - _Segment = Segment - _Style = Style - from_triplet = Color.from_triplet - - for index in range(PULSE_SIZE): - position = index / PULSE_SIZE - fade = 0.5 + cos((position * pi * 2)) / 2.0 - color = blend_rgb(fore_color, back_color, cross_fade=fade) - append(_Segment(bar, _Style(color=from_triplet(color)))) - return segments - def update(self, completed: float, total: Optional[float] = None) -> None: """Update progress with new values. @@ -139,7 +137,7 @@ def _render_pulse( fore_style = console.get_style(self.pulse_style, default="white") back_style = console.get_style(self.style, default="black") - pulse_segments = self._get_pulse_segments( + pulse_segments = _get_pulse_segments( fore_style, back_style, console.color_system, console.no_color, ascii=ascii ) segment_count = len(pulse_segments) diff --git a/rich/style.py b/rich/style.py index 0787c33147..4153e2774c 100644 --- a/rich/style.py +++ b/rich/style.py @@ -1,15 +1,14 @@ import sys from functools import lru_cache -from marshal import loads, dumps +from marshal import dumps, loads from random import randint -from typing import Any, cast, Dict, Iterable, List, Optional, Type, Union +from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast from . import errors from .color import Color, ColorParseError, ColorSystem, blend_rgb -from .repr import rich_repr, Result +from .repr import Result, rich_repr from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme - # Style instances and style definitions are often interchangeable StyleType = Union[str, "Style"] @@ -575,42 +574,9 @@ def parse(cls, style_definition: str) -> "Style": style = Style(color=color, bgcolor=bgcolor, link=link, **attributes) return style - @lru_cache(maxsize=1024) def get_html_style(self, theme: Optional[TerminalTheme] = None) -> str: """Get a CSS style rule.""" - theme = theme or DEFAULT_TERMINAL_THEME - css: List[str] = [] - append = css.append - - color = self.color - bgcolor = self.bgcolor - if self.reverse: - color, bgcolor = bgcolor, color - if self.dim: - foreground_color = ( - theme.foreground_color if color is None else color.get_truecolor(theme) - ) - color = Color.from_triplet( - blend_rgb(foreground_color, theme.background_color, 0.5) - ) - if color is not None: - theme_color = color.get_truecolor(theme) - append(f"color: {theme_color.hex}") - append(f"text-decoration-color: {theme_color.hex}") - if bgcolor is not None: - theme_color = bgcolor.get_truecolor(theme, foreground=False) - append(f"background-color: {theme_color.hex}") - if self.bold: - append("font-weight: bold") - if self.italic: - append("font-style: italic") - if self.underline: - append("text-decoration: underline") - if self.strike: - append("text-decoration: line-through") - if self.overline: - append("text-decoration: overline") - return "; ".join(css) + return _get_html_style_cached(self, theme) @classmethod def combine(cls, styles: Iterable["Style"]) -> "Style": @@ -751,6 +717,43 @@ def __add__(self, style: Optional["Style"]) -> "Style": NULL_STYLE = Style() +@lru_cache(maxsize=1024) +def _get_html_style_cached(style: Style, theme: Optional[TerminalTheme] = None) -> str: + theme = theme or DEFAULT_TERMINAL_THEME + css: List[str] = [] + append = css.append + + color = style.color + bgcolor = style.bgcolor + if style.reverse: + color, bgcolor = bgcolor, color + if style.dim: + foreground_color = ( + theme.foreground_color if color is None else color.get_truecolor(theme) + ) + color = Color.from_triplet( + blend_rgb(foreground_color, theme.background_color, 0.5) + ) + if color is not None: + theme_color = color.get_truecolor(theme) + append(f"color: {theme_color.hex}") + append(f"text-decoration-color: {theme_color.hex}") + if bgcolor is not None: + theme_color = bgcolor.get_truecolor(theme, foreground=False) + append(f"background-color: {theme_color.hex}") + if style.bold: + append("font-weight: bold") + if style.italic: + append("font-style: italic") + if style.underline: + append("text-decoration: underline") + if style.strike: + append("text-decoration: line-through") + if style.overline: + append("text-decoration: overline") + return "; ".join(css) + + class StyleStack: """A stack of styles.""" diff --git a/tests/test_bar.py b/tests/test_bar.py index 021a8aaac1..5d36a8caa8 100644 --- a/tests/test_bar.py +++ b/tests/test_bar.py @@ -1,5 +1,5 @@ from rich.console import Console -from rich.progress_bar import ProgressBar +from rich.progress_bar import ProgressBar, _get_pulse_segments from rich.segment import Segment from rich.style import Style @@ -63,7 +63,7 @@ def test_pulse(): def test_get_pulse_segments(): bar = ProgressBar() - segments = bar._get_pulse_segments( + segments = _get_pulse_segments( Style.parse("red"), Style.parse("yellow"), None, False, False ) print(repr(segments)) From 95c0b168bf115e1dfb077f8442a8d4b792fcd979 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 13 Jan 2022 16:46:36 +0000 Subject: [PATCH 231/287] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d15e5f3ff..15ce46de9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ 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). +## [Unreleased] + +- Stop using `functools.lru_cache` decorator on instance methods + ## [11.0.0] - 2022-01-09 ### Added From 5957b960b5f40fa322552b9a8477b9b83743d09f Mon Sep 17 00:00:00 2001 From: Peder Bergebakken Sundt Date: Sun, 16 Jan 2022 15:04:30 +0100 Subject: [PATCH 232/287] Collapse platform details in bug reports To reduce noise. Example: https://github.com/Textualize/rich/issues/1838 --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c72dc5ae81..05cd2cd112 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -15,6 +15,8 @@ Edit this with a clear and concise description of what the bug. Provide a minimal code example that demonstrates the issue if you can. If the issue is visual in nature, consider posting a screenshot. **Platform** +
+Click to expand What platform (Win/Linux/Mac) are you running on? What terminal software are you using? @@ -25,3 +27,5 @@ python -m rich.diagnose python -m rich._windows pip freeze | grep rich ``` + +
From 12ecab7400a33db83284c44b5da1f84124b18407 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:30:43 +0000 Subject: [PATCH 233/287] Bump sphinx from 4.3.2 to 4.4.0 Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.2 to 4.4.0. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.2...v4.4.0) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 716b1b3ddc..849854779e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ alabaster==0.7.12 -Sphinx==4.3.2 +Sphinx==4.4.0 sphinx-rtd-theme==1.0.0 sphinx-copybutton==0.4.0 From 009bf5e407dad18d68066ed1ce3f74701498a5be Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 17 Jan 2022 15:02:04 +0000 Subject: [PATCH 234/287] Revert "Fix width measurement of 353 emoji" --- CHANGELOG.md | 6 - rich/_cell_widths.py | 131 +++-------- rich/cells.py | 3 +- rich/emoji.py | 10 +- tests/test_cells.py | 37 --- tools/emoji_variation_sequences.py | 355 ----------------------------- tools/make_terminal_widths.py | 33 +-- 7 files changed, 47 insertions(+), 528 deletions(-) delete mode 100644 tools/emoji_variation_sequences.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0de277c2c5..4d15e5f3ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,6 @@ 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). -## [Unreleased] - -### Added - -- Fix width measurement of 353 emoji variation sequences https://github.com/Textualize/rich/pull/1832 - ## [11.0.0] - 2022-01-09 ### Added diff --git a/rich/_cell_widths.py b/rich/_cell_widths.py index 5fad15e05b..36286df379 100644 --- a/rich/_cell_widths.py +++ b/rich/_cell_widths.py @@ -3,11 +3,7 @@ CELL_WIDTHS = [ (0, 0, 0), (1, 31, -1), - (35, 35, 2), - (42, 42, 2), (127, 159, -1), - (169, 169, 2), - (174, 174, 2), (768, 879, 0), (1155, 1161, 0), (1425, 1469, 0), @@ -174,85 +170,39 @@ (7675, 7679, 0), (8203, 8207, 0), (8232, 8238, 0), - (8252, 8252, 2), - (8265, 8265, 2), (8288, 8291, 0), (8400, 8432, 0), - (8482, 8482, 2), - (8505, 8505, 2), - (8596, 8601, 2), - (8617, 8618, 2), (8986, 8987, 2), - (9000, 9002, 2), - (9167, 9167, 2), - (9193, 9203, 2), - (9208, 9210, 2), - (9410, 9410, 2), - (9642, 9643, 2), - (9654, 9654, 2), - (9664, 9664, 2), - (9723, 9726, 2), - (9728, 9732, 2), - (9742, 9742, 2), - (9745, 9745, 2), + (9001, 9002, 2), + (9193, 9196, 2), + (9200, 9200, 2), + (9203, 9203, 2), + (9725, 9726, 2), (9748, 9749, 2), - (9752, 9752, 2), - (9757, 9757, 2), - (9760, 9760, 2), - (9762, 9763, 2), - (9766, 9766, 2), - (9770, 9770, 2), - (9774, 9775, 2), - (9784, 9786, 2), - (9792, 9792, 2), - (9794, 9794, 2), (9800, 9811, 2), - (9823, 9824, 2), - (9827, 9827, 2), - (9829, 9830, 2), - (9832, 9832, 2), - (9851, 9851, 2), - (9854, 9855, 2), - (9874, 9879, 2), - (9881, 9881, 2), - (9883, 9884, 2), - (9888, 9889, 2), + (9855, 9855, 2), + (9875, 9875, 2), + (9889, 9889, 2), (9898, 9899, 2), - (9904, 9905, 2), (9917, 9918, 2), (9924, 9925, 2), - (9928, 9928, 2), - (9934, 9935, 2), - (9937, 9937, 2), - (9939, 9940, 2), - (9961, 9962, 2), - (9968, 9973, 2), - (9975, 9978, 2), + (9934, 9934, 2), + (9940, 9940, 2), + (9962, 9962, 2), + (9970, 9971, 2), + (9973, 9973, 2), + (9978, 9978, 2), (9981, 9981, 2), - (9986, 9986, 2), (9989, 9989, 2), - (9992, 9997, 2), - (9999, 9999, 2), - (10002, 10002, 2), - (10004, 10004, 2), - (10006, 10006, 2), - (10013, 10013, 2), - (10017, 10017, 2), + (9994, 9995, 2), (10024, 10024, 2), - (10035, 10036, 2), - (10052, 10052, 2), - (10055, 10055, 2), (10060, 10060, 2), (10062, 10062, 2), (10067, 10069, 2), (10071, 10071, 2), - (10083, 10084, 2), (10133, 10135, 2), - (10145, 10145, 2), (10160, 10160, 2), (10175, 10175, 2), - (10548, 10549, 2), - (11013, 11015, 2), (11035, 11036, 2), (11088, 11088, 2), (11093, 11093, 2), @@ -451,8 +401,6 @@ (125252, 125258, 0), (126980, 126980, 2), (127183, 127183, 2), - (127344, 127345, 2), - (127358, 127359, 2), (127374, 127374, 2), (127377, 127386, 2), (127488, 127490, 2), @@ -460,43 +408,30 @@ (127552, 127560, 2), (127568, 127569, 2), (127584, 127589, 2), - (127744, 127777, 2), - (127780, 127891, 2), - (127894, 127895, 2), - (127897, 127899, 2), - (127902, 127984, 2), - (127987, 127989, 2), - (127991, 128253, 2), + (127744, 127776, 2), + (127789, 127797, 2), + (127799, 127868, 2), + (127870, 127891, 2), + (127904, 127946, 2), + (127951, 127955, 2), + (127968, 127984, 2), + (127988, 127988, 2), + (127992, 128062, 2), + (128064, 128064, 2), + (128066, 128252, 2), (128255, 128317, 2), - (128329, 128334, 2), + (128331, 128334, 2), (128336, 128359, 2), - (128367, 128368, 2), - (128371, 128378, 2), - (128391, 128391, 2), - (128394, 128397, 2), - (128400, 128400, 2), + (128378, 128378, 2), (128405, 128406, 2), - (128420, 128421, 2), - (128424, 128424, 2), - (128433, 128434, 2), - (128444, 128444, 2), - (128450, 128452, 2), - (128465, 128467, 2), - (128476, 128478, 2), - (128481, 128481, 2), - (128483, 128483, 2), - (128488, 128488, 2), - (128495, 128495, 2), - (128499, 128499, 2), - (128506, 128591, 2), + (128420, 128420, 2), + (128507, 128591, 2), (128640, 128709, 2), - (128715, 128722, 2), + (128716, 128716, 2), + (128720, 128722, 2), (128725, 128727, 2), - (128736, 128741, 2), - (128745, 128745, 2), (128747, 128748, 2), - (128752, 128752, 2), - (128755, 128764, 2), + (128756, 128764, 2), (128992, 129003, 2), (129292, 129338, 2), (129340, 129349, 2), diff --git a/rich/cells.py b/rich/cells.py index 2099ee761c..e824ea2a6d 100644 --- a/rich/cells.py +++ b/rich/cells.py @@ -1,5 +1,5 @@ -import re from functools import lru_cache +import re from typing import Dict, List from ._cell_widths import CELL_WIDTHS @@ -138,7 +138,6 @@ def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]: if __name__ == "__main__": # pragma: no cover - print(get_character_cell_size("🛥")) print(get_character_cell_size("😽")) for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8): diff --git a/rich/emoji.py b/rich/emoji.py index b80a775e93..d5a1062a96 100644 --- a/rich/emoji.py +++ b/rich/emoji.py @@ -1,11 +1,11 @@ import sys from typing import TYPE_CHECKING, Optional, Union -from ._emoji_codes import EMOJI -from ._emoji_replace import _emoji_replace from .jupyter import JupyterMixin from .segment import Segment from .style import Style +from ._emoji_codes import EMOJI +from ._emoji_replace import _emoji_replace if sys.version_info >= (3, 8): from typing import Literal @@ -86,15 +86,11 @@ def __rich_console__( console = Console(record=True) - data = list( - f":{name}: {name}" for name, value in sorted(EMOJI.items()) if len(value) == 1 - ) columns = Columns( - data, + (f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name), column_first=True, ) console.print(columns) - console.print(len(data)) if len(sys.argv) > 1: console.save_html(sys.argv[1]) diff --git a/tests/test_cells.py b/tests/test_cells.py index 8bcb29ff67..d64317f3ba 100644 --- a/tests/test_cells.py +++ b/tests/test_cells.py @@ -1,43 +1,6 @@ from rich import cells -def test_cell_len_empty_string(): - assert cells.cell_len("") == 0 - - -def test_cell_len_single_ascii_char(): - assert cells.cell_len("a") == 1 - - -def test_cell_len_single_ascii_num(): - assert cells.cell_len("5") == 1 - - -def test_cell_len_ascii_string(): - assert cells.cell_len("hello") == len("hello") - - -def test_cell_len_zero_width_character(): - assert cells.cell_len("\u0483") == 0 - - -def test_cell_len_single_width_non_ascii_character(): - assert cells.cell_len("\u0370") == 1 - - -def test_cell_len_japanese_hiragana(): - assert cells.cell_len("こんにちは") == 10 - - -def test_cell_len_poop_emoji_has_width_2(): - assert cells.cell_len("💩") == 2 - - -def test_cell_len_emoji_presentation_sequence(): - # Handled different from standard emoji - we vary from wcwidth here, which reports width 1. - assert cells.cell_len("🏵️") == 2 - - def test_set_cell_size(): assert cells.set_cell_size("foo", 0) == "" assert cells.set_cell_size("f", 0) == "" diff --git a/tools/emoji_variation_sequences.py b/tools/emoji_variation_sequences.py deleted file mode 100644 index 23c18b3682..0000000000 --- a/tools/emoji_variation_sequences.py +++ /dev/null @@ -1,355 +0,0 @@ -EMOJI_VARIATION_SEQUENCES = { - "♒", - "🕖", - "⏱", - "🔒", - "♻", - "☣", - "🔍", - "⛄", - "✡", - "🕳", - "🐿", - "▪", - "🗡", - "🚘", - "🌪", - "♟", - "✉", - "🛳", - "📺", - "↙", - "㊗", - "👆", - "♐", - "🎧", - "🌡", - "☂", - "8", - "⚕", - "♦", - "🗂", - "🏆", - "⏳", - "📥", - "🅰", - "🗓", - "™", - "📟", - "🚍", - "🌤", - "☯", - "7", - "🏊", - "⤴", - "🛥", - "⛳", - "🗞", - "📋", - "🕡", - "✏", - "♂", - "🛤", - "♏", - "◽", - "1", - "🚼", - "💣", - "🌨", - "⬜", - "🕷", - "⌨", - "♑", - "©", - "⚽", - "☀", - "🏞", - "🎛", - "🌦", - "♓", - "🎓", - "🕣", - "📭", - "㊙", - "👎", - "⛱", - "⛰", - "💳", - "⏭", - "⚛", - "☑", - "💻", - "⁉", - "⚱", - "6", - "⛷", - "⛽", - "♿", - "🏄", - "🚺", - "🛰", - "🖍", - "⚠", - "🚭", - "⬆", - "🌏", - "🏘", - "👍", - "🕰", - "📚", - "⏏", - "🕘", - "📽", - "🕵", - "🕓", - "☸", - "⛑", - "♎", - "✍", - "🕙", - "🗺", - "🕔", - "❓", - "📻", - "⚙", - "Ⓜ", - "♀", - "❤", - "🕸", - "🍸", - "🈚", - "🕞", - "🕦", - "⛴", - "🗑", - "▶", - "📤", - "🛍", - "🎬", - "🕕", - "🌥", - "🎚", - "♾", - "🛡", - "👪", - "♋", - "👽", - "⛔", - "☔", - "⛲", - "✌", - "🖱", - "🏳", - "👈", - "♣", - "🏚", - "🎟", - "☕", - "2", - "↪", - "⚡", - "♊", - "🕹", - "🏕", - "👁", - "⭕", - "♌", - "☄", - "🈯", - "🎮", - "‼", - "*", - "🛠", - "🅾", - "⏸", - "🕜", - "🛎", - "✔", - "☹", - "⌚", - "🗣", - "↗", - "⛅", - "⬛", - "4", - "🖊", - "☺", - "🀄", - "9", - "🖐", - "⛺", - "❗", - "🖋", - "☦", - "🚔", - "🅱", - "👉", - "♉", - "⚾", - "🛩", - "♥", - "☝", - "⏮", - "🔈", - "🏷", - "☘", - "☢", - "🗝", - "🖥", - "〰", - "📬", - "🖲", - "🗳", - "🕛", - "🕧", - "ℹ", - "🖼", - "⚰", - "🚹", - "#", - "🛋", - "🌧", - "🐦", - "🕊", - "🗄", - "🐟", - "🐕", - "⚔", - "⛏", - "3", - "🌬", - "🏂", - "⛓", - "🏗", - "💿", - "🛏", - "🏵", - "🎙", - "😐", - "☁", - "♠", - "⬇", - "🏝", - "🏜", - "📷", - "🗨", - "🖌", - "🚲", - "✂", - "🕯", - "🎭", - "🚑", - "®", - "♨", - "⏪", - "🗃", - "◼", - "🎖", - "🛣", - "🕗", - "👂", - "☪", - "◾", - "⚗", - "🚇", - "✝", - "📦", - "⏺", - "☮", - "⛵", - "🏠", - "✴", - "🏭", - "⏩", - "☎", - "⚖", - "🛢", - "↖", - "❣", - "🏛", - "🕒", - "↘", - "🏖", - "🌜", - "🕶", - "⛪", - "🕟", - "🖇", - "🐈", - "↔", - "🌩", - "⛩", - "❇", - "🏟", - "⏲", - "💰", - "⚒", - "🌍", - "◻", - "☠", - "⛹", - "♈", - "👓", - "✖", - "📹", - "🕴", - "🎞", - "⤵", - "▫", - "🍽", - "◀", - "🗜", - "➡", - "📫", - "🏋", - "⌛", - "🏍", - "⬅", - "⚫", - "🕐", - "🗯", - "🏔", - "🕑", - "🏙", - "❄", - "📪", - "🅿", - "🌶", - "〽", - "🔓", - "⏹", - "⭐", - "🕠", - "🕝", - "🈂", - "🕚", - "🗒", - "🈷", - "↩", - "☃", - "✈", - "🕉", - "5", - "⚪", - "⚜", - "🏎", - "🌫", - "🏌", - "⛈", - "✳", - "🕤", - "✒", - "🌎", - "🕥", - "🌕", - "⛸", - "0", - "↕", - "🎗", - "🖨", - "👇", - "⚓", - "🕢", - "♍", - "⏯", -} diff --git a/tools/make_terminal_widths.py b/tools/make_terminal_widths.py index e8b384c2d8..850f67a910 100644 --- a/tools/make_terminal_widths.py +++ b/tools/make_terminal_widths.py @@ -1,12 +1,11 @@ -import string import subprocess -import sys from typing import List, Tuple +import sys + +from rich.progress import Progress from wcwidth import wcwidth -from rich.progress import Progress -from tools.emoji_variation_sequences import EMOJI_VARIATION_SEQUENCES progress = Progress() @@ -17,21 +16,10 @@ def make_widths_table() -> List[Tuple[int, int, int]]: make_table_task = progress.add_task("Calculating table...") - widths = [] - for codepoint in range(0, sys.maxunicode + 1): - # Emoji presentation sequences behave as though they were East Asian Wide, - # regardless of their assigned East_Asian_Width property value: - # http://www.unicode.org/reports/tr41/tr41-26.html#UTS51 - # Codepoints representing digits can appear at the start of EPSQs, but they - # are captured by a regex inside Rich which targets the most common codepoint ranges, - # so we don't need them in our lookup table. - if ( - chr(codepoint) in EMOJI_VARIATION_SEQUENCES - and chr(codepoint) not in string.digits - ): - widths.append((codepoint, 2)) - else: - widths.append((codepoint, wcwidth(chr(codepoint)))) + widths = ( + (codepoint, wcwidth(chr(codepoint))) + for codepoint in range(0, sys.maxunicode + 1) + ) _widths = [(codepoint, width) for codepoint, width in widths if width != 1] iter_widths = iter(_widths) @@ -52,6 +40,7 @@ def make_widths_table() -> List[Tuple[int, int, int]]: def get_cell_size(table: List[Tuple[int, int, int]], character: str) -> int: + codepoint = ord(character) lower_bound = 0 upper_bound = len(table) - 1 @@ -77,11 +66,9 @@ def test(widths_table): character = chr(codepoint) width1 = get_cell_size(widths_table, character) width2 = wcwidth(character) - if width1 != width2 and character not in EMOJI_VARIATION_SEQUENCES: + if width1 != width2: print(f"{width1} != {width2}") - raise Exception( - f"Width mismatch between Rich and wcwidth for character '{character}'" - ) + break def run(): From 106225f22c9546f3a5abdadb9e0d25871cfaf3f4 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 17 Jan 2022 15:40:13 +0000 Subject: [PATCH 235/287] Check for `__class__ before calling isinstance` --- rich/_inspect.py | 5 +++-- rich/pretty.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rich/_inspect.py b/rich/_inspect.py index 262695b1c4..7089701b44 100644 --- a/rich/_inspect.py +++ b/rich/_inspect.py @@ -3,7 +3,7 @@ from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature from typing import Any, Iterable, Optional, Tuple -from .console import RenderableType, Group +from .console import Group, RenderableType from .highlighter import ReprHighlighter from .jupyter import JupyterMixin from .panel import Panel @@ -206,5 +206,6 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]: yield items_table else: yield Text.from_markup( - f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." + f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] " + f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." ) diff --git a/rich/pretty.py b/rich/pretty.py index 57e743df49..45cd3a0039 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -722,7 +722,7 @@ def iter_attrs() -> Iterable[ pop_visited(obj_id) - elif isinstance(obj, _CONTAINERS): + elif hasattr(obj, "__class__") and isinstance(obj, _CONTAINERS): for container_type in _CONTAINERS: if isinstance(obj, container_type): obj_type = container_type From fde74c284a2620e16b64ed9b9fe651b94d93318f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 17 Jan 2022 17:53:53 +0000 Subject: [PATCH 236/287] Delete a redundant test --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0de277c2c5..330854f941 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Fix width measurement of 353 emoji variation sequences https://github.com/Textualize/rich/pull/1832 +- Workaround for strange edge case of object from Faiss with no `__class__` ## [11.0.0] - 2022-01-09 From 92e1b7ac7026142aeec36ff2f54ffd7c2875c8d2 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Tue, 18 Jan 2022 03:57:27 +0800 Subject: [PATCH 237/287] Rename `README.cn.md`, and apply link change --- README.de-ch.md | 3 ++- README.de.md | 3 ++- README.es.md | 3 ++- README.fr.md | 3 ++- README.hi.md | 3 ++- README.it.md | 3 ++- README.ja.md | 3 ++- README.kr.md | 3 ++- README.pt-br.md | 3 ++- README.ru.md | 3 ++- README.sv.md | 3 ++- README.cn.md => README.zh-cn.md | 3 ++- 12 files changed, 24 insertions(+), 12 deletions(-) rename README.cn.md => README.zh-cn.md (98%) diff --git a/README.de-ch.md b/README.de-ch.md index e965753221..4d6359ff52 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.de.md b/README.de.md index 38cf845d79..148f146f21 100644 --- a/README.de.md +++ b/README.de.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.es.md b/README.es.md index a3aa631cab..ec4e4f4253 100644 --- a/README.es.md +++ b/README.es.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.fr.md b/README.fr.md index 394f03bf83..0fbea94fc0 100644 --- a/README.fr.md +++ b/README.fr.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.hi.md b/README.hi.md index 9c3009f4fa..443472c5c8 100644 --- a/README.hi.md +++ b/README.hi.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.it.md b/README.it.md index 7d0b68d714..cf2e2c5fe0 100644 --- a/README.it.md +++ b/README.it.md @@ -6,7 +6,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.ja.md b/README.ja.md index 1bec484597..0429d11509 100644 --- a/README.ja.md +++ b/README.ja.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.kr.md b/README.kr.md index a1a67ea95d..e3aa03134e 100644 --- a/README.kr.md +++ b/README.kr.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.pt-br.md b/README.pt-br.md index c2294502ea..3d888ee449 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.ru.md b/README.ru.md index 4223309d97..d9a02c21c4 100644 --- a/README.ru.md +++ b/README.ru.md @@ -8,7 +8,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.sv.md b/README.sv.md index 35b2669791..b630b3e7f9 100644 --- a/README.sv.md +++ b/README.sv.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) diff --git a/README.cn.md b/README.zh-cn.md similarity index 98% rename from README.cn.md rename to README.zh-cn.md index 3fc571cd72..97f0996340 100644 --- a/README.cn.md +++ b/README.zh-cn.md @@ -7,7 +7,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) From 506432672b0ad481db18de3b2c8cb9c0fbb69827 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Tue, 18 Jan 2022 03:58:06 +0800 Subject: [PATCH 238/287] Add `README.zh-tw.md` --- README.zh-tw.md | 457 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 README.zh-tw.md diff --git a/README.zh-tw.md b/README.zh-tw.md new file mode 100644 index 0000000000..189b1fadad --- /dev/null +++ b/README.zh-tw.md @@ -0,0 +1,457 @@ +[![Downloads](https://pepy.tech/badge/rich/month)](https://pepy.tech/project/rich) +[![PyPI version](https://badge.fury.io/py/rich.svg)](https://badge.fury.io/py/rich) +[![codecov](https://codecov.io/gh/willmcgugan/rich/branch/master/graph/badge.svg)](https://codecov.io/gh/willmcgugan/rich) +[![Rich blog](https://img.shields.io/badge/blog-rich%20news-yellowgreen)](https://www.willmcgugan.com/tag/rich/) +[![Twitter Follow](https://img.shields.io/twitter/follow/willmcgugan.svg?style=social)](https://twitter.com/willmcgugan) + +![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) + +[English readme](https://github.com/willmcgugan/rich/blob/master/README.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) + • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) + • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) + • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) + • [日本語 readme](https://github.com/willmcgugan/rich/blob/master/README.ja.md) + • [한국어 readme](https://github.com/willmcgugan/rich/blob/master/README.kr.md) + • [Français readme](https://github.com/willmcgugan/rich/blob/master/README.fr.md) + • [Schwizerdütsch readme](https://github.com/willmcgugan/rich/blob/master/README.de-ch.md) + • [हिन्दी readme](https://github.com/willmcgugan/rich/blob/master/README.hi.md) + • [Português brasileiro readme](https://github.com/willmcgugan/rich/blob/master/README.pt-br.md) + • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) + • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) + +Rich is a Python library for _rich_ text and beautiful formatting in the terminal. + +The [Rich API](https://rich.readthedocs.io/en/latest/) makes it easy to add color and style to terminal output. Rich can also render pretty tables, progress bars, markdown, syntax highlighted source code, tracebacks, and more — out of the box. + +![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) + +For a video introduction to Rich see [calmcode.io](https://calmcode.io/rich/introduction.html) by [@fishnets88](https://twitter.com/fishnets88). + +See what [people are saying about Rich](https://www.willmcgugan.com/blog/pages/post/rich-tweets/). + +## Compatibility + +Rich works with Linux, OSX, and Windows. True color / emoji works with new Windows Terminal, classic terminal is limited to 16 colors. Rich requires Python 3.6.1 or later. + +Rich works with [Jupyter notebooks](https://jupyter.org/) with no additional configuration required. + +## Installing + +Install with `pip` or your favorite PyPI package manager. + +```sh +python -m pip install rich +``` + +Run the following to test Rich output on your terminal: + +```sh +python -m rich +``` + +## Rich Print + +To effortlessly add rich output to your application, you can import the [rich print](https://rich.readthedocs.io/en/latest/introduction.html#quick-start) method, which has the same signature as the builtin Python function. Try this: + +```python +from rich import print + +print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals()) +``` + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/print.png) + +## Rich REPL + +Rich can be installed in the Python REPL, so that any data structures will be pretty printed and highlighted. + +```python +>>> from rich import pretty +>>> pretty.install() +``` + +![REPL](https://github.com/willmcgugan/rich/raw/master/imgs/repl.png) + +## Using the Console + +For more control over rich terminal content, import and construct a [Console](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console) object. + +```python +from rich.console import Console + +console = Console() +``` + +The Console object has a `print` method which has an intentionally similar interface to the builtin `print` function. Here's an example of use: + +```python +console.print("Hello", "World!") +``` + +As you might expect, this will print `"Hello World!"` to the terminal. Note that unlike the builtin `print` function, Rich will word-wrap your text to fit within the terminal width. + +There are a few ways of adding color and style to your output. You can set a style for the entire output by adding a `style` keyword argument. Here's an example: + +```python +console.print("Hello", "World!", style="bold red") +``` + +The output will be something like the following: + +![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/hello_world.png) + +That's fine for styling a line of text at a time. For more finely grained styling, Rich renders a special markup which is similar in syntax to [bbcode](https://en.wikipedia.org/wiki/BBCode). Here's an example: + +```python +console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a [i]way[/i].") +``` + +![Console Markup](https://github.com/willmcgugan/rich/raw/master/imgs/where_there_is_a_will.png) + +You can use a Console object to generate sophisticated output with minimal effort. See the [Console API](https://rich.readthedocs.io/en/latest/console.html) docs for details. + +## Rich Inspect + +Rich has an [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) function which can produce a report on any Python object, such as class, instance, or builtin. + +```python +>>> my_list = ["foo", "bar"] +>>> from rich import inspect +>>> inspect(my_list, methods=True) +``` + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/inspect.png) + +See the [inspect docs](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) for details. + +# Rich Library + +Rich contains a number of builtin _renderables_ you can use to create elegant output in your CLI and help you debug your code. + +Click the following headings for details: + +
+Log + +The Console object has a `log()` method which has a similar interface to `print()`, but also renders a column for the current time and the file and line which made the call. By default Rich will do syntax highlighting for Python structures and for repr strings. If you log a collection (i.e. a dict or a list) Rich will pretty print it so that it fits in the available space. Here's an example of some of these features. + +```python +from rich.console import Console +console = Console() + +test_data = [ + {"jsonrpc": "2.0", "method": "sum", "params": [None, 1, 2, 4, False, True], "id": "1",}, + {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}, + {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"}, +] + +def test_log(): + enabled = False + context = { + "foo": "bar", + } + movies = ["Deadpool", "Rise of the Skywalker"] + console.log("Hello from", console, "!") + console.log(test_data, log_locals=True) + + +test_log() +``` + +The above produces the following output: + +![Log](https://github.com/willmcgugan/rich/raw/master/imgs/log.png) + +Note the `log_locals` argument, which outputs a table containing the local variables where the log method was called. + +The log method could be used for logging to the terminal for long running applications such as servers, but is also a very nice debugging aid. + +
+
+Logging Handler + +You can also use the builtin [Handler class](https://rich.readthedocs.io/en/latest/logging.html) to format and colorize output from Python's logging module. Here's an example of the output: + +![Logging](https://github.com/willmcgugan/rich/raw/master/imgs/logging.png) + +
+ +
+Emoji + +To insert an emoji in to console output place the name between two colons. Here's an example: + +```python +>>> console.print(":smiley: :vampire: :pile_of_poo: :thumbs_up: :raccoon:") +😃 🧛 💩 👍 🦝 +``` + +Please use this feature wisely. + +
+ +
+Tables + +Rich can render flexible [tables](https://rich.readthedocs.io/en/latest/tables.html) with unicode box characters. There is a large variety of formatting options for borders, styles, cell alignment etc. + +![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) + +The animation above was generated with [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) in the examples directory. + +Here's a simpler table example: + +```python +from rich.console import Console +from rich.table import Table + +console = Console() + +table = Table(show_header=True, header_style="bold magenta") +table.add_column("Date", style="dim", width=12) +table.add_column("Title") +table.add_column("Production Budget", justify="right") +table.add_column("Box Office", justify="right") +table.add_row( + "Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118" +) +table.add_row( + "May 25, 2018", + "[red]Solo[/red]: A Star Wars Story", + "$275,000,000", + "$393,151,347", +) +table.add_row( + "Dec 15, 2017", + "Star Wars Ep. VIII: The Last Jedi", + "$262,000,000", + "[bold]$1,332,539,889[/bold]", +) + +console.print(table) +``` + +This produces the following output: + +![table](https://github.com/willmcgugan/rich/raw/master/imgs/table.png) + +Note that console markup is rendered in the same way as `print()` and `log()`. In fact, anything that is renderable by Rich may be included in the headers / rows (even other tables). + +The `Table` class is smart enough to resize columns to fit the available width of the terminal, wrapping text as required. Here's the same example, with the terminal made smaller than the table above: + +![table2](https://github.com/willmcgugan/rich/raw/master/imgs/table2.png) + +
+ +
+Progress Bars + +Rich can render multiple flicker-free [progress](https://rich.readthedocs.io/en/latest/progress.html) bars to track long-running tasks. + +For basic usage, wrap any sequence in the `track` function and iterate over the result. Here's an example: + +```python +from rich.progress import track + +for step in track(range(100)): + do_step(step) +``` + +It's not much harder to add multiple progress bars. Here's an example taken from the docs: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/progress.gif) + +The columns may be configured to show any details you want. Built-in columns include percentage complete, file size, file speed, and time remaining. Here's another example showing a download in progress: + +![progress](https://github.com/willmcgugan/rich/raw/master/imgs/downloader.gif) + +To try this out yourself, see [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) which can download multiple URLs simultaneously while displaying progress. + +
+ +
+Status + +For situations where it is hard to calculate progress, you can use the [status](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console.status) method which will display a 'spinner' animation and message. The animation won't prevent you from using the console as normal. Here's an example: + +```python +from time import sleep +from rich.console import Console + +console = Console() +tasks = [f"task {n}" for n in range(1, 11)] + +with console.status("[bold green]Working on tasks...") as status: + while tasks: + task = tasks.pop(0) + sleep(1) + console.log(f"{task} complete") +``` + +This generates the following output in the terminal. + +![status](https://github.com/willmcgugan/rich/raw/master/imgs/status.gif) + +The spinner animations were borrowed from [cli-spinners](https://www.npmjs.com/package/cli-spinners). You can select a spinner by specifying the `spinner` parameter. Run the following command to see the available values: + +``` +python -m rich.spinner +``` + +The above command generates the following output in the terminal: + +![spinners](https://github.com/willmcgugan/rich/raw/master/imgs/spinners.gif) + +
+ +
+Tree + +Rich can render a [tree](https://rich.readthedocs.io/en/latest/tree.html) with guide lines. A tree is ideal for displaying a file structure, or any other hierarchical data. + +The labels of the tree can be simple text or anything else Rich can render. Run the following for a demonstration: + +``` +python -m rich.tree +``` + +This generates the following output: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/tree.png) + +See the [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) example for a script that displays a tree view of any directory, similar to the linux `tree` command. + +
+ +
+Columns + +Rich can render content in neat [columns](https://rich.readthedocs.io/en/latest/columns.html) with equal or optimal width. Here's a very basic clone of the (MacOS / Linux) `ls` command which displays a directory listing in columns: + +```python +import os +import sys + +from rich import print +from rich.columns import Columns + +directory = os.listdir(sys.argv[1]) +print(Columns(directory)) +``` + +The following screenshot is the output from the [columns example](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) which displays data pulled from an API in columns: + +![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) + +
+ +
+Markdown + +Rich can render [markdown](https://rich.readthedocs.io/en/latest/markdown.html) and does a reasonable job of translating the formatting to the terminal. + +To render markdown import the `Markdown` class and construct it with a string containing markdown code. Then print it to the console. Here's an example: + +```python +from rich.console import Console +from rich.markdown import Markdown + +console = Console() +with open("README.md") as readme: + markdown = Markdown(readme.read()) +console.print(markdown) +``` + +This will produce output something like the following: + +![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/markdown.png) + +
+ +
+Syntax Highlighting + +Rich uses the [pygments](https://pygments.org/) library to implement [syntax highlighting](https://rich.readthedocs.io/en/latest/syntax.html). Usage is similar to rendering markdown; construct a `Syntax` object and print it to the console. Here's an example: + +```python +from rich.console import Console +from rich.syntax import Syntax + +my_code = ''' +def iter_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: + """Iterate and generate a tuple with a flag for first and last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + first = True + for value in iter_values: + yield first, False, previous_value + first = False + previous_value = value + yield first, True, previous_value +''' +syntax = Syntax(my_code, "python", theme="monokai", line_numbers=True) +console = Console() +console.print(syntax) +``` + +This will produce the following output: + +![syntax](https://github.com/willmcgugan/rich/raw/master/imgs/syntax.png) + +
+ +
+Tracebacks + +Rich can render [beautiful tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) which are easier to read and show more code than standard Python tracebacks. You can set Rich as the default traceback handler so all uncaught exceptions will be rendered by Rich. + +Here's what it looks like on OSX (similar on Linux): + +![traceback](https://github.com/willmcgugan/rich/raw/master/imgs/traceback.png) + +
+ +All Rich renderables make use of the [Console Protocol](https://rich.readthedocs.io/en/latest/protocol.html), which you can also use to implement your own Rich content. + +# Rich for enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of Rich and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/pypi-rich?utm_source=pypi-rich&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +# Projects using Rich + +Here are a few projects using Rich: + +- [BrancoLab/BrainRender](https://github.com/BrancoLab/BrainRender) + a python package for the visualization of three dimensional neuro-anatomical data +- [Ciphey/Ciphey](https://github.com/Ciphey/Ciphey) + Automated decryption tool +- [emeryberger/scalene](https://github.com/emeryberger/scalene) + a high-performance, high-precision CPU and memory profiler for Python +- [hedythedev/StarCli](https://github.com/hedythedev/starcli) + Browse GitHub trending projects from your command line +- [intel/cve-bin-tool](https://github.com/intel/cve-bin-tool) + This tool scans for a number of common, vulnerable components (openssl, libpng, libxml2, expat and a few others) to let you know if your system includes common libraries with known vulnerabilities. +- [nf-core/tools](https://github.com/nf-core/tools) + Python package with helper tools for the nf-core community. +- [cansarigol/pdbr](https://github.com/cansarigol/pdbr) + pdb + Rich library for enhanced debugging +- [plant99/felicette](https://github.com/plant99/felicette) + Satellite imagery for dummies. +- [seleniumbase/SeleniumBase](https://github.com/seleniumbase/SeleniumBase) + Automate & test 10x faster with Selenium & pytest. Batteries included. +- [smacke/ffsubsync](https://github.com/smacke/ffsubsync) + Automagically synchronize subtitles with video. +- [tryolabs/norfair](https://github.com/tryolabs/norfair) + Lightweight Python library for adding real-time 2D object tracking to any detector. +- [ansible/ansible-lint](https://github.com/ansible/ansible-lint) Ansible-lint checks playbooks for practices and behaviour that could potentially be improved +- [ansible-community/molecule](https://github.com/ansible-community/molecule) Ansible Molecule testing framework +- +[Many more](https://github.com/willmcgugan/rich/network/dependents)! + + From 7a2c37f077fccf5c741a28135005457d8d18d7ce Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 18 Jan 2022 11:42:22 +0000 Subject: [PATCH 239/287] Handle exceptions thrown from isinstance --- rich/pretty.py | 41 +++++++++++++++++++++++++---------------- tests/test_inspect.py | 17 ++++++++++++++++- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/rich/pretty.py b/rich/pretty.py index 45cd3a0039..f42434ef5c 100644 --- a/rich/pretty.py +++ b/rich/pretty.py @@ -2,7 +2,6 @@ import dataclasses import inspect import os -import re import sys from array import array from collections import Counter, UserDict, UserList, defaultdict, deque @@ -93,7 +92,7 @@ def _ipy_display_hook( from .console import ConsoleRenderable # needed here to prevent circular import # always skip rich generated jupyter renderables or None values - if isinstance(value, JupyterRenderable) or value is None: + if _safe_isinstance(value, JupyterRenderable) or value is None: return console = console or get_console() @@ -124,12 +123,12 @@ def _ipy_display_hook( return # Delegate rendering to IPython # certain renderables should start on a new line - if isinstance(value, ConsoleRenderable): + if _safe_isinstance(value, ConsoleRenderable): console.line() console.print( value - if isinstance(value, RichRenderable) + if _safe_isinstance(value, RichRenderable) else Pretty( value, overflow=overflow, @@ -144,6 +143,16 @@ def _ipy_display_hook( ) +def _safe_isinstance( + obj: object, class_or_tuple: Union[type, Tuple[type, ...]] +) -> bool: + """isinstance can fail in rare cases, for example types with no __class__""" + try: + return isinstance(obj, class_or_tuple) + except Exception: + return False + + def install( console: Optional["Console"] = None, overflow: "OverflowMethod" = "ignore", @@ -178,7 +187,7 @@ def display_hook(value: Any) -> None: builtins._ = None # type: ignore console.print( value - if isinstance(value, RichRenderable) + if _safe_isinstance(value, RichRenderable) else Pretty( value, overflow=overflow, @@ -355,7 +364,7 @@ def _get_braces_for_array(_object: "array[Any]") -> Tuple[str, str, str]: def is_expandable(obj: Any) -> bool: """Check if an object may be expanded by pretty print.""" return ( - isinstance(obj, _CONTAINERS) + _safe_isinstance(obj, _CONTAINERS) or (is_dataclass(obj)) or (hasattr(obj, "__rich_repr__")) or _is_attr_object(obj) @@ -539,7 +548,7 @@ def to_repr(obj: Any) -> str: """Get repr string for an object, but catch errors.""" if ( max_string is not None - and isinstance(obj, (bytes, str)) + and _safe_isinstance(obj, (bytes, str)) and len(obj) > max_string ): truncated = len(obj) - max_string @@ -565,7 +574,7 @@ def _traverse(obj: Any, root: bool = False, depth: int = 0) -> Node: def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: for arg in rich_args: - if isinstance(arg, tuple): + if _safe_isinstance(arg, tuple): if len(arg) == 3: key, child, default = arg if default == child: @@ -622,7 +631,7 @@ def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: last=root, ) for last, arg in loop_last(args): - if isinstance(arg, tuple): + if _safe_isinstance(arg, tuple): key, child = arg child_node = _traverse(child, depth=depth + 1) child_node.last = last @@ -689,7 +698,7 @@ def iter_attrs() -> Iterable[ elif ( is_dataclass(obj) - and not isinstance(obj, type) + and not _safe_isinstance(obj, type) and not fake_attributes and (_is_dataclass_repr(obj) or py_version == (3, 6)) ): @@ -722,9 +731,9 @@ def iter_attrs() -> Iterable[ pop_visited(obj_id) - elif hasattr(obj, "__class__") and isinstance(obj, _CONTAINERS): + elif _safe_isinstance(obj, _CONTAINERS): for container_type in _CONTAINERS: - if isinstance(obj, container_type): + if _safe_isinstance(obj, container_type): obj_type = container_type break @@ -752,7 +761,7 @@ def iter_attrs() -> Iterable[ num_items = len(obj) last_item_index = num_items - 1 - if isinstance(obj, _MAPPING_CONTAINERS): + if _safe_isinstance(obj, _MAPPING_CONTAINERS): iter_items = iter(obj.items()) if max_length is not None: iter_items = islice(iter_items, max_length) @@ -777,7 +786,7 @@ def iter_attrs() -> Iterable[ pop_visited(obj_id) else: node = Node(value_repr=to_repr(obj), last=root) - node.is_tuple = isinstance(obj, tuple) + node.is_tuple = _safe_isinstance(obj, tuple) return node node = _traverse(_object, root=True) @@ -812,13 +821,13 @@ def pretty_repr( str: A possibly multi-line representation of the object. """ - if isinstance(_object, Node): + if _safe_isinstance(_object, Node): node = _object else: node = traverse( _object, max_length=max_length, max_string=max_string, max_depth=max_depth ) - repr_str = node.render( + repr_str: str = node.render( max_width=max_width, indent_size=indent_size, expand_all=expand_all ) return repr_str diff --git a/tests/test_inspect.py b/tests/test_inspect.py index 5a9a57610c..e947a7d6a7 100644 --- a/tests/test_inspect.py +++ b/tests/test_inspect.py @@ -1,12 +1,12 @@ import io import sys +from unittest import mock import pytest from rich import inspect from rich.console import Console - skip_py36 = pytest.mark.skipif( sys.version_info.minor == 6 and sys.version_info.major == 3, reason="rendered differently on py3.6", @@ -260,3 +260,18 @@ class Foo: result = render(foo, methods=True, width=100) print(repr(result)) assert expected == result + + +def test_inspect_swig_edge_case(): + """Issue #1838 - Edge case with Faiss library - object with empty dir()""" + + class Thing: + @property + def __class__(self): + raise AttributeError + + thing = Thing() + try: + inspect(thing) + except Exception as e: + assert False, f"Object with no __class__ shouldn't raise {e}" From 3944c46ee75267862fd74ae178c85bda983acfc7 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 18 Jan 2022 11:47:33 +0000 Subject: [PATCH 240/287] Add changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 330854f941..34ef0c3b81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Fix width measurement of 353 emoji variation sequences https://github.com/Textualize/rich/pull/1832 -- Workaround for strange edge case of object from Faiss with no `__class__` +- Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 ## [11.0.0] - 2022-01-09 From 8c3c2e712a2b89d0084a4b77a674f45134e34937 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 18 Jan 2022 12:00:24 +0000 Subject: [PATCH 241/287] Handle case of no attr object in output --- rich/_inspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/_inspect.py b/rich/_inspect.py index 7089701b44..07b1b623b8 100644 --- a/rich/_inspect.py +++ b/rich/_inspect.py @@ -204,7 +204,7 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]: add_row(key_text, Pretty(value, highlighter=highlighter)) if items_table.row_count: yield items_table - else: + elif not_shown_count: yield Text.from_markup( f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] " f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." From 902f7085edd97f88feda88f2ae95d834852c86d1 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 19 Jan 2022 10:51:12 +0000 Subject: [PATCH 242/287] Revert "Stop using functools.lru_cache decorator on instance methods" --- CHANGELOG.md | 2 +- rich/color.py | 165 +++++++++++++++++++++---------------------- rich/palette.py | 52 ++++++-------- rich/progress_bar.py | 96 +++++++++++++------------ rich/style.py | 79 ++++++++++----------- tests/test_bar.py | 4 +- 6 files changed, 192 insertions(+), 206 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b756e29dee..0de277c2c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Stop using `functools.lru_cache` decorator on instance methods + - Fix width measurement of 353 emoji variation sequences https://github.com/Textualize/rich/pull/1832 ## [11.0.0] - 2022-01-09 diff --git a/rich/color.py b/rich/color.py index 2a68649622..f0fa026d64 100644 --- a/rich/color.py +++ b/rich/color.py @@ -1,4 +1,3 @@ -import functools import platform import re from colorsys import rgb_to_hls @@ -8,13 +7,14 @@ from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE from .color_triplet import ColorTriplet -from .repr import Result, rich_repr +from .repr import rich_repr, Result from .terminal_theme import DEFAULT_TERMINAL_THEME if TYPE_CHECKING: # pragma: no cover from .terminal_theme import TerminalTheme from .text import Text + WINDOWS = platform.system() == "Windows" @@ -279,8 +279,8 @@ class Color(NamedTuple): def __rich__(self) -> "Text": """Dispays the actual color if Rich printed.""" - from .style import Style from .text import Text + from .style import Style return Text.assemble( f" "Color": number=number, ) - else: # color_rgb: + else: # color_rgb: components = color_rgb.split(",") if len(components) != 3: raise ColorParseError( @@ -446,94 +446,87 @@ def parse(cls, color: str) -> "Color": ) return cls(color, ColorType.TRUECOLOR, triplet=triplet) + @lru_cache(maxsize=1024) def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]: """Get the ANSI escape codes for this color.""" - return _get_ansi_codes_cached(color=self, foreground=foreground) + _type = self.type + if _type == ColorType.DEFAULT: + return ("39" if foreground else "49",) + + elif _type == ColorType.WINDOWS: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.STANDARD: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.EIGHT_BIT: + assert self.number is not None + return ("38" if foreground else "48", "5", str(self.number)) + + else: # self.standard == ColorStandard.TRUECOLOR: + assert self.triplet is not None + red, green, blue = self.triplet + return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) + @lru_cache(maxsize=1024) def downgrade(self, system: ColorSystem) -> "Color": """Downgrade a color system to a system with fewer colors.""" - return _downgrade_cached(color=self, system=system) - - -@functools.lru_cache(maxsize=1024) -def _get_ansi_codes_cached(color: Color, foreground: bool) -> Tuple[str, ...]: - _type = color.type - if _type == ColorType.DEFAULT: - return ("39" if foreground else "49",) - - elif _type == ColorType.WINDOWS: - number = color.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.STANDARD: - number = color.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.EIGHT_BIT: - assert color.number is not None - return ("38" if foreground else "48", "5", str(color.number)) - - else: # color.standard == ColorStandard.TRUECOLOR: - assert color.triplet is not None - red, green, blue = color.triplet - return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) - - -@lru_cache(maxsize=1024) -def _downgrade_cached(color: Color, system: ColorSystem) -> Color: - if color.type in [ColorType.DEFAULT, system]: - return color - # Convert to 8-bit color from truecolor color - if system == ColorSystem.EIGHT_BIT and color.system == ColorSystem.TRUECOLOR: - assert color.triplet is not None - red, green, blue = color.triplet.normalized - _h, l, s = rgb_to_hls(red, green, blue) - # If saturation is under 10% assume it is grayscale - if s < 0.1: - gray = round(l * 25.0) - if gray == 0: - color_number = 16 - elif gray == 25: - color_number = 231 - else: - color_number = 231 + gray - return Color(color.name, ColorType.EIGHT_BIT, number=color_number) - - color_number = ( - 16 + 36 * round(red * 5.0) + 6 * round(green * 5.0) + round(blue * 5.0) - ) - return Color(color.name, ColorType.EIGHT_BIT, number=color_number) - - # Convert to standard from truecolor or 8-bit - elif system == ColorSystem.STANDARD: - if color.system == ColorSystem.TRUECOLOR: - assert color.triplet is not None - triplet = color.triplet - else: # color.system == ColorSystem.EIGHT_BIT - assert color.number is not None - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[color.number]) - - color_number = STANDARD_PALETTE.match(triplet) - return Color(color.name, ColorType.STANDARD, number=color_number) - - elif system == ColorSystem.WINDOWS: - if color.system == ColorSystem.TRUECOLOR: - assert color.triplet is not None - triplet = color.triplet - else: # color.system == ColorSystem.EIGHT_BIT - assert color.number is not None - if color.number < 16: - return Color(color.name, ColorType.WINDOWS, number=color.number) - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[color.number]) - - color_number = WINDOWS_PALETTE.match(triplet) - return Color(color.name, ColorType.WINDOWS, number=color_number) - return color + 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: + gray = round(l * 25.0) + if gray == 0: + color_number = 16 + elif gray == 25: + color_number = 231 + else: + color_number = 231 + gray + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + color_number = ( + 16 + 36 * round(red * 5.0) + 6 * round(green * 5.0) + round(blue * 5.0) + ) + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + # Convert to standard from truecolor or 8-bit + elif system == ColorSystem.STANDARD: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = STANDARD_PALETTE.match(triplet) + return Color(self.name, ColorType.STANDARD, number=color_number) + + elif system == ColorSystem.WINDOWS: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + if self.number < 16: + return Color(self.name, ColorType.WINDOWS, number=self.number) + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = WINDOWS_PALETTE.match(triplet) + return Color(self.name, ColorType.WINDOWS, number=color_number) + + return self def parse_rgb_hex(hex_color: str) -> ColorTriplet: diff --git a/rich/palette.py b/rich/palette.py index cd55dec9b8..f29587945c 100644 --- a/rich/palette.py +++ b/rich/palette.py @@ -1,6 +1,6 @@ -from functools import lru_cache from math import sqrt -from typing import TYPE_CHECKING, Sequence, Tuple +from functools import lru_cache +from typing import Sequence, Tuple, TYPE_CHECKING from .color_triplet import ColorTriplet @@ -20,8 +20,8 @@ def __getitem__(self, number: int) -> ColorTriplet: def __rich__(self) -> "Table": from rich.color import Color from rich.style import Style - from rich.table import Table from rich.text import Text + from rich.table import Table table = Table( "index", @@ -40,6 +40,8 @@ def __rich__(self) -> "Table": ) return table + # This is somewhat inefficient and needs caching + @lru_cache(maxsize=1024) def match(self, color: Tuple[int, int, int]) -> int: """Find a color from a palette that most closely matches a given color. @@ -49,38 +51,30 @@ def match(self, color: Tuple[int, int, int]) -> int: Returns: int: Index of closes matching color. """ - return _match_palette_cached(color=color, available_colors=tuple(self._colors)) - - -@lru_cache(maxsize=1024) -def _match_palette_cached( - color: Tuple[int, int, int], available_colors: Tuple[Tuple[int, int, int]] -) -> int: - red1, green1, blue1 = color - _sqrt = sqrt - get_color = available_colors.__getitem__ - - def get_color_distance(index: int) -> float: - """Get the distance to a color.""" - red2, green2, blue2 = get_color(index) - red_mean = (red1 + red2) // 2 - red = red1 - red2 - green = green1 - green2 - blue = blue1 - blue2 - return _sqrt( - (((512 + red_mean) * red * red) >> 8) - + 4 * green * green - + (((767 - red_mean) * blue * blue) >> 8) - ) + red1, green1, blue1 = color + _sqrt = sqrt + get_color = self._colors.__getitem__ + + def get_color_distance(index: int) -> float: + """Get the distance to a color.""" + red2, green2, blue2 = get_color(index) + red_mean = (red1 + red2) // 2 + red = red1 - red2 + green = green1 - green2 + blue = blue1 - blue2 + return _sqrt( + (((512 + red_mean) * red * red) >> 8) + + 4 * green * green + + (((767 - red_mean) * blue * blue) >> 8) + ) - min_index = min(range(len(available_colors)), key=get_color_distance) - return min_index + min_index = min(range(len(self._colors)), key=get_color_distance) + return min_index if __name__ == "__main__": # pragma: no cover import colorsys from typing import Iterable - from rich.color import Color from rich.console import Console, ConsoleOptions from rich.segment import Segment diff --git a/rich/progress_bar.py b/rich/progress_bar.py index ce51a86040..1797b5f786 100644 --- a/rich/progress_bar.py +++ b/rich/progress_bar.py @@ -1,5 +1,5 @@ -import functools import math +from functools import lru_cache from time import monotonic from typing import Iterable, List, Optional @@ -15,51 +15,6 @@ PULSE_SIZE = 20 -@functools.lru_cache(maxsize=16) -def _get_pulse_segments( - fore_style: Style, - back_style: Style, - color_system: str, - no_color: bool, - ascii: bool = False, -) -> List[Segment]: - """Get a list of segments to render a pulse animation. - - Returns: - List[Segment]: A list of segments, one segment per character. - """ - bar = "-" if ascii else "━" - segments: List[Segment] = [] - if color_system not in ("standard", "eight_bit", "truecolor") or no_color: - segments += [Segment(bar, fore_style)] * (PULSE_SIZE // 2) - segments += [Segment(" " if no_color else bar, back_style)] * ( - PULSE_SIZE - (PULSE_SIZE // 2) - ) - return segments - - append = segments.append - fore_color = ( - fore_style.color.get_truecolor() - if fore_style.color - else ColorTriplet(255, 0, 255) - ) - back_color = ( - back_style.color.get_truecolor() if back_style.color else ColorTriplet(0, 0, 0) - ) - cos = math.cos - pi = math.pi - _Segment = Segment - _Style = Style - from_triplet = Color.from_triplet - - for index in range(PULSE_SIZE): - position = index / PULSE_SIZE - fade = 0.5 + cos((position * pi * 2)) / 2.0 - color = blend_rgb(fore_color, back_color, cross_fade=fade) - append(_Segment(bar, _Style(color=from_triplet(color)))) - return segments - - class ProgressBar(JupyterMixin): """Renders a (progress) bar. Used by rich.progress. @@ -109,6 +64,53 @@ def percentage_completed(self) -> float: completed = min(100, max(0.0, completed)) return completed + @lru_cache(maxsize=16) + def _get_pulse_segments( + self, + fore_style: Style, + back_style: Style, + color_system: str, + no_color: bool, + ascii: bool = False, + ) -> List[Segment]: + """Get a list of segments to render a pulse animation. + + Returns: + List[Segment]: A list of segments, one segment per character. + """ + bar = "-" if ascii else "━" + segments: List[Segment] = [] + if color_system not in ("standard", "eight_bit", "truecolor") or no_color: + segments += [Segment(bar, fore_style)] * (PULSE_SIZE // 2) + segments += [Segment(" " if no_color else bar, back_style)] * ( + PULSE_SIZE - (PULSE_SIZE // 2) + ) + return segments + + append = segments.append + fore_color = ( + fore_style.color.get_truecolor() + if fore_style.color + else ColorTriplet(255, 0, 255) + ) + back_color = ( + back_style.color.get_truecolor() + if back_style.color + else ColorTriplet(0, 0, 0) + ) + cos = math.cos + pi = math.pi + _Segment = Segment + _Style = Style + from_triplet = Color.from_triplet + + for index in range(PULSE_SIZE): + position = index / PULSE_SIZE + fade = 0.5 + cos((position * pi * 2)) / 2.0 + color = blend_rgb(fore_color, back_color, cross_fade=fade) + append(_Segment(bar, _Style(color=from_triplet(color)))) + return segments + def update(self, completed: float, total: Optional[float] = None) -> None: """Update progress with new values. @@ -137,7 +139,7 @@ def _render_pulse( fore_style = console.get_style(self.pulse_style, default="white") back_style = console.get_style(self.style, default="black") - pulse_segments = _get_pulse_segments( + pulse_segments = self._get_pulse_segments( fore_style, back_style, console.color_system, console.no_color, ascii=ascii ) segment_count = len(pulse_segments) diff --git a/rich/style.py b/rich/style.py index 4153e2774c..0787c33147 100644 --- a/rich/style.py +++ b/rich/style.py @@ -1,14 +1,15 @@ import sys from functools import lru_cache -from marshal import dumps, loads +from marshal import loads, dumps from random import randint -from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast +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 Result, rich_repr +from .repr import rich_repr, Result from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme + # Style instances and style definitions are often interchangeable StyleType = Union[str, "Style"] @@ -574,9 +575,42 @@ def parse(cls, style_definition: str) -> "Style": style = Style(color=color, bgcolor=bgcolor, link=link, **attributes) return style + @lru_cache(maxsize=1024) def get_html_style(self, theme: Optional[TerminalTheme] = None) -> str: """Get a CSS style rule.""" - return _get_html_style_cached(self, theme) + theme = theme or DEFAULT_TERMINAL_THEME + css: List[str] = [] + append = css.append + + color = self.color + bgcolor = self.bgcolor + if self.reverse: + color, bgcolor = bgcolor, color + if self.dim: + foreground_color = ( + theme.foreground_color if color is None else color.get_truecolor(theme) + ) + color = Color.from_triplet( + blend_rgb(foreground_color, theme.background_color, 0.5) + ) + if color is not None: + theme_color = color.get_truecolor(theme) + append(f"color: {theme_color.hex}") + append(f"text-decoration-color: {theme_color.hex}") + if bgcolor is not None: + theme_color = bgcolor.get_truecolor(theme, foreground=False) + append(f"background-color: {theme_color.hex}") + if self.bold: + append("font-weight: bold") + if self.italic: + append("font-style: italic") + if self.underline: + append("text-decoration: underline") + if self.strike: + append("text-decoration: line-through") + if self.overline: + append("text-decoration: overline") + return "; ".join(css) @classmethod def combine(cls, styles: Iterable["Style"]) -> "Style": @@ -717,43 +751,6 @@ def __add__(self, style: Optional["Style"]) -> "Style": NULL_STYLE = Style() -@lru_cache(maxsize=1024) -def _get_html_style_cached(style: Style, theme: Optional[TerminalTheme] = None) -> str: - theme = theme or DEFAULT_TERMINAL_THEME - css: List[str] = [] - append = css.append - - color = style.color - bgcolor = style.bgcolor - if style.reverse: - color, bgcolor = bgcolor, color - if style.dim: - foreground_color = ( - theme.foreground_color if color is None else color.get_truecolor(theme) - ) - color = Color.from_triplet( - blend_rgb(foreground_color, theme.background_color, 0.5) - ) - if color is not None: - theme_color = color.get_truecolor(theme) - append(f"color: {theme_color.hex}") - append(f"text-decoration-color: {theme_color.hex}") - if bgcolor is not None: - theme_color = bgcolor.get_truecolor(theme, foreground=False) - append(f"background-color: {theme_color.hex}") - if style.bold: - append("font-weight: bold") - if style.italic: - append("font-style: italic") - if style.underline: - append("text-decoration: underline") - if style.strike: - append("text-decoration: line-through") - if style.overline: - append("text-decoration: overline") - return "; ".join(css) - - class StyleStack: """A stack of styles.""" diff --git a/tests/test_bar.py b/tests/test_bar.py index 5d36a8caa8..021a8aaac1 100644 --- a/tests/test_bar.py +++ b/tests/test_bar.py @@ -1,5 +1,5 @@ from rich.console import Console -from rich.progress_bar import ProgressBar, _get_pulse_segments +from rich.progress_bar import ProgressBar from rich.segment import Segment from rich.style import Style @@ -63,7 +63,7 @@ def test_pulse(): def test_get_pulse_segments(): bar = ProgressBar() - segments = _get_pulse_segments( + segments = bar._get_pulse_segments( Style.parse("red"), Style.parse("yellow"), None, False, False ) print(repr(segments)) From 4d1a1a94196a55d55a4a9c060f8e1e6e81b5e23f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Wed, 19 Jan 2022 15:42:35 +0000 Subject: [PATCH 243/287] Remove unused import --- tests/test_inspect.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_inspect.py b/tests/test_inspect.py index e947a7d6a7..05a78b8718 100644 --- a/tests/test_inspect.py +++ b/tests/test_inspect.py @@ -1,6 +1,5 @@ import io import sys -from unittest import mock import pytest From dbe30faa107c93a137e2b3a3c7264cfb45da6a41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jan 2022 20:45:31 +0000 Subject: [PATCH 244/287] Bump ipython from 7.16.2 to 7.16.3 Bumps [ipython](https://github.com/ipython/ipython) from 7.16.2 to 7.16.3. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/7.16.2...7.16.3) --- updated-dependencies: - dependency-name: ipython dependency-type: indirect ... Signed-off-by: dependabot[bot] --- poetry.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index ee2eaa39e1..59c3236d6d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3,7 +3,7 @@ name = "appnope" version = "0.1.2" description = "Disable App Nap on macOS >= 10.9" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -74,7 +74,7 @@ name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -195,7 +195,7 @@ name = "decorator" version = "5.1.0" description = "Decorators for Humans" category = "main" -optional = true +optional = false python-versions = ">=3.5" [[package]] @@ -306,10 +306,10 @@ test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "nose", "jedi (<=0.17.2)"] [[package]] name = "ipython" -version = "7.16.2" +version = "7.16.3" description = "IPython: Productive Interactive Computing" category = "main" -optional = true +optional = false python-versions = ">=3.6" [package.dependencies] @@ -340,7 +340,7 @@ name = "ipython-genutils" version = "0.2.0" description = "Vestigial utilities from IPython" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -368,7 +368,7 @@ name = "jedi" version = "0.17.2" description = "An autocompletion tool for Python that can be used for text editors." category = "main" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] @@ -641,7 +641,7 @@ name = "parso" version = "0.7.1" description = "A Python Parser" category = "main" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] @@ -660,7 +660,7 @@ name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." category = "main" -optional = true +optional = false python-versions = "*" [package.dependencies] @@ -671,7 +671,7 @@ name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -735,7 +735,7 @@ name = "prompt-toolkit" version = "3.0.24" description = "Library for building powerful interactive command lines in Python" category = "main" -optional = true +optional = false python-versions = ">=3.6.2" [package.dependencies] @@ -746,7 +746,7 @@ name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -953,7 +953,7 @@ name = "traitlets" version = "4.3.3" description = "Traitlets Python config system" category = "main" -optional = true +optional = false python-versions = "*" [package.dependencies] @@ -1013,7 +1013,7 @@ name = "wcwidth" version = "0.2.5" description = "Measures the displayed width of unicode strings in a terminal" category = "main" -optional = true +optional = false python-versions = "*" [[package]] @@ -1273,8 +1273,8 @@ ipykernel = [ {file = "ipykernel-5.5.6.tar.gz", hash = "sha256:4ea44b90ae1f7c38987ad58ea0809562a17c2695a0499644326f334aecd369ec"}, ] ipython = [ - {file = "ipython-7.16.2-py3-none-any.whl", hash = "sha256:2f644313be4fdc5c8c2a17467f2949c29423c9e283a159d1fc9bf450a1a300af"}, - {file = "ipython-7.16.2.tar.gz", hash = "sha256:613085f8acb0f35f759e32bea35fba62c651a4a2e409a0da11414618f5eec0c4"}, + {file = "ipython-7.16.3-py3-none-any.whl", hash = "sha256:c0427ed8bc33ac481faf9d3acf7e84e0010cdaada945e0badd1e2e74cc075833"}, + {file = "ipython-7.16.3.tar.gz", hash = "sha256:5ac47dc9af66fc2f5530c12069390877ae372ac905edca75a92a6e363b5d7caa"}, ] ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, From 317125a86046c06e8da422c92b6d089aa79f4083 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Sun, 23 Jan 2022 03:27:34 +0800 Subject: [PATCH 245/287] Add Traditional Chinese text --- rich/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/__main__.py b/rich/__main__.py index 132e809412..78f3f7b006 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -97,7 +97,7 @@ def comparison(renderable1: RenderableType, renderable2: RenderableType) -> Tabl table.add_row( "Asian\nlanguage\nsupport", - ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다", + ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다\n:flag_for_taiwan: 本函式庫支援中日韓文字元!", ) markup_example = ( From ecb18d4c9323ccfb71a4030b3ab4261a46f84ddc Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Sun, 23 Jan 2022 03:28:48 +0800 Subject: [PATCH 246/287] Translate Traditional Chinese readme --- README.zh-tw.md | 144 ++++++++++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/README.zh-tw.md b/README.zh-tw.md index 189b1fadad..2e4b857b02 100644 --- a/README.zh-tw.md +++ b/README.zh-tw.md @@ -21,31 +21,31 @@ • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) -Rich is a Python library for _rich_ text and beautiful formatting in the terminal. +Rich 是一款 Python 函式庫,提供終端機介面中 _豐富的_ 文字效果及精美的格式設定。 -The [Rich API](https://rich.readthedocs.io/en/latest/) makes it easy to add color and style to terminal output. Rich can also render pretty tables, progress bars, markdown, syntax highlighted source code, tracebacks, and more — out of the box. +[Rich API](https://rich.readthedocs.io/en/latest/) 讓終端機介面加上色彩及樣式變得易如反掌。Rich 也可以繪製漂亮的表格、進度條、Markdown、語法突顯的程式碼、Traceback(追溯)……。 ![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) -For a video introduction to Rich see [calmcode.io](https://calmcode.io/rich/introduction.html) by [@fishnets88](https://twitter.com/fishnets88). +關於 Rich 的介紹,請參見 [@fishnets88](https://twitter.com/fishnets88) 在 [calmcode.io](https://calmcode.io/rich/introduction.html) 錄製的影片。 -See what [people are saying about Rich](https://www.willmcgugan.com/blog/pages/post/rich-tweets/). +[看看其他人對於 Rich 的討論](https://www.willmcgugan.com/blog/pages/post/rich-tweets/)。 -## Compatibility +## 相容性 -Rich works with Linux, OSX, and Windows. True color / emoji works with new Windows Terminal, classic terminal is limited to 16 colors. Rich requires Python 3.6.1 or later. +Rich 可在 Linux、macOS、Windows 上運作。在新的 Windows Terminal 中可支援顯示全彩及 Emoji,但傳統的終端機中僅支援 16 色。Rich 需要的 Python 最低版本為 3.6.1。 -Rich works with [Jupyter notebooks](https://jupyter.org/) with no additional configuration required. +Rich 可在 [Jupyter notebooks](https://jupyter.org/) 上使用,無須額外設定。 -## Installing +## 安裝 -Install with `pip` or your favorite PyPI package manager. +以 `pip` 或 PyPI 套件管理器安裝。 ```sh python -m pip install rich ``` -Run the following to test Rich output on your terminal: +以此命令測試 Rich 在終端機的輸出效果: ```sh python -m rich @@ -53,7 +53,7 @@ python -m rich ## Rich Print -To effortlessly add rich output to your application, you can import the [rich print](https://rich.readthedocs.io/en/latest/introduction.html#quick-start) method, which has the same signature as the builtin Python function. Try this: +匯入 [rich print](https://rich.readthedocs.io/en/latest/introduction.html#quick-start) 方法就可以輕鬆地讓程式進行 rich 輸出,rich print 與 Python 內建的函式用法相似。試試: ```python from rich import print @@ -65,7 +65,7 @@ print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals()) ## Rich REPL -Rich can be installed in the Python REPL, so that any data structures will be pretty printed and highlighted. +Rich 可以安裝在 Python REPL 中,如此一來任何資料結構都能被漂亮的輸出及突顯標示。 ```python >>> from rich import pretty @@ -74,9 +74,9 @@ Rich can be installed in the Python REPL, so that any data structures will be pr ![REPL](https://github.com/willmcgugan/rich/raw/master/imgs/repl.png) -## Using the Console +## 使用 Console -For more control over rich terminal content, import and construct a [Console](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console) object. +匯入並建構 [Console](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console) 物件,以更全面地控制 rich 終端機內容。 ```python from rich.console import Console @@ -84,25 +84,25 @@ from rich.console import Console console = Console() ``` -The Console object has a `print` method which has an intentionally similar interface to the builtin `print` function. Here's an example of use: +Console 物件有個 `print` 方法,且刻意設計的與內建 `print` 函式相似。參考此範例: ```python console.print("Hello", "World!") ``` -As you might expect, this will print `"Hello World!"` to the terminal. Note that unlike the builtin `print` function, Rich will word-wrap your text to fit within the terminal width. +如同預期的,這會將 `"Hello World!"` 印在終端機。須注意不同於內建的 `print` 函式,Rich 會自動將過長的文字換行,以符合終端機的寬度。 -There are a few ways of adding color and style to your output. You can set a style for the entire output by adding a `style` keyword argument. Here's an example: +有幾種加上顏色及樣式的方式。您可以用 `style` 引數設定輸出內容的樣式,參考此範例: ```python console.print("Hello", "World!", style="bold red") ``` -The output will be something like the following: +輸出結果如下圖: ![Hello World](https://github.com/willmcgugan/rich/raw/master/imgs/hello_world.png) -That's fine for styling a line of text at a time. For more finely grained styling, Rich renders a special markup which is similar in syntax to [bbcode](https://en.wikipedia.org/wiki/BBCode). Here's an example: +介紹完了如何對整行文字設定樣式,接著來看看更細部的使用。Rich 可以接受類似 [bbcode](https://en.wikipedia.org/wiki/BBCode) 的語法,對個別文字設定樣式。參考此範例: ```python console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a [i]way[/i].") @@ -110,11 +110,11 @@ console.print("Where there is a [bold cyan]Will[/bold cyan] there [u]is[/u] a [i ![Console Markup](https://github.com/willmcgugan/rich/raw/master/imgs/where_there_is_a_will.png) -You can use a Console object to generate sophisticated output with minimal effort. See the [Console API](https://rich.readthedocs.io/en/latest/console.html) docs for details. +您可以用 Console 物件不費吹灰之力地達成細膩的輸出效果。參閱 [Console API](https://rich.readthedocs.io/en/latest/console.html) 說明文件以了解細節。 ## Rich Inspect -Rich has an [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) function which can produce a report on any Python object, such as class, instance, or builtin. +Rich 提供了 [inspect](https://rich.readthedocs.io/en/latest/reference/init.html?highlight=inspect#rich.inspect) 函式,可以對任何 Python 物件,如 class、instance 或 builtin ,為其產生一份報告。 ```python >>> my_list = ["foo", "bar"] @@ -124,18 +124,18 @@ Rich has an [inspect](https://rich.readthedocs.io/en/latest/reference/init.html? ![Log](https://github.com/willmcgugan/rich/raw/master/imgs/inspect.png) -See the [inspect docs](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) for details. +參閱 [inspect 說明文件](https://rich.readthedocs.io/en/latest/reference/init.html#rich.inspect) 以了解細節。 -# Rich Library +# Rich 函式庫 Rich contains a number of builtin _renderables_ you can use to create elegant output in your CLI and help you debug your code. -Click the following headings for details: +按一下子標題以了解細節:
Log -The Console object has a `log()` method which has a similar interface to `print()`, but also renders a column for the current time and the file and line which made the call. By default Rich will do syntax highlighting for Python structures and for repr strings. If you log a collection (i.e. a dict or a list) Rich will pretty print it so that it fits in the available space. Here's an example of some of these features. +Console 物件提供了 `log()` 方法,使用方式與 `print()` 類似,但還多了一欄來顯示目前時間、進行呼叫的檔案及行號。預設情況下 Rich 會語法突顯標示 Python 的結構及 repr 字串。若使用於字典或串列這類集合性物件,Rich 會將其漂亮地印出來,以符合可用空間。此範例示範了這些功能。 ```python from rich.console import Console @@ -160,19 +160,19 @@ def test_log(): test_log() ``` -The above produces the following output: +上面的程式碼會產生下圖結果: ![Log](https://github.com/willmcgugan/rich/raw/master/imgs/log.png) -Note the `log_locals` argument, which outputs a table containing the local variables where the log method was called. +注意到 `log_locals` 引數,可用來輸出一張表格,用來顯示 log 方法被呼叫時,區域變數的內容。 -The log method could be used for logging to the terminal for long running applications such as servers, but is also a very nice debugging aid. +log 方法可用於伺服器上長時間運作的程式,也很適合一般程式偵錯用途。
Logging Handler -You can also use the builtin [Handler class](https://rich.readthedocs.io/en/latest/logging.html) to format and colorize output from Python's logging module. Here's an example of the output: +您也可以使用內建的 [Handler 類別](https://rich.readthedocs.io/en/latest/logging.html) 來將 Python logging 模組的輸出內容格式化並賦予色彩: ![Logging](https://github.com/willmcgugan/rich/raw/master/imgs/logging.png) @@ -181,27 +181,27 @@ You can also use the builtin [Handler class](https://rich.readthedocs.io/en/late
Emoji -To insert an emoji in to console output place the name between two colons. Here's an example: +以一對冒號包住表情符號的名稱,來透過 console 插入 Emoji。參考範例: ```python >>> console.print(":smiley: :vampire: :pile_of_poo: :thumbs_up: :raccoon:") 😃 🧛 💩 👍 🦝 ``` -Please use this feature wisely. +請謹慎使用此功能。
-Tables +表格 -Rich can render flexible [tables](https://rich.readthedocs.io/en/latest/tables.html) with unicode box characters. There is a large variety of formatting options for borders, styles, cell alignment etc. +Rich 可以用 unicode box 字元繪製彈性的 [表格](https://rich.readthedocs.io/en/latest/tables.html)。格式設定十分多元,包含框線、樣式、儲存格對齊……。 ![table movie](https://github.com/willmcgugan/rich/raw/master/imgs/table_movie.gif) -The animation above was generated with [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) in the examples directory. +上圖的動畫效果是以 [table_movie.py](https://github.com/willmcgugan/rich/blob/master/examples/table_movie.py) 產生的,該檔案位於 examples 資料夾。 -Here's a simpler table example: +參考這個簡單的表格範例: ```python from rich.console import Console @@ -233,24 +233,24 @@ table.add_row( console.print(table) ``` -This produces the following output: +執行結果如圖: ![table](https://github.com/willmcgugan/rich/raw/master/imgs/table.png) -Note that console markup is rendered in the same way as `print()` and `log()`. In fact, anything that is renderable by Rich may be included in the headers / rows (even other tables). +請留意,主控台標記的呈現方式與 `print()`、`log()` 相同。事實上,由 Rich 繪製的任何東西都可以被放在任何標題、列,甚至其他表格裡。 -The `Table` class is smart enough to resize columns to fit the available width of the terminal, wrapping text as required. Here's the same example, with the terminal made smaller than the table above: +`Table` 類別很聰明,能夠自動調整欄寬來配合終端機的大小,也會在需要時自動將文字換行。此範例的程式碼與上一個相同,然而終端機變小了一點: ![table2](https://github.com/willmcgugan/rich/raw/master/imgs/table2.png)
-Progress Bars +進度條 -Rich can render multiple flicker-free [progress](https://rich.readthedocs.io/en/latest/progress.html) bars to track long-running tasks. +Rich 可繪製多個不閃爍的 [進度條](https://rich.readthedocs.io/en/latest/progress.html),以追蹤需時較久的工作。 -For basic usage, wrap any sequence in the `track` function and iterate over the result. Here's an example: +基本的使用方式,是將序列放在 `track` 函式中,再對其結果疊代。參考此範例: ```python from rich.progress import track @@ -259,22 +259,22 @@ for step in track(range(100)): do_step(step) ``` -It's not much harder to add multiple progress bars. Here's an example taken from the docs: +新增多個進度條也不是難事,來看看說明文件中的範例: ![progress](https://github.com/willmcgugan/rich/raw/master/imgs/progress.gif) -The columns may be configured to show any details you want. Built-in columns include percentage complete, file size, file speed, and time remaining. Here's another example showing a download in progress: +您可以調整要顯示的狀態欄位。內建的欄位包含完成百分比、檔案大小、讀寫速度及剩餘時間。來看看另一個用來顯示下載進度的範例: ![progress](https://github.com/willmcgugan/rich/raw/master/imgs/downloader.gif) -To try this out yourself, see [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) which can download multiple URLs simultaneously while displaying progress. +想嘗試看看嗎?您可以在 [examples/downloader.py](https://github.com/willmcgugan/rich/blob/master/examples/downloader.py) 取得此範例程式。此程式可以在下載多個檔案時顯示各自的進度。
-Status +狀態 -For situations where it is hard to calculate progress, you can use the [status](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console.status) method which will display a 'spinner' animation and message. The animation won't prevent you from using the console as normal. Here's an example: +有些狀況下很難估計進度,就可以使用 [status](https://rich.readthedocs.io/en/latest/reference/console.html#rich.console.Console.status) 方法,此方法會顯示「spinner」動畫及訊息。該動畫播放時,仍可正常操作主控台。參考此範例: ```python from time import sleep @@ -290,45 +290,45 @@ with console.status("[bold green]Working on tasks...") as status: console.log(f"{task} complete") ``` -This generates the following output in the terminal. +終端機的顯示效果如下: ![status](https://github.com/willmcgugan/rich/raw/master/imgs/status.gif) -The spinner animations were borrowed from [cli-spinners](https://www.npmjs.com/package/cli-spinners). You can select a spinner by specifying the `spinner` parameter. Run the following command to see the available values: +該 spinner 動畫乃借用自 [cli-spinners](https://www.npmjs.com/package/cli-spinners)。可以用 `spinner` 參數指定 spinner 樣式。執行此命令以顯示可用的值: ``` python -m rich.spinner ``` -The above command generates the following output in the terminal: +此命令在終端機的輸出結果如下圖: ![spinners](https://github.com/willmcgugan/rich/raw/master/imgs/spinners.gif)
-Tree + -Rich can render a [tree](https://rich.readthedocs.io/en/latest/tree.html) with guide lines. A tree is ideal for displaying a file structure, or any other hierarchical data. +Rich 可以用導引線繪製一棵 [樹](https://rich.readthedocs.io/en/latest/tree.html)。樹很適合用來顯示檔案結構,或其他繼承性的資料。 -The labels of the tree can be simple text or anything else Rich can render. Run the following for a demonstration: +可以用文字或其他 Rich 能繪製的元素作為樹的標籤。執行下列程式碼來看看效果: ``` python -m rich.tree ``` -This generates the following output: +這會產生下圖的結果: ![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/tree.png) -See the [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) example for a script that displays a tree view of any directory, similar to the linux `tree` command. +您可以參考 [tree.py](https://github.com/willmcgugan/rich/blob/master/examples/tree.py) 範例程式,此程式可以樹狀圖展示目錄結構,如同 Linux 的 `tree` 命令。
-Columns +資料欄 -Rich can render content in neat [columns](https://rich.readthedocs.io/en/latest/columns.html) with equal or optimal width. Here's a very basic clone of the (MacOS / Linux) `ls` command which displays a directory listing in columns: +Rich 可以將內容呈現於整齊的 [資料欄](https://rich.readthedocs.io/en/latest/columns.html) 中,其欄寬可為等寬或最適寬度。此範例仿作了 macOS / Linux 系統中 `ls` 命令的基本功能,可以用資料欄列出目錄: ```python import os @@ -341,7 +341,7 @@ directory = os.listdir(sys.argv[1]) print(Columns(directory)) ``` -The following screenshot is the output from the [columns example](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) which displays data pulled from an API in columns: +此螢幕截圖為 [資料欄範例](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) 的輸出結果。此程式從某 API 取得資料,並以資料欄呈現: ![columns](https://github.com/willmcgugan/rich/raw/master/imgs/columns.png) @@ -350,9 +350,9 @@ The following screenshot is the output from the [columns example](https://github
Markdown -Rich can render [markdown](https://rich.readthedocs.io/en/latest/markdown.html) and does a reasonable job of translating the formatting to the terminal. +Rich 可以繪製 [Markdown](https://rich.readthedocs.io/en/latest/markdown.html) 並處理了將其轉換為終端機格式的大量工作。 -To render markdown import the `Markdown` class and construct it with a string containing markdown code. Then print it to the console. Here's an example: +先匯入 `Markdown` 類別,再以內容為 Markdown 語言的字串建構一個物件,接著將其印到 console。參考此範例: ```python from rich.console import Console @@ -364,16 +364,16 @@ with open("README.md") as readme: console.print(markdown) ``` -This will produce output something like the following: +執行結果如下圖: ![markdown](https://github.com/willmcgugan/rich/raw/master/imgs/markdown.png)
-Syntax Highlighting +語法突顯 -Rich uses the [pygments](https://pygments.org/) library to implement [syntax highlighting](https://rich.readthedocs.io/en/latest/syntax.html). Usage is similar to rendering markdown; construct a `Syntax` object and print it to the console. Here's an example: +Rich 使用了 [pygments](https://pygments.org/) 函式庫來實作 [語法突顯](https://rich.readthedocs.io/en/latest/syntax.html) 功能。使用方式與繪製 Markdown 相似,先建構 `Syntax` 物件並將其印到 console。參考此範例: ```python from rich.console import Console @@ -399,34 +399,34 @@ console = Console() console.print(syntax) ``` -This will produce the following output: +執行結果如下圖: ![syntax](https://github.com/willmcgugan/rich/raw/master/imgs/syntax.png)
-Tracebacks +Tracebacks(追溯) -Rich can render [beautiful tracebacks](https://rich.readthedocs.io/en/latest/traceback.html) which are easier to read and show more code than standard Python tracebacks. You can set Rich as the default traceback handler so all uncaught exceptions will be rendered by Rich. +Rich 可以繪製 [漂亮的 tracebacks](https://rich.readthedocs.io/en/latest/traceback.html),相較標準的 Python traceback 顯示了更多程式碼且更好懂。您可以將 Rich 設為預設的 traceback handler(處理常式),如此一來所有未接住的例外都由 Rich 呈現。 -Here's what it looks like on OSX (similar on Linux): +它在 macOS 上執行的效果如圖(Linux 上差異不大): ![traceback](https://github.com/willmcgugan/rich/raw/master/imgs/traceback.png)
-All Rich renderables make use of the [Console Protocol](https://rich.readthedocs.io/en/latest/protocol.html), which you can also use to implement your own Rich content. +所有可由 Rich 繪製的物件都用到了 [Console 協定](https://rich.readthedocs.io/en/latest/protocol.html),您也可以依此實作自訂的 Rich 內容。 -# Rich for enterprise +# Rich 企業版 -Available as part of the Tidelift Subscription. +可在 Tidelift 訂閱方案取得。 -The maintainers of Rich and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/pypi-rich?utm_source=pypi-rich&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) +Rich 及其他數以千計的套件維護者正與 Tidelift 合作,以提供開放原始碼套件的商業性支援。此計畫能協助您節省時間、避開風險,同時也讓套件的維護者獲得報酬。[了解更多。](https://tidelift.com/subscription/pkg/pypi-rich?utm_source=pypi-rich&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) -# Projects using Rich +# 使用 Rich 的專案 -Here are a few projects using Rich: +以下列出幾個使用 Rich 的專案: - [BrancoLab/BrainRender](https://github.com/BrancoLab/BrainRender) a python package for the visualization of three dimensional neuro-anatomical data From 7fe872bc9f659e9fc18bc4d9a6c093c28bd5c138 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Sun, 23 Jan 2022 03:48:32 +0800 Subject: [PATCH 247/287] Update `README.zh-tw.md` --- README.zh-tw.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.zh-tw.md b/README.zh-tw.md index 2e4b857b02..8ff4b4c00f 100644 --- a/README.zh-tw.md +++ b/README.zh-tw.md @@ -128,7 +128,7 @@ Rich 提供了 [inspect](https://rich.readthedocs.io/en/latest/reference/init.ht # Rich 函式庫 -Rich contains a number of builtin _renderables_ you can use to create elegant output in your CLI and help you debug your code. +Rich 包含了一系列可繪製的物件,您可以使用它們來印出精美的畫面,或者協助偵錯程式碼。 按一下子標題以了解細節: From 14333a49daf18fc504403578db2708eec790fde0 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Sun, 23 Jan 2022 23:55:44 +0800 Subject: [PATCH 248/287] Change wording and update `README.zh-tw.md` --- README.zh-tw.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.zh-tw.md b/README.zh-tw.md index 8ff4b4c00f..29b5e10281 100644 --- a/README.zh-tw.md +++ b/README.zh-tw.md @@ -21,9 +21,9 @@ • [Italian readme](https://github.com/willmcgugan/rich/blob/master/README.it.md) • [Русский readme](https://github.com/willmcgugan/rich/blob/master/README.ru.md) -Rich 是一款 Python 函式庫,提供終端機介面中 _豐富的_ 文字效果及精美的格式設定。 +Rich 是一款提供終端機介面中 _豐富的_ 文字效果及精美的格式設定的 Python 函式庫。 -[Rich API](https://rich.readthedocs.io/en/latest/) 讓終端機介面加上色彩及樣式變得易如反掌。Rich 也可以繪製漂亮的表格、進度條、Markdown、語法突顯的程式碼、Traceback(追溯)……。 +[Rich API](https://rich.readthedocs.io/en/latest/) 讓終端機介面加上色彩及樣式變得易如反掌。Rich 也可以繪製漂亮的表格、進度條、Markdown、語法醒目標示的程式碼、Traceback(追溯)……。 ![Features](https://github.com/willmcgugan/rich/raw/master/imgs/features.png) @@ -33,7 +33,7 @@ Rich 是一款 Python 函式庫,提供終端機介面中 _豐富的_ 文字效 ## 相容性 -Rich 可在 Linux、macOS、Windows 上運作。在新的 Windows Terminal 中可支援顯示全彩及 Emoji,但傳統的終端機中僅支援 16 色。Rich 需要的 Python 最低版本為 3.6.1。 +Rich 可在 Linux、macOS、Windows 上運作。在新的 Windows Terminal 中可支援顯示全彩及 Emoji,但傳統的終端機中僅支援 16 色。Rich 最低需要的 Python 版本為 3.6.1。 Rich 可在 [Jupyter notebooks](https://jupyter.org/) 上使用,無須額外設定。 @@ -65,7 +65,7 @@ print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals()) ## Rich REPL -Rich 可以安裝在 Python REPL 中,如此一來任何資料結構都能被漂亮的輸出及突顯標示。 +Rich 可以安裝在 Python REPL 中,如此一來就可以漂亮的輸出與突顯標示任何資料結構。 ```python >>> from rich import pretty @@ -135,7 +135,7 @@ Rich 包含了一系列可繪製的物件,您可以使用它們來印出精美
Log -Console 物件提供了 `log()` 方法,使用方式與 `print()` 類似,但還多了一欄來顯示目前時間、進行呼叫的檔案及行號。預設情況下 Rich 會語法突顯標示 Python 的結構及 repr 字串。若使用於字典或串列這類集合性物件,Rich 會將其漂亮地印出來,以符合可用空間。此範例示範了這些功能。 +Console 物件提供了 `log()` 方法,使用方式與 `print()` 類似,但還多了一欄來顯示目前時間、進行呼叫的檔案及行號。預設情況下 Rich 會語法醒目標示 Python 的結構及 repr 字串。若使用於字典或串列這類集合性物件,Rich 會將其漂亮地印出來,以符合可用空間。此範例示範了這些功能。 ```python from rich.console import Console @@ -371,9 +371,9 @@ console.print(markdown)
-語法突顯 +語法醒目標示 -Rich 使用了 [pygments](https://pygments.org/) 函式庫來實作 [語法突顯](https://rich.readthedocs.io/en/latest/syntax.html) 功能。使用方式與繪製 Markdown 相似,先建構 `Syntax` 物件並將其印到 console。參考此範例: +Rich 使用了 [pygments](https://pygments.org/) 函式庫來實作 [語法醒目標示](https://rich.readthedocs.io/en/latest/syntax.html) 功能。使用方式與繪製 Markdown 相似,先建構 `Syntax` 物件並將其印到 console。參考此範例: ```python from rich.console import Console From 31bd59ec7137c8117c5075f02f9553a70a3b6bb1 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Mon, 24 Jan 2022 00:07:34 +0800 Subject: [PATCH 249/287] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3819a7813..b861718303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 +- Add Traditional Chinese readme ### Added @@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **breaking** Deprecated rich.console.RenderGroup, now named rich.console.Group - **breaking** `Syntax.__init__` parameter `lexer_name` renamed to `lexer` - Syntax constructor accepts both str and now a pygments lexer https://github.com/Textualize/rich/pull/1748 +- Rename the file name of Simplified Chinese readme to `README.zh-cn.md` (original `README.cn.md`) to reflect the variants of Chinese. ## [10.16.2] - 2021-01-02 From de093e5552cd3909778c52d411786746f2508f5c Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Mon, 24 Jan 2022 21:10:31 +0800 Subject: [PATCH 250/287] Update link in `README.md` --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5365e7d0f..23822026d7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) • [Läs på svenska](https://github.com/willmcgugan/rich/blob/master/README.sv.md) From 4d526ec0ada96ac9505402d919e15f8f10f9d407 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 10:13:43 +0000 Subject: [PATCH 251/287] Add Syntax.guess_lexer method --- rich/syntax.py | 58 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 759351907a..f156961cf9 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -1,9 +1,9 @@ import os.path import platform -from rich.containers import Lines import textwrap from abc import ABC, abstractmethod -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from os import PathLike +from typing import Any, AnyStr, Dict, Iterable, List, Optional, Set, Tuple, Type, Union from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename @@ -23,6 +23,8 @@ ) from pygments.util import ClassNotFound +from rich.containers import Lines + from ._loop import loop_first from .color import Color, blend_rgb from .console import Console, ConsoleOptions, JustifyMethod, RenderResult @@ -200,7 +202,8 @@ class Syntax(JupyterMixin): dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. start_line (int, optional): Starting number for line numbers. Defaults to 1. - line_range (Tuple[int, int], optional): If given should be a tuple of the start and end line to render. + line_range (Tuple[int | None, int | None], optional): If given should be a tuple of the start and end line to render. + A value of None in the tuple indicates the range is open in that direction. highlight_lines (Set[int]): A set of line numbers to highlight. code_width: Width of code to render (not including line numbers), or ``None`` to use all available width. tab_size (int, optional): Size of tabs. Defaults to 4. @@ -233,7 +236,7 @@ def __init__( dedent: bool = False, line_numbers: bool = False, start_line: int = 1, - line_range: Optional[Tuple[int, int]] = None, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, highlight_lines: Optional[Set[int]] = None, code_width: Optional[int] = None, tab_size: int = 4, @@ -299,22 +302,7 @@ def from_path( with open(path, "rt", encoding=encoding) as code_file: code = code_file.read() - lexer = None - lexer_name = "default" - try: - _, ext = os.path.splitext(path) - if ext: - extension = ext.lstrip(".").lower() - lexer = get_lexer_by_name(extension) - lexer_name = lexer.name - except ClassNotFound: - pass - - if lexer is None: - try: - lexer_name = guess_lexer_for_filename(path, code).name - except ClassNotFound: - pass + lexer_name = cls.guess_lexer(path, code=code) return cls( code, @@ -332,6 +320,36 @@ def from_path( indent_guides=indent_guides, ) + @classmethod + def guess_lexer(cls, path: AnyStr, code: Optional[str] = None) -> str: + """Guess the name of the Pygments lexer to use based on path and optional string of code. + Initially looks at file extension and falls back to analysing the code, if supplied. + + Args: + path (AnyStr): The path to the file containing the code you wish to know the lexer for. + code (str, optional): Optional string of code that will be used as a fallback if no lexer + is found for the supplied path. + + Returns: + str: The name of the Pygments lexer that best matches the supplied path/code. + """ + lexer = None + lexer_name = "default" + try: + _, ext = os.path.splitext(path) + if ext: + extension = ext.lstrip(".").lower() + lexer = get_lexer_by_name(extension) + lexer_name = lexer.name + except ClassNotFound: + pass + if code and lexer is None: + try: + lexer_name = guess_lexer_for_filename(path, code).name + except ClassNotFound: + pass + return lexer_name + def _get_base_style(self) -> Style: """Get the base style.""" default_style = self._theme.get_background_style() + self.background_style From 15e72ab4332eef81ed4e834633c700dc13d17cae Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 10:54:49 +0000 Subject: [PATCH 252/287] Tidying up Syntax.guess_lexer, adding test --- rich/syntax.py | 38 +++++++++++++++++++++++++------------- tests/test_syntax.py | 17 ++++++++++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index f156961cf9..9b303685ff 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -322,8 +322,12 @@ def from_path( @classmethod def guess_lexer(cls, path: AnyStr, code: Optional[str] = None) -> str: - """Guess the name of the Pygments lexer to use based on path and optional string of code. - Initially looks at file extension and falls back to analysing the code, if supplied. + """Guess the alias of the Pygments lexer to use based on a path and an optional string of code. + If code is supplied, it will use a combination of the code and the filename to determine the + best lexer to use. For example, if the file is ``index.html`` and the file contains Django + templating syntax, then "html+django" will be returned. If the file is ``index.html``, and no + templating language is used, the "html" lexer will be used. If no string of code + is supplied, the lexer will be chosen based on the file extension.. Args: path (AnyStr): The path to the file containing the code you wish to know the lexer for. @@ -333,21 +337,29 @@ def guess_lexer(cls, path: AnyStr, code: Optional[str] = None) -> str: Returns: str: The name of the Pygments lexer that best matches the supplied path/code. """ - lexer = None + lexer: Optional[Lexer] = None lexer_name = "default" - try: - _, ext = os.path.splitext(path) - if ext: - extension = ext.lstrip(".").lower() - lexer = get_lexer_by_name(extension) - lexer_name = lexer.name - except ClassNotFound: - pass - if code and lexer is None: + if code: try: - lexer_name = guess_lexer_for_filename(path, code).name + lexer: Lexer = guess_lexer_for_filename(path, code) except ClassNotFound: pass + + if not lexer: + try: + _, ext = os.path.splitext(path) + if ext: + extension = ext.lstrip(".").lower() + lexer = get_lexer_by_name(extension) + except ClassNotFound: + pass + + if lexer: + if lexer.aliases: + lexer_name = lexer.aliases[0] + else: + lexer_name = lexer.name + return lexer_name def _get_base_style(self) -> Style: diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 834285ac17..52f26d196b 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -1,17 +1,17 @@ # coding=utf-8 +import os import sys -import os, tempfile +import tempfile import pytest -from .render import render +from pygments.lexers import PythonLexer from rich.panel import Panel from rich.style import Style -from rich.syntax import Syntax, ANSISyntaxTheme, PygmentsSyntaxTheme, Color, Console - -from pygments.lexers import PythonLexer +from rich.syntax import ANSISyntaxTheme, Color, Console, PygmentsSyntaxTheme, Syntax +from .render import render CODE = '''\ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: @@ -266,6 +266,13 @@ def test_from_file_unknown_lexer(): os.remove(path) +def test_syntax_guess_lexer(): + assert Syntax.guess_lexer("banana.py", "import this") == "python" + assert Syntax.guess_lexer("banana.html", "hello") == "html" + assert Syntax.guess_lexer("banana.html", "<%= @foo %>") == "rhtml" + assert Syntax.guess_lexer("banana.html", "{{something|filter:3}}") == "html+django" + + if __name__ == "__main__": syntax = Panel.fit( Syntax( From 49e9fe9bd2020fcbf725019d07002d5d0e381a09 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 10:55:34 +0000 Subject: [PATCH 253/287] Improving Syntax.guess_lexer test --- tests/test_syntax.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 52f26d196b..a8ac05b6b5 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -267,6 +267,7 @@ def test_from_file_unknown_lexer(): def test_syntax_guess_lexer(): + assert Syntax.guess_lexer("banana.py") == "python" assert Syntax.guess_lexer("banana.py", "import this") == "python" assert Syntax.guess_lexer("banana.html", "hello") == "html" assert Syntax.guess_lexer("banana.html", "<%= @foo %>") == "rhtml" From c4df3a772e16f44282e385aa6398f914fc31f159 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 11:02:25 +0000 Subject: [PATCH 254/287] Add PR to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3819a7813..f3e81f7249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 +- Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 ### Added From 781b41f4a780e70196692d7a43881eef0b0b81e0 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 13:07:49 +0000 Subject: [PATCH 255/287] Fix type checking --- rich/syntax.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 9b303685ff..e912daaa10 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -321,7 +321,7 @@ def from_path( ) @classmethod - def guess_lexer(cls, path: AnyStr, code: Optional[str] = None) -> str: + def guess_lexer(cls, path: str, code: Optional[str] = None) -> str: """Guess the alias of the Pygments lexer to use based on a path and an optional string of code. If code is supplied, it will use a combination of the code and the filename to determine the best lexer to use. For example, if the file is ``index.html`` and the file contains Django @@ -341,7 +341,7 @@ def guess_lexer(cls, path: AnyStr, code: Optional[str] = None) -> str: lexer_name = "default" if code: try: - lexer: Lexer = guess_lexer_for_filename(path, code) + lexer = guess_lexer_for_filename(path, code) except ClassNotFound: pass @@ -399,7 +399,9 @@ def lexer(self) -> Optional[Lexer]: return None def highlight( - self, code: str, line_range: Optional[Tuple[int, int]] = None + self, + code: str, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, ) -> Text: """Highlight code and return a Text instance. @@ -447,7 +449,7 @@ def tokens_to_spans() -> Iterable[Tuple[str, Optional[Style]]]: """Convert tokens to spans.""" tokens = iter(line_tokenize()) line_no = 0 - _line_start = line_start - 1 + _line_start = line_start - 1 if line_start else 0 # Skip over tokens until line start while line_no < _line_start: @@ -460,7 +462,7 @@ def tokens_to_spans() -> Iterable[Tuple[str, Optional[Style]]]: yield (token, _get_theme_style(token_type)) if token.endswith("\n"): line_no += 1 - if line_no >= line_end: + if line_end and line_no >= line_end: break text.append_tokens(tokens_to_spans()) @@ -543,11 +545,6 @@ def __rich_console__( else self.code_width ) - line_offset = 0 - if self.line_range: - start_line, end_line = self.line_range - line_offset = max(0, start_line - 1) - ends_on_nl = self.code.endswith("\n") code = self.code if ends_on_nl else self.code + "\n" code = textwrap.dedent(code) if self.dedent else code @@ -589,6 +586,10 @@ def __rich_console__( yield from syntax_line return + start_line, end_line = self.line_range or (None, None) + line_offset = 0 + if start_line: + line_offset = max(0, start_line - 1) lines: Union[List[Text], Lines] = text.split("\n", allow_blank=ends_on_nl) if self.line_range: lines = lines[line_offset:end_line] From 70ebda06ee3d924c5c2d647adc148430127b4075 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Wed, 26 Jan 2022 20:38:13 +0800 Subject: [PATCH 256/287] Revert Simplified Chinese readme to old name --- CHANGELOG.md | 1 - README.zh-cn.md => README.cn.md | 2 +- README.de-ch.md | 2 +- README.de.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.hi.md | 2 +- README.it.md | 2 +- README.ja.md | 2 +- README.kr.md | 2 +- README.md | 2 +- README.pt-br.md | 2 +- README.ru.md | 2 +- README.sv.md | 2 +- README.zh-tw.md | 2 +- 15 files changed, 14 insertions(+), 15 deletions(-) rename README.zh-cn.md => README.cn.md (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8272ba6407..f7dfca3565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **breaking** Deprecated rich.console.RenderGroup, now named rich.console.Group - **breaking** `Syntax.__init__` parameter `lexer_name` renamed to `lexer` - Syntax constructor accepts both str and now a pygments lexer https://github.com/Textualize/rich/pull/1748 -- Rename the file name of Simplified Chinese readme to `README.zh-cn.md` (original `README.cn.md`) to reflect the variants of Chinese. ## [10.16.2] - 2021-01-02 diff --git a/README.zh-cn.md b/README.cn.md similarity index 99% rename from README.zh-cn.md rename to README.cn.md index 97f0996340..a5c7c5b66a 100644 --- a/README.zh-cn.md +++ b/README.cn.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.de-ch.md b/README.de-ch.md index 4d6359ff52..6c1d7d278b 100644 --- a/README.de-ch.md +++ b/README.de-ch.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.de.md b/README.de.md index 148f146f21..34a99a64e8 100644 --- a/README.de.md +++ b/README.de.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.es.md b/README.es.md index ec4e4f4253..c9cb2af141 100644 --- a/README.es.md +++ b/README.es.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.fr.md b/README.fr.md index 0fbea94fc0..1a09c054a1 100644 --- a/README.fr.md +++ b/README.fr.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.hi.md b/README.hi.md index 443472c5c8..c3c62f5321 100644 --- a/README.hi.md +++ b/README.hi.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.it.md b/README.it.md index cf2e2c5fe0..c6e8b5620c 100644 --- a/README.it.md +++ b/README.it.md @@ -6,7 +6,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.ja.md b/README.ja.md index 0429d11509..300f779d31 100644 --- a/README.ja.md +++ b/README.ja.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.kr.md b/README.kr.md index e3aa03134e..b55529af72 100644 --- a/README.kr.md +++ b/README.kr.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.md b/README.md index 23822026d7..f7cf6368fa 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.pt-br.md b/README.pt-br.md index 3d888ee449..55f366cafd 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.ru.md b/README.ru.md index d9a02c21c4..b6ff2d255e 100644 --- a/README.ru.md +++ b/README.ru.md @@ -8,7 +8,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.sv.md b/README.sv.md index b630b3e7f9..b2685a705e 100644 --- a/README.sv.md +++ b/README.sv.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) diff --git a/README.zh-tw.md b/README.zh-tw.md index 29b5e10281..207f3260f7 100644 --- a/README.zh-tw.md +++ b/README.zh-tw.md @@ -7,7 +7,7 @@ ![Logo](https://github.com/willmcgugan/rich/raw/master/imgs/logo.svg) [English readme](https://github.com/willmcgugan/rich/blob/master/README.md) - • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-cn.md) + • [简体中文 readme](https://github.com/willmcgugan/rich/blob/master/README.cn.md) • [正體中文 readme](https://github.com/willmcgugan/rich/blob/master/README.zh-tw.md) • [Lengua española readme](https://github.com/willmcgugan/rich/blob/master/README.es.md) • [Deutsche readme](https://github.com/willmcgugan/rich/blob/master/README.de.md) From 0a37fcc93a025fb19821fa9a05a59aa1d3848a20 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Wed, 26 Jan 2022 16:50:19 +0000 Subject: [PATCH 257/287] Syntax should always justify left --- rich/syntax.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index e912daaa10..380710ba75 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -2,8 +2,7 @@ import platform import textwrap from abc import ABC, abstractmethod -from os import PathLike -from typing import Any, AnyStr, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename @@ -577,7 +576,7 @@ def __rich_console__( else: syntax_lines = console.render_lines( text, - options.update(width=code_width, height=None), + options.update(width=code_width, height=None, justify="left"), style=self.background_style, pad=True, new_lines=True, @@ -622,7 +621,7 @@ def __rich_console__( if self.word_wrap: wrapped_lines = console.render_lines( line, - render_options.update(height=None), + render_options.update(height=None, justify="left"), style=background_style, pad=not transparent_background, ) From 404539dce79baa7481e281a674d96db9340697c8 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 10:13:11 +0000 Subject: [PATCH 258/287] Add PR to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3e81f7249..eb80f1dad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 +- Ensure `Syntax` always justifies left https://github.com/Textualize/rich/pull/1872 ### Added From 9247705bd8cb8da3381c3e30045cb5d739ddce33 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 10:38:55 +0000 Subject: [PATCH 259/287] Allow override of lexer in Syntax.from_path --- rich/syntax.py | 8 ++++++-- tests/test_syntax.py | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index e912daaa10..d3b14bca32 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -267,6 +267,7 @@ def from_path( cls, path: str, encoding: str = "utf-8", + lexer: Optional[Union[Lexer, str]] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -283,6 +284,7 @@ def from_path( Args: path (str): Path to file to highlight. + lexer (str | Lexer, optional): Lexer to use. If None, lexer will be auto-detected from path/file content. encoding (str): Encoding of file. theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "emacs". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to True. @@ -302,11 +304,12 @@ def from_path( with open(path, "rt", encoding=encoding) as code_file: code = code_file.read() - lexer_name = cls.guess_lexer(path, code=code) + if not lexer: + lexer = cls.guess_lexer(path, code=code) return cls( code, - lexer_name, + lexer, theme=theme, dedent=dedent, line_numbers=line_numbers, @@ -757,6 +760,7 @@ def __rich_console__( else: syntax = Syntax.from_path( args.path, + lexer=args.lexer_name, line_numbers=args.line_numbers, word_wrap=args.word_wrap, theme=args.theme, diff --git a/tests/test_syntax.py b/tests/test_syntax.py index a8ac05b6b5..46d0126e14 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -241,8 +241,13 @@ def test_ansi_theme(): assert theme.get_background_style() == Style() -@pytest.mark.skipif(sys.platform == "win32", reason="permissions error on Windows") -def test_from_file(): +skip_windows_permission_error = pytest.mark.skipif( + sys.platform == "win32", reason="permissions error on Windows" +) + + +@skip_windows_permission_error +def test_from_path(): fh, path = tempfile.mkstemp("example.py") try: os.write(fh, b"import this\n") @@ -254,8 +259,8 @@ def test_from_file(): os.remove(path) -@pytest.mark.skipif(sys.platform == "win32", reason="permissions error on Windows") -def test_from_file_unknown_lexer(): +@skip_windows_permission_error +def test_from_path_unknown_lexer(): fh, path = tempfile.mkstemp("example.nosuchtype") try: os.write(fh, b"import this\n") @@ -266,6 +271,30 @@ def test_from_file_unknown_lexer(): os.remove(path) +@skip_windows_permission_error +def test_from_path_lexer_override(): + fh, path = tempfile.mkstemp("example.nosuchtype") + try: + os.write(fh, b"import this\n") + syntax = Syntax.from_path(path, lexer="rust") + assert syntax.lexer.name is "Rust" + assert syntax.code == "import this\n" + finally: + os.remove(path) + + +@skip_windows_permission_error +def test_from_path_lexer_override_invalid_lexer(): + fh, path = tempfile.mkstemp("example.nosuchtype") + try: + os.write(fh, b"import this\n") + syntax = Syntax.from_path(path, lexer="blah") + assert syntax.lexer is None + assert syntax.code == "import this\n" + finally: + os.remove(path) + + def test_syntax_guess_lexer(): assert Syntax.guess_lexer("banana.py") == "python" assert Syntax.guess_lexer("banana.py", "import this") == "python" From 8c41358fb13bf135067d331d231fd244b7b787d9 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 10:40:12 +0000 Subject: [PATCH 260/287] Add Pull Request to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3e81f7249..26469ec5b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 +- Add `lexer` parameter to `Syntax.from_path` to allow for overrides https://github.com/Textualize/rich/pull/1873 ### Added From 308f433f4e04ac1835d7c720c4cb1d749b2adc8b Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 10:42:54 +0000 Subject: [PATCH 261/287] Fix ordering in docstring --- rich/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index d3b14bca32..1be36fd879 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -284,8 +284,8 @@ def from_path( Args: path (str): Path to file to highlight. - lexer (str | Lexer, optional): Lexer to use. If None, lexer will be auto-detected from path/file content. encoding (str): Encoding of file. + lexer (str | Lexer, optional): Lexer to use. If None, lexer will be auto-detected from path/file content. theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "emacs". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to True. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. From f715403f1a0eafb8847414c510af2c694a66e4a5 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 11:53:34 +0000 Subject: [PATCH 262/287] Handle classes in inspect when methods=True --- rich/_inspect.py | 12 +++++++++++- rich/default_styles.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/rich/_inspect.py b/rich/_inspect.py index 07b1b623b8..b3652bfbdb 100644 --- a/rich/_inspect.py +++ b/rich/_inspect.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +import inspect from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature from typing import Any, Iterable, Optional, Tuple @@ -106,8 +107,17 @@ def _get_signature(self, name: str, obj: Any) -> Optional[Text]: signature_text = self.highlighter(_signature) qualname = name or getattr(obj, "__qualname__", name) + + # If obj is a module, there may be classes (which are callable) to display + if inspect.isclass(obj): + prefix = "class" + else: + prefix = "def" + qual_signature = Text.assemble( - ("def ", "inspect.def"), (qualname, "inspect.callable"), signature_text + (f"{prefix} ", f"inspect.{prefix}"), + (qualname, "inspect.callable"), + signature_text, ) return qual_signature diff --git a/rich/default_styles.py b/rich/default_styles.py index 63290bcaba..d803eec91d 100644 --- a/rich/default_styles.py +++ b/rich/default_styles.py @@ -2,7 +2,6 @@ from .style import Style - DEFAULT_STYLES: Dict[str, Style] = { "none": Style.null(), "reset": Style( @@ -41,6 +40,7 @@ "inspect.attr.dunder": Style(color="yellow", italic=True, dim=True), "inspect.callable": Style(bold=True, color="red"), "inspect.def": Style(italic=True, color="bright_cyan"), + "inspect.class": Style(italic=True, color="bright_cyan"), "inspect.error": Style(bold=True, color="red"), "inspect.equals": Style(), "inspect.help": Style(color="cyan"), From 1ea00c3c473e6f187b8a24963bef0682fac81142 Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Thu, 27 Jan 2022 20:13:46 +0800 Subject: [PATCH 263/287] Remove Trad. Chinese texts in `__main__.py` --- rich/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/__main__.py b/rich/__main__.py index 78f3f7b006..5b69ac354d 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -97,7 +97,7 @@ def comparison(renderable1: RenderableType, renderable2: RenderableType) -> Tabl table.add_row( "Asian\nlanguage\nsupport", - ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다\n:flag_for_taiwan: 本函式庫支援中日韓文字元!", + ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다\n", ) markup_example = ( From e9cf4caa5836fa721af8c967eb63289c499af45e Mon Sep 17 00:00:00 2001 From: toto6038 <50100922+toto6038@users.noreply.github.com> Date: Thu, 27 Jan 2022 20:18:26 +0800 Subject: [PATCH 264/287] Remove trailing LF character --- rich/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/__main__.py b/rich/__main__.py index 5b69ac354d..132e809412 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -97,7 +97,7 @@ def comparison(renderable1: RenderableType, renderable2: RenderableType) -> Tabl table.add_row( "Asian\nlanguage\nsupport", - ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다\n", + ":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다", ) markup_example = ( From 8ceeb83fd499a9580daca440a868024b1d2da689 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 12:36:07 +0000 Subject: [PATCH 265/287] Update changelog, add test for inspecting modules containing classes --- CHANGELOG.md | 2 +- tests/test_inspect.py | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb80f1dad9..613fca7a7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 - Ensure `Syntax` always justifies left https://github.com/Textualize/rich/pull/1872 - +- Handle classes in inspect when methods=True https://github.com/Textualize/rich/pull/1874 ### Added diff --git a/tests/test_inspect.py b/tests/test_inspect.py index 05a78b8718..63c5f06244 100644 --- a/tests/test_inspect.py +++ b/tests/test_inspect.py @@ -1,5 +1,6 @@ import io import sys +from types import ModuleType import pytest @@ -81,7 +82,6 @@ def test_render(): def test_inspect_text(): - expected = ( "╭──────────────── ─────────────────╮\n" "│ str(object='') -> str │\n" @@ -99,7 +99,6 @@ def test_inspect_text(): @skip_py36 @skip_py37 def test_inspect_empty_dict(): - expected = ( "╭──────────────── ────────────────╮\n" "│ dict() -> new empty dictionary │\n" @@ -121,7 +120,6 @@ def test_inspect_empty_dict(): def test_inspect_builtin_function(): - expected = ( "╭────────── ───────────╮\n" "│ def print(...) │\n" @@ -138,7 +136,6 @@ def test_inspect_builtin_function(): @skip_py36 def test_inspect_integer(): - expected = ( "╭────── ───────╮\n" "│ int([x]) -> integer │\n" @@ -155,7 +152,6 @@ def test_inspect_integer(): @skip_py36 def test_inspect_integer_with_value(): - expected = "╭────── ───────╮\n│ int([x]) -> integer │\n│ int(x, base=10) -> integer │\n│ │\n│ ╭────────────────────────╮ │\n│ │ 1 │ │\n│ ╰────────────────────────╯ │\n│ │\n│ denominator = 1 │\n│ imag = 0 │\n│ numerator = 1 │\n│ real = 1 │\n╰────────────────────────────╯\n" value = render(1, value=True) print(repr(value)) @@ -166,7 +162,6 @@ def test_inspect_integer_with_value(): @skip_py37 @skip_py310 def test_inspect_integer_with_methods(): - expected = ( "╭──────────────── ─────────────────╮\n" "│ int([x]) -> integer │\n" @@ -204,7 +199,6 @@ def test_inspect_integer_with_methods(): @skip_py38 @skip_py39 def test_inspect_integer_with_methods(): - expected = ( "╭──────────────── ─────────────────╮\n" "│ int([x]) -> integer │\n" @@ -274,3 +268,25 @@ def __class__(self): inspect(thing) except Exception as e: assert False, f"Object with no __class__ shouldn't raise {e}" + + +def test_inspect_module_with_class(): + def function(): + pass + + class Thing: + """Docstring""" + + pass + + module = ModuleType("my_module") + module.SomeClass = Thing + module.function = function + + expected = ( + "╭────────── ──────────╮\n" + "│ function = def function(): │\n" + "│ SomeClass = class SomeClass(): Docstring │\n" + "╰──────────────────────────────────────────╯\n" + ) + assert render(module, methods=True) == expected From 57acc6f4bc58c95f5494e018c6ca7cb1449e2d02 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 27 Jan 2022 16:21:14 +0000 Subject: [PATCH 266/287] Add note about MANPAGER environment variable to docs --- docs/source/console.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/console.rst b/docs/source/console.rst index 965fef7ee6..ed4b6c46f7 100644 --- a/docs/source/console.rst +++ b/docs/source/console.rst @@ -140,7 +140,7 @@ Run the following command to see the available choices for ``spinner``:: Justify / Alignment ------------------- -Both print and log support a ``justify`` argument which if set must be one of "default", "left", "right", "center", or "full". If "left", any text printed (or logged) will be left aligned, if "right" text will be aligned to the right of the terminal, if "center" the text will be centered, and if "full" the text will be lined up with both the left and right edges of the terminal (like printed text in a book). +Both print and log support a ``justify`` argument which if set must be one of "default", "left", "right", "center", or "full". If "left", any text printed (or logged) will be left aligned, if "right" text will be aligned to the right of the terminal, if "center" the text will be centered, and if "full" the text will be lined up with both the left and right edges of the terminal (like printed text in a book). The default for ``justify`` is ``"default"`` which will generally look the same as ``"left"`` but with a subtle difference. Left justify will pad the right of the text with spaces, while a default justify will not. You will only notice the difference if you set a background color with the ``style`` argument. The following example demonstrates the difference:: @@ -161,7 +161,7 @@ This produces the following output:
Rich
     Rich                
-            Rich         
+            Rich        
                     Rich
     
@@ -282,7 +282,7 @@ You can also tell the Console object to write to a file by setting the ``file`` with open("report.txt", "wt") as report_file: console = Console(file=report_file) console.rule(f"Report Generated {datetime.now().ctime()}") - + Note that when writing to a file you may want to explicitly the ``width`` argument if you don't want to wrap the output to the current console width. Capturing output @@ -321,7 +321,7 @@ You can page output from a Console by calling :meth:`~rich.console.Console.pager Since the default pager on most platforms don't support color, Rich will strip color from the output. If you know that your pager supports color, you can set ``styles=True`` when calling the :meth:`~rich.console.Console.pager` method. .. note:: - Rich will use the ``PAGER`` environment variable to get the pager command. On Linux and macOS you can set this to ``less -r`` to enable paging with ANSI styles. + Rich will look at ``MANPAGER`` then the ``PAGER`` environment variables (``MANPAGER`` takes priority) to get the pager command. On Linux and macOS you can set one of these to ``less -r`` to enable paging with ANSI styles. Alternate screen ---------------- @@ -340,10 +340,10 @@ Here's an example of an alternate screen:: with console.screen(): console.print(locals()) sleep(5) - + The above code will display a pretty printed dictionary on the alternate screen before returning to the command prompt after 5 seconds. -You can also provide a renderable to :meth:`~rich.console.Console.screen` which will be displayed in the alternate screen when you call :meth:`~rich.ScreenContext.update`. +You can also provide a renderable to :meth:`~rich.console.Console.screen` which will be displayed in the alternate screen when you call :meth:`~rich.ScreenContext.update`. Here's an example:: From 47e83e16fecbd2daf7df42a2875460d1c1df03ad Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 28 Jan 2022 14:41:06 +0000 Subject: [PATCH 267/287] blurb --- rich/__main__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rich/__main__.py b/rich/__main__.py index 132e809412..ea6ccfd9bd 100644 --- a/rich/__main__.py +++ b/rich/__main__.py @@ -242,6 +242,10 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: sponsor_message.add_column(style="green", justify="right") sponsor_message.add_column(no_wrap=True) + sponsor_message.add_row( + "Textualize", + "[u blue link=https://github.com/textualize]https://github.com/textualize", + ) sponsor_message.add_row( "Buy devs a :coffee:", "[u blue link=https://ko-fi.com/textualize]https://ko-fi.com/textualize", @@ -250,15 +254,12 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: "Twitter", "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan", ) - sponsor_message.add_row( - "Blog", "[u blue link=https://www.willmcgugan.com]https://www.willmcgugan.com" - ) intro_message = Text.from_markup( """\ We hope you enjoy using Rich! -Rich is maintained with :heart: by [link=https://www.textualize.io]Textualize.io[/] +Rich is maintained with [red]:heart:[/] by [link=https://www.textualize.io]Textualize.io[/] - Will McGugan""" ) From 26da2787c0ef775736782c7fa11ff80b7c7124eb Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 28 Jan 2022 14:44:27 +0000 Subject: [PATCH 268/287] sort changelog --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edf3ff4bea..15e9616cab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,21 @@ 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). -## [Unreleased] +## [11.1.0] - 2022-01-28 ### Added -- Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 - Add `lexer` parameter to `Syntax.from_path` to allow for overrides https://github.com/Textualize/rich/pull/1873 + +### Fixed + +- Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Ensure `Syntax` always justifies left https://github.com/Textualize/rich/pull/1872 - Handle classes in inspect when methods=True https://github.com/Textualize/rich/pull/1874 +[11.0.0] - 2022-01-09 + ### Added - Added max_depth arg to pretty printing https://github.com/Textualize/rich/issues/1585 From e5317f638c0c0188415d619fb9f19f5219e8e84d Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 28 Jan 2022 14:44:58 +0000 Subject: [PATCH 269/287] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4a0a6d29fc..e8ea9bf99c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "11.0.0" +version = "11.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" From 3f7d3e4ef372f4ce954c240df723d8cd646b1534 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 28 Jan 2022 14:45:56 +0000 Subject: [PATCH 270/287] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e9616cab..8b49b5c57c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure `Syntax` always justifies left https://github.com/Textualize/rich/pull/1872 - Handle classes in inspect when methods=True https://github.com/Textualize/rich/pull/1874 -[11.0.0] - 2022-01-09 +## [11.0.0] - 2022-01-09 ### Added @@ -1616,6 +1616,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[11.1.0]: https://github.com/willmcgugan/rich/compare/v11.0.0...v11.1.0 [11.0.0]: https://github.com/willmcgugan/rich/compare/v10.16.1...v11.0.0 [10.16.1]: https://github.com/willmcgugan/rich/compare/v10.16.0...v10.16.1 [10.16.0]: https://github.com/willmcgugan/rich/compare/v10.15.2...v10.16.0 From 1e6fb1876b338be091a8a80b3141833ad518a267 Mon Sep 17 00:00:00 2001 From: Yuval Ben Arie Date: Sat, 29 Jan 2022 15:50:09 +0200 Subject: [PATCH 271/287] Table no_wrap documentation fix --- docs/source/tables.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tables.rst b/docs/source/tables.rst index 967a573825..7429ac66ac 100644 --- a/docs/source/tables.rst +++ b/docs/source/tables.rst @@ -139,7 +139,7 @@ There are a number of options you can set on a column to modify how it will look - ``min_width`` When set to an integer will prevent the column from shrinking below this amount. - ``max_width`` When set to an integer will prevent the column from growing beyond this amount. - ``ratio`` Defines a ratio to set the column width. For instance, if there are 3 columns with a total of 6 ratio, and ``ratio=2`` then the column will be a third of the available size. -- ``no_wrap`` Set to False to prevent this column from wrapping. +- ``no_wrap`` Set to True to prevent this column from wrapping. Vertical Alignment ~~~~~~~~~~~~~~~~~~ From b90c33eae76453dc8893bcc9aefd56a725fb9401 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 31 Jan 2022 14:24:33 +0000 Subject: [PATCH 272/287] Fix test in traceback, remove the no-eval pre-commit hook --- .pre-commit-config.yaml | 1 - tests/test_traceback.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 892dc79187..bbae40c844 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,6 @@ repos: rev: v1.9.0 hooks: - id: python-check-mock-methods - - id: python-no-eval - id: python-no-log-warn - id: python-use-type-annotations - id: rst-directive-colons diff --git a/tests/test_traceback.py b/tests/test_traceback.py index e3342ca13c..8bcc8922fa 100644 --- a/tests/test_traceback.py +++ b/tests/test_traceback.py @@ -110,7 +110,7 @@ def test_syntax_error(): console = Console(width=100, file=io.StringIO()) try: # raises SyntaxError: unexpected EOF while parsing - compile("(2+2") + eval("(2+2") except Exception: console.print_exception() exception_text = console.file.getvalue() From b1673d029b08e0463c447a02dcd9847ce838235a Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 31 Jan 2022 14:25:36 +0000 Subject: [PATCH 273/287] Prevent too broad `except` clause in test --- tests/test_traceback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_traceback.py b/tests/test_traceback.py index 8bcc8922fa..31658c5a43 100644 --- a/tests/test_traceback.py +++ b/tests/test_traceback.py @@ -111,7 +111,7 @@ def test_syntax_error(): try: # raises SyntaxError: unexpected EOF while parsing eval("(2+2") - except Exception: + except SyntaxError: console.print_exception() exception_text = console.file.getvalue() assert "SyntaxError" in exception_text From b0794522a6a8f85d9110db2c1768d1c4f48162d9 Mon Sep 17 00:00:00 2001 From: ptmcg Date: Mon, 31 Jan 2022 08:29:01 -0600 Subject: [PATCH 274/287] Add default_columns classmethod to Progress class --- rich/progress.py | 21 +++++++++++---------- tests/test_progress.py | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/rich/progress.py b/rich/progress.py index 1f670db438..8b9713c7a3 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -588,12 +588,7 @@ def __init__( refresh_per_second is None or refresh_per_second > 0 ), "refresh_per_second must be > 0" self._lock = RLock() - self.columns = columns or ( - TextColumn("[progress.description]{task.description}"), - BarColumn(), - TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), - TimeRemainingColumn(), - ) + self.columns = columns or self.default_columns() self.speed_estimate_period = speed_estimate_period self.disable = disable @@ -613,6 +608,15 @@ def __init__( self.print = self.console.print self.log = self.console.log + @classmethod + def default_columns(cls) -> Tuple[ProgressColumn, ...]: + return ( + TextColumn("[progress.description]{task.description}"), + BarColumn(), + TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), + TimeRemainingColumn(), + ) + @property def console(self) -> Console: return self.live.console @@ -1015,10 +1019,7 @@ def remove_task(self, task_id: TaskID) -> None: with Progress( SpinnerColumn(), - TextColumn("[progress.description]{task.description}"), - BarColumn(), - TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), - TimeRemainingColumn(), + *Progress.default_columns(), TimeElapsedColumn(), console=console, transient=True, diff --git a/tests/test_progress.py b/tests/test_progress.py index 2020f91ffb..876e5d99b1 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -334,6 +334,32 @@ def test_columns() -> None: assert result == expected +def test_using_default_columns() -> None: + # can only check types, as the instances do not '==' each other + expected_default_types = [ + TextColumn, + BarColumn, + TextColumn, + TimeRemainingColumn, + ] + + progress = Progress() + assert [type(c) for c in progress.columns] == expected_default_types + + progress = Progress( + SpinnerColumn(), + *Progress.default_columns(), + "Elapsed:", + TimeElapsedColumn(), + ) + assert [type(c) for c in progress.columns] == [ + SpinnerColumn, + *expected_default_types, + str, + TimeElapsedColumn, + ] + + def test_task_create() -> None: task = Task(TaskID(1), "foo", 100, 0, _get_time=lambda: 1) assert task.elapsed is None From ec1ec9d30a4882fc5678672e9dcf6875701a89f3 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 31 Jan 2022 14:35:58 +0000 Subject: [PATCH 275/287] Add US spelling of "gray" to colour names --- rich/color.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/rich/color.py b/rich/color.py index f0fa026d64..b6c56a1ee4 100644 --- a/rich/color.py +++ b/rich/color.py @@ -7,7 +7,7 @@ from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE from .color_triplet import ColorTriplet -from .repr import rich_repr, Result +from .repr import Result, rich_repr from .terminal_theme import DEFAULT_TERMINAL_THEME if TYPE_CHECKING: # pragma: no cover @@ -61,6 +61,7 @@ def __repr__(self) -> str: "bright_cyan": 14, "bright_white": 15, "grey0": 16, + "gray0": 16, "navy_blue": 17, "dark_blue": 18, "blue3": 20, @@ -96,6 +97,7 @@ def __repr__(self) -> str: "blue_violet": 57, "orange4": 94, "grey37": 59, + "gray37": 59, "medium_purple4": 60, "slate_blue3": 62, "royal_blue1": 63, @@ -128,7 +130,9 @@ def __repr__(self) -> str: "yellow4": 106, "wheat4": 101, "grey53": 102, + "gray53": 102, "light_slate_grey": 103, + "light_slate_gray": 103, "medium_purple": 104, "light_slate_blue": 105, "dark_olive_green3": 149, @@ -155,11 +159,13 @@ def __repr__(self) -> str: "light_salmon3": 173, "rosy_brown": 138, "grey63": 139, + "gray63": 139, "medium_purple1": 141, "gold3": 178, "dark_khaki": 143, "navajo_white3": 144, "grey69": 145, + "gray69": 145, "light_steel_blue3": 146, "light_steel_blue": 147, "yellow3": 184, @@ -189,6 +195,7 @@ def __repr__(self) -> str: "light_goldenrod2": 222, "light_yellow3": 187, "grey84": 188, + "gray84": 188, "light_steel_blue1": 189, "yellow2": 190, "dark_olive_green1": 192, @@ -223,30 +230,55 @@ def __repr__(self) -> str: "wheat1": 229, "cornsilk1": 230, "grey100": 231, + "gray100": 231, "grey3": 232, + "gray3": 232, "grey7": 233, + "gray7": 233, "grey11": 234, + "gray11": 234, "grey15": 235, + "gray15": 235, "grey19": 236, + "gray19": 236, "grey23": 237, + "gray23": 237, "grey27": 238, + "gray27": 238, "grey30": 239, + "gray30": 239, "grey35": 240, + "gray35": 240, "grey39": 241, + "gray39": 241, "grey42": 242, + "gray42": 242, "grey46": 243, + "gray46": 243, "grey50": 244, + "gray50": 244, "grey54": 245, + "gray54": 245, "grey58": 246, + "gray58": 246, "grey62": 247, + "gray62": 247, "grey66": 248, + "gray66": 248, "grey70": 249, + "gray70": 249, "grey74": 250, + "gray74": 250, "grey78": 251, + "gray78": 251, "grey82": 252, + "gray82": 252, "grey85": 253, + "gray85": 253, "grey89": 254, + "gray89": 254, "grey93": 255, + "gray93": 255, } @@ -279,8 +311,8 @@ class Color(NamedTuple): def __rich__(self) -> "Text": """Dispays the actual color if Rich printed.""" - from .text import Text from .style import Style + from .text import Text return Text.assemble( f" Date: Mon, 31 Jan 2022 14:38:04 +0000 Subject: [PATCH 276/287] Update CHANGELOG.md r.e. support for US ANSI gray --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b49b5c57c..858101987e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ 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). +## Unreleased + +- Add support for US spelling of "gray" in ANSI color names https://github.com/Textualize/rich/issues/1890 + ## [11.1.0] - 2022-01-28 ### Added From c17cf5ae7476fdacbfe470f0074b0ee8f9f46e47 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 31 Jan 2022 14:49:41 +0000 Subject: [PATCH 277/287] Add `Added` header to `Unreleased` section of changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 858101987e..4997ae3258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + - Add support for US spelling of "gray" in ANSI color names https://github.com/Textualize/rich/issues/1890 ## [11.1.0] - 2022-01-28 From 5c586b67efd358a35f3796712c01686da5c086bb Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Mon, 31 Jan 2022 18:57:47 +0100 Subject: [PATCH 278/287] Typo: THe -> The --- rich/markdown.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/markdown.py b/rich/markdown.py index 92d0d3c010..186e103697 100644 --- a/rich/markdown.py +++ b/rich/markdown.py @@ -25,7 +25,7 @@ def create(cls, markdown: "Markdown", node: Any) -> "MarkdownElement": """Factory to create markdown element, Args: - markdown (Markdown): THe parent Markdown object. + markdown (Markdown): The parent Markdown object. node (Any): A node from Pygments. Returns: @@ -312,7 +312,7 @@ def create(cls, markdown: "Markdown", node: Any) -> "MarkdownElement": """Factory to create markdown element, Args: - markdown (Markdown): THe parent Markdown object. + markdown (Markdown): The parent Markdown object. node (Any): A node from Pygments. Returns: From 76e234b79d8e8ae2c922c6576856bb5c613ce1e0 Mon Sep 17 00:00:00 2001 From: ptmcg Date: Mon, 31 Jan 2022 13:09:51 -0600 Subject: [PATCH 279/287] Rename default_columns to get_default_columns, and add docstring --- rich/progress.py | 28 +++++++++++++++++++++++++--- tests/test_progress.py | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/rich/progress.py b/rich/progress.py index 8b9713c7a3..fe35b6c175 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -588,7 +588,7 @@ def __init__( refresh_per_second is None or refresh_per_second > 0 ), "refresh_per_second must be > 0" self._lock = RLock() - self.columns = columns or self.default_columns() + self.columns = columns or self.get_default_columns() self.speed_estimate_period = speed_estimate_period self.disable = disable @@ -609,7 +609,29 @@ def __init__( self.log = self.console.log @classmethod - def default_columns(cls) -> Tuple[ProgressColumn, ...]: + def get_default_columns(cls) -> Tuple[ProgressColumn, ...]: + """Get the default columns used for a new Progress instance: + - a text column for the description (TextColumn) + - the bar itself (BarColumn) + - a text column showing completion percentage (TextColumn) + - an estimated-time-remaining column (TimeRemainingColumn) + If the Progress instance is created without passing a columns argument, + the default columns defined here will be used. + + You can also create a Progress instance using custom columns before + and/or after the defaults, as in this example: + + progress = Progress( + SpinnerColumn(), + *Progress.default_columns(), + "Elapsed:", + TimeElapsedColumn(), + ) + + This code shows the creation of a Progress display, containing + a spinner to the left, the default columns, and a labeled elapsed + time column. + """ return ( TextColumn("[progress.description]{task.description}"), BarColumn(), @@ -1019,7 +1041,7 @@ def remove_task(self, task_id: TaskID) -> None: with Progress( SpinnerColumn(), - *Progress.default_columns(), + *Progress.get_default_columns(), TimeElapsedColumn(), console=console, transient=True, diff --git a/tests/test_progress.py b/tests/test_progress.py index 876e5d99b1..20b9d32ed4 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -348,7 +348,7 @@ def test_using_default_columns() -> None: progress = Progress( SpinnerColumn(), - *Progress.default_columns(), + *Progress.get_default_columns(), "Elapsed:", TimeElapsedColumn(), ) From 731f9848228e4cffede54ed2056b606b27a35ecb Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Fri, 4 Feb 2022 13:51:58 +0000 Subject: [PATCH 280/287] Expose diagnose.report as a function add a little more info to hint at environment --- .coveragerc | 3 ++- rich/diagnose.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/.coveragerc b/.coveragerc index ff1a046c08..2afac8dc60 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,7 +2,8 @@ omit = rich/jupyter.py rich/_windows.py rich/_timer.py - + rich/diagnose.py + [report] exclude_lines = pragma: no cover diff --git a/rich/diagnose.py b/rich/diagnose.py index 455e11dc02..7ecdff97ff 100644 --- a/rich/diagnose.py +++ b/rich/diagnose.py @@ -1,6 +1,35 @@ -if __name__ == "__main__": # pragma: no cover - from rich.console import Console - from rich import inspect +import os +import platform + +from rich import inspect +from rich.console import Console, get_windows_console_features +from rich.panel import Panel +from rich.text import Text + + +def report(): # pragma: no cover + """Print a report to the terminal with debugging information""" + console = Console() + inspect(console) + features = get_windows_console_features() + inspect(features) + + if console.is_jupyter: + jpy_parent_pid = os.getenv("JPY_PARENT_PID") + vs_code_verbose = os.getenv("VSCODE_VERBOSE_LOGGING") + console.print( + Panel( + title="Jupyter Environment Hints", + renderable=Text( + f"JPY_PARENT_PID = {jpy_parent_pid}\n" + f"VSCODE_VERBOSE_LOGGING = {vs_code_verbose}" + ), + ), + ) + + console.print(f'platform="{platform.system()}"') + +if __name__ == "__main__": # pragma: no cover console = Console() inspect(console) From bdad740de91368814c331ea807f362e5bec73336 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Fri, 4 Feb 2022 14:10:12 +0000 Subject: [PATCH 281/287] Update issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 05cd2cd112..723781db8f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -20,12 +20,21 @@ Provide a minimal code example that demonstrates the issue if you can. If the is What platform (Win/Linux/Mac) are you running on? What terminal software are you using? -I may ask you to cut and paste the output of the following commands. It may save some time if you do it now. +I may ask you to copy and paste the output of the following commands. It may save some time if you do it now. + +If you're using Rich in a terminal: ``` -python -m rich.diagnose -python -m rich._windows +python -c "from rich.diagnose import report; report()" pip freeze | grep rich ``` - + +If you're using Rich in a Jupyter Notebook, run the following snippet in a cell +and paste the output in your bug report. + +```python +from rich.diagnose import report +report() +``` +
From 29bc5dd4905c6bf8ec8d4fd8d789abbdfe5d6b92 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Fri, 4 Feb 2022 14:19:15 +0000 Subject: [PATCH 282/287] Add missing return type annotation to diagnose.report --- rich/diagnose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/diagnose.py b/rich/diagnose.py index 7ecdff97ff..7e8ad989bd 100644 --- a/rich/diagnose.py +++ b/rich/diagnose.py @@ -7,7 +7,7 @@ from rich.text import Text -def report(): # pragma: no cover +def report() -> None: # pragma: no cover """Print a report to the terminal with debugging information""" console = Console() inspect(console) From bcbaed2b95b3f0ce4d5a72a5fc40274158d96bc9 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Fri, 4 Feb 2022 14:23:32 +0000 Subject: [PATCH 283/287] Added `rich.diagnose.report` note to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4997ae3258..0887ed3941 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add support for US spelling of "gray" in ANSI color names https://github.com/Textualize/rich/issues/1890 +- Added `rich.diagnose.report` to expose environment debugging logic as function https://github.com/Textualize/rich/pull/1917 ## [11.1.0] - 2022-01-28 From e1c595c7e5bd00fc7900471ea13f6de2fa8d165d Mon Sep 17 00:00:00 2001 From: ptmcg Date: Sun, 6 Feb 2022 13:53:06 -0600 Subject: [PATCH 284/287] task._progress change default_factory to create deque(maxlen=1000), to avoid run-time while loop to trim to length 1000 --- rich/progress.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rich/progress.py b/rich/progress.py index fe35b6c175..115ae81608 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -475,7 +475,7 @@ class Task: """Optional[float]: The last speed for a finished task.""" _progress: Deque[ProgressSample] = field( - default_factory=deque, init=False, repr=False + default_factory=lambda: deque(maxlen=1000), init=False, repr=False ) _lock: RLock = field(repr=False, default_factory=RLock) @@ -813,8 +813,6 @@ def update( popleft = _progress.popleft while _progress and _progress[0].timestamp < old_sample_time: popleft() - while len(_progress) > 1000: - popleft() if update_completed > 0: _progress.append(ProgressSample(current_time, update_completed)) if task.completed >= task.total and task.finished_time is None: From e4f48cc612e35d2fb6bfe9c8c946a80aa2dad564 Mon Sep 17 00:00:00 2001 From: ptmcg Date: Sun, 6 Feb 2022 14:03:39 -0600 Subject: [PATCH 285/287] Update CONTRIBUTORS.md and CHANGELOG.md with changes related to adding Progress.get_default_columns --- CHANGELOG.md | 1 + CONTRIBUTORS.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ece575abd..154decdc24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add support for US spelling of "gray" in ANSI color names https://github.com/Textualize/rich/issues/1890 +- Added classmethod `Progress.get_default_columns()` to get the default list of progress bar columns https://github.com/Textualize/rich/pull/1894 ## [11.1.0] - 2022-01-28 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c29cd79049..0c0f891fdc 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -16,6 +16,7 @@ The following people have contributed to the development of Rich: - [Hedy Li](https://github.com/hedythedev) - [Alexander Mancevice](https://github.com/amancevice) - [Will McGugan](https://github.com/willmcgugan) +- [Paul McGuire](https://github.com/ptmcg) - [Nathan Page](https://github.com/nathanrpage97) - [Avi Perl](https://github.com/avi-perl) - [Laurent Peuch](https://github.com/psycojoker) From c8c2cf117f3510b1105c3fa5a93a811855f7f0b5 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 7 Feb 2022 10:06:36 +0000 Subject: [PATCH 286/287] Add more diagnose.report env variables, invoke from __main__ --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- rich/diagnose.py | 30 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 723781db8f..6d6f45677f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,7 +25,7 @@ I may ask you to copy and paste the output of the following commands. It may sav If you're using Rich in a terminal: ``` -python -c "from rich.diagnose import report; report()" +python -m rich.diagnose pip freeze | grep rich ``` diff --git a/rich/diagnose.py b/rich/diagnose.py index 7e8ad989bd..09c4e0622b 100644 --- a/rich/diagnose.py +++ b/rich/diagnose.py @@ -4,7 +4,7 @@ from rich import inspect from rich.console import Console, get_windows_console_features from rich.panel import Panel -from rich.text import Text +from rich.pretty import Pretty def report() -> None: # pragma: no cover @@ -14,22 +14,22 @@ def report() -> None: # pragma: no cover features = get_windows_console_features() inspect(features) - if console.is_jupyter: - jpy_parent_pid = os.getenv("JPY_PARENT_PID") - vs_code_verbose = os.getenv("VSCODE_VERBOSE_LOGGING") - console.print( - Panel( - title="Jupyter Environment Hints", - renderable=Text( - f"JPY_PARENT_PID = {jpy_parent_pid}\n" - f"VSCODE_VERBOSE_LOGGING = {vs_code_verbose}" - ), - ), - ) + env_names = ( + "TERM", + "COLORTERM", + "CLICOLOR", + "NO_COLOR", + "TERM_PROGRAM", + "COLUMNS", + "LINES", + "JPY_PARENT_PID", + "VSCODE_VERBOSE_LOGGING", + ) + env = {name: os.getenv(name) for name in env_names} + console.print(Panel.fit((Pretty(env)), title="[b]Environment Variables")) console.print(f'platform="{platform.system()}"') if __name__ == "__main__": # pragma: no cover - console = Console() - inspect(console) + report() From 429c6d38614072d574e22d7aabbe08ff566ab60c Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 8 Feb 2022 20:05:39 +0000 Subject: [PATCH 287/287] optimization for measure --- CHANGELOG.md | 8 ++++++-- pyproject.toml | 2 +- rich/measure.py | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a53bb620..9c1416a5bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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). -## Unreleased +## [11.2.0] - 2022-02-08 ### Added @@ -13,11 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `rich.diagnose.report` to expose environment debugging logic as function https://github.com/Textualize/rich/pull/1917 - Added classmethod `Progress.get_default_columns()` to get the default list of progress bar columns https://github.com/Textualize/rich/pull/1894 +### Fixed + +- Fixed performance issue in measuring text + ## [11.1.0] - 2022-01-28 ### Added - - Workaround for edge case of object from Faiss with no `__class__` https://github.com/Textualize/rich/issues/1838 - Add Traditional Chinese readme - Add `Syntax.guess_lexer`, add support for more lexers (e.g. Django templates etc.) https://github.com/Textualize/rich/pull/1869 @@ -1627,6 +1630,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[11.2.0]: https://github.com/willmcgugan/rich/compare/v11.1.0...v11.2.0 [11.1.0]: https://github.com/willmcgugan/rich/compare/v11.0.0...v11.1.0 [11.0.0]: https://github.com/willmcgugan/rich/compare/v10.16.1...v11.0.0 [10.16.1]: https://github.com/willmcgugan/rich/compare/v10.16.0...v10.16.1 diff --git a/pyproject.toml b/pyproject.toml index e8ea9bf99c..4b221c35b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "11.1.0" +version = "11.2.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/measure.py b/rich/measure.py index aea238df93..e12787c8be 100644 --- a/rich/measure.py +++ b/rich/measure.py @@ -1,5 +1,5 @@ from operator import itemgetter -from typing import Callable, Iterable, NamedTuple, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Callable, Iterable, NamedTuple, Optional from . import errors from .protocol import is_renderable, rich_cast @@ -96,7 +96,9 @@ def get( if _max_width < 1: return Measurement(0, 0) if isinstance(renderable, str): - renderable = console.render_str(renderable, markup=options.markup) + renderable = console.render_str( + renderable, markup=options.markup, highlight=False + ) renderable = rich_cast(renderable) if is_renderable(renderable): get_console_width: Optional[