nbcat 0.12.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nbcat-0.12.0 → nbcat-0.13.0}/PKG-INFO +6 -4
- {nbcat-0.12.0 → nbcat-0.13.0}/README.md +4 -3
- {nbcat-0.12.0 → nbcat-0.13.0}/pyproject.toml +2 -1
- nbcat-0.13.0/src/nbcat/__init__.py +1 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/main.py +50 -27
- nbcat-0.13.0/src/nbcat/pager.py +82 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/test_render_cell.py +1 -21
- {nbcat-0.12.0 → nbcat-0.13.0}/uv.lock +68 -1
- nbcat-0.12.0/src/nbcat/__init__.py +0 -1
- {nbcat-0.12.0 → nbcat-0.13.0}/.github/workflows/ci.yml +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/.github/workflows/homebrew.yml +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/.gitignore +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/LICENSE +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/Makefile +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/docs/screenshot.png +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/enums.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/exceptions.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/image.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/markdown.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/py.typed +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/src/nbcat/schemas.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/invalid.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/many_tracebacks.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/no_min_version.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test3.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test3_no_metadata.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test3_no_min_version.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test3_no_worksheets.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test3_worksheet_with_no_cells.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4.5.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4custom.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4docinfo.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4jupyter_metadata.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/assets/test4jupyter_metadata_timings.ipynb +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/conftest.py +0 -0
- {nbcat-0.12.0 → nbcat-0.13.0}/tests/test_read_notebook.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nbcat
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.13.0
|
4
4
|
Summary: cat for jupyter notebooks
|
5
5
|
Project-URL: Homepage, https://github.com/akopdev/nbcat
|
6
6
|
Project-URL: Repository, https://github.com/akopdev/nbcat
|
@@ -33,6 +33,7 @@ Requires-Dist: argcomplete
|
|
33
33
|
Requires-Dist: pydantic
|
34
34
|
Requires-Dist: requests
|
35
35
|
Requires-Dist: rich
|
36
|
+
Requires-Dist: textual
|
36
37
|
Requires-Dist: timg
|
37
38
|
Provides-Extra: dev
|
38
39
|
Requires-Dist: pytest; extra == 'dev'
|
@@ -52,9 +53,10 @@ Description-Content-Type: text/markdown
|
|
52
53
|
|
53
54
|
## Features
|
54
55
|
|
55
|
-
- Very fast and lightweight with minimal dependencies
|
56
|
-
- Preview remote notebooks without downloading them
|
57
|
-
-
|
56
|
+
- Very fast and lightweight with minimal dependencies.
|
57
|
+
- Preview remote notebooks without downloading them.
|
58
|
+
- Enable paginated view mode with keyboard navigation (similar to `less`).
|
59
|
+
- Supports for all Jupyter notebook versions, including old legacy formats.
|
58
60
|
|
59
61
|
## Motivation
|
60
62
|
|
@@ -8,9 +8,10 @@
|
|
8
8
|
|
9
9
|
## Features
|
10
10
|
|
11
|
-
- Very fast and lightweight with minimal dependencies
|
12
|
-
- Preview remote notebooks without downloading them
|
13
|
-
-
|
11
|
+
- Very fast and lightweight with minimal dependencies.
|
12
|
+
- Preview remote notebooks without downloading them.
|
13
|
+
- Enable paginated view mode with keyboard navigation (similar to `less`).
|
14
|
+
- Supports for all Jupyter notebook versions, including old legacy formats.
|
14
15
|
|
15
16
|
## Motivation
|
16
17
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "nbcat"
|
3
|
-
version = "0.
|
3
|
+
version = "0.13.0"
|
4
4
|
description = "cat for jupyter notebooks"
|
5
5
|
authors = [
|
6
6
|
{ name = "Akop Kesheshyan", email = "devnull@akop.dev" }
|
@@ -17,6 +17,7 @@ dependencies = [
|
|
17
17
|
"pydantic",
|
18
18
|
"rich",
|
19
19
|
"timg",
|
20
|
+
"textual"
|
20
21
|
]
|
21
22
|
|
22
23
|
[project.optional-dependencies]
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.13.0"
|
@@ -6,7 +6,6 @@ import argcomplete
|
|
6
6
|
import requests
|
7
7
|
from argcomplete.completers import FilesCompleter
|
8
8
|
from pydantic import ValidationError
|
9
|
-
from rich import box
|
10
9
|
from rich.console import Console, Group, RenderableType
|
11
10
|
from rich.padding import Padding
|
12
11
|
from rich.panel import Panel
|
@@ -23,6 +22,7 @@ from .exceptions import (
|
|
23
22
|
)
|
24
23
|
from .image import Image
|
25
24
|
from .markdown import Markdown
|
25
|
+
from .pager import Pager
|
26
26
|
from .schemas import Cell, Notebook
|
27
27
|
|
28
28
|
console = Console()
|
@@ -87,10 +87,8 @@ def render_cell(cell: Cell) -> RenderableType:
|
|
87
87
|
def _render_markdown(input: str) -> Markdown:
|
88
88
|
return Markdown(input, code_theme="ansi_dark")
|
89
89
|
|
90
|
-
def _render_code(input: str, language: str = "python") ->
|
91
|
-
return
|
92
|
-
Syntax(input, language, line_numbers=True, theme="ansi_dark", dedent=True), padding=0
|
93
|
-
)
|
90
|
+
def _render_code(input: str, language: str = "python") -> Syntax:
|
91
|
+
return Syntax(input, language, theme="ansi_dark", padding=(1, 2), dedent=True)
|
94
92
|
|
95
93
|
def _render_raw(input: str) -> Text:
|
96
94
|
return Text(input)
|
@@ -116,41 +114,48 @@ def render_cell(cell: Cell) -> RenderableType:
|
|
116
114
|
renderer = RENDERERS.get(cell.cell_type)
|
117
115
|
source = renderer(cell.input) if renderer else None
|
118
116
|
if source:
|
119
|
-
|
117
|
+
s_title = f"[green]In [{cell.execution_count}][/]" if cell.execution_count else None
|
118
|
+
if s_title:
|
119
|
+
rows.append(Panel(source, title=s_title, title_align="left"))
|
120
|
+
else:
|
121
|
+
rows.append(Padding(source, (1, 0)))
|
122
|
+
|
120
123
|
if not cell.outputs:
|
121
|
-
return
|
124
|
+
return rows.pop()
|
122
125
|
|
123
126
|
for o in cell.outputs:
|
127
|
+
o_title = f"[blue]Out [{o.execution_count}][/]" if o.execution_count else None
|
124
128
|
if o.output:
|
125
129
|
renderer = RENDERERS.get(o.output.output_type)
|
126
130
|
output = renderer(o.output.text) if renderer else None
|
127
131
|
if output:
|
128
|
-
|
132
|
+
if o_title:
|
133
|
+
rows.append(Panel(output, style="italic", title=o_title, title_align="left"))
|
134
|
+
else:
|
135
|
+
rows.append(Padding(output, (1, 0), style="italic"))
|
129
136
|
return Group(*rows)
|
130
137
|
|
131
138
|
|
132
|
-
def
|
139
|
+
def render_notebook(nb: Notebook) -> list[RenderableType]:
|
133
140
|
"""
|
134
|
-
|
141
|
+
Convert a Notebook object into a list of rich renderables for terminal display.
|
142
|
+
|
143
|
+
Each cell in the notebook is processed and rendered using `render_cell`,
|
144
|
+
producing a sequence of styled input/output blocks suitable for use in a
|
145
|
+
Textual or Rich-based terminal UI.
|
135
146
|
|
136
147
|
Args:
|
137
|
-
nb (Notebook):
|
138
|
-
"""
|
139
|
-
if not nb.cells:
|
140
|
-
console.print("[bold red]Notebook contains no cells.")
|
141
|
-
return
|
148
|
+
nb (Notebook): The notebook object containing parsed cells (e.g., from a .ipynb file).
|
142
149
|
|
150
|
+
Returns
|
151
|
+
-------
|
152
|
+
list[RenderableType]: A list of rich renderable objects representing the notebook cells.
|
153
|
+
Returns an empty list if the notebook has no cells.
|
154
|
+
"""
|
155
|
+
rendered: list[RenderableType] = []
|
143
156
|
for cell in nb.cells:
|
144
|
-
rendered
|
145
|
-
|
146
|
-
out = Panel(
|
147
|
-
rendered,
|
148
|
-
title=f"[green][{cell.execution_count}][/]" if cell.execution_count else None,
|
149
|
-
title_align="left",
|
150
|
-
)
|
151
|
-
else:
|
152
|
-
out = Padding(rendered, (1, 0))
|
153
|
-
console.print(out)
|
157
|
+
rendered.append(render_cell(cell))
|
158
|
+
return rendered
|
154
159
|
|
155
160
|
|
156
161
|
def main():
|
@@ -162,20 +167,38 @@ def main():
|
|
162
167
|
"file", help="Path or URL to a .ipynb notebook", type=str
|
163
168
|
).completer = FilesCompleter()
|
164
169
|
parser.add_argument(
|
170
|
+
"-v",
|
165
171
|
"--version",
|
166
172
|
help="print version information and quite",
|
167
173
|
action="version",
|
168
174
|
version=__version__,
|
169
175
|
)
|
170
176
|
parser.add_argument(
|
171
|
-
"--debug", help="enable extended error output", action="store_true", default=False
|
177
|
+
"-d", "--debug", help="enable extended error output", action="store_true", default=False
|
178
|
+
)
|
179
|
+
parser.add_argument(
|
180
|
+
"-p",
|
181
|
+
"--page",
|
182
|
+
help="enable paginated view mode (similar to less)",
|
183
|
+
action="store_true",
|
184
|
+
default=False,
|
172
185
|
)
|
173
186
|
|
174
187
|
try:
|
175
188
|
argcomplete.autocomplete(parser)
|
176
189
|
args = parser.parse_args()
|
190
|
+
|
177
191
|
notebook = read_notebook(args.file, debug=args.debug)
|
178
|
-
|
192
|
+
objects = render_notebook(notebook)
|
193
|
+
|
194
|
+
if not objects:
|
195
|
+
console.print("[bold red]Notebook contains no cells.")
|
196
|
+
return
|
197
|
+
|
198
|
+
if args.page:
|
199
|
+
Pager(objects).run()
|
200
|
+
else:
|
201
|
+
console.print(*objects)
|
179
202
|
except Exception as e:
|
180
203
|
sys.exit(f"nbcat: {e}")
|
181
204
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
from rich.console import RenderableType
|
2
|
+
from textual.app import App, ComposeResult
|
3
|
+
from textual.binding import Binding
|
4
|
+
from textual.containers import VerticalScroll
|
5
|
+
from textual.widgets import Static
|
6
|
+
|
7
|
+
|
8
|
+
class Pager(App):
|
9
|
+
BINDINGS = [
|
10
|
+
# Exit
|
11
|
+
Binding("q", "quit", "Quit"),
|
12
|
+
Binding(":q", "quit", "Quit"),
|
13
|
+
Binding("Q", "quit", "Quit"),
|
14
|
+
Binding(":Q", "quit", "Quit"),
|
15
|
+
Binding("ZZ", "quit", "Quit"),
|
16
|
+
# One line
|
17
|
+
Binding("j", "scroll_down", "Down"),
|
18
|
+
Binding("e", "scroll_down", "Down"),
|
19
|
+
Binding("^e", "scroll_down", "Down"),
|
20
|
+
Binding("^n", "scroll_down", "Down"),
|
21
|
+
Binding("cr", "scroll_down", "Down"), # carriage return = Enter
|
22
|
+
Binding("k", "scroll_up", "Up"),
|
23
|
+
Binding("y", "scroll_up", "Up"),
|
24
|
+
Binding("ctrl+y", "scroll_up", "Up"),
|
25
|
+
Binding("ctrl+k", "scroll_up", "Up"),
|
26
|
+
Binding("ctrl+p", "scroll_up", "Up"),
|
27
|
+
# One window
|
28
|
+
Binding("f", "page_down", "Page Down"),
|
29
|
+
Binding("ctrl+f", "page_down", "Page Down"),
|
30
|
+
Binding("ctrl+v", "page_down", "Page Down"),
|
31
|
+
Binding("space", "page_down", "Page Down"),
|
32
|
+
Binding("b", "page_up", "Page Up"),
|
33
|
+
Binding("ctrl+b", "page_up", "Page Up"),
|
34
|
+
Binding("escape+v", "page_up", "Page Up"),
|
35
|
+
# Extended window control
|
36
|
+
Binding("z", "page_down", "Window Down (set N)"),
|
37
|
+
Binding("w", "page_up", "Window Up (set N)"),
|
38
|
+
Binding("escape+space", "page_down", "Forward one window, no EOF stop"),
|
39
|
+
Binding("d", "half_page_down", "Half Page Down"),
|
40
|
+
Binding("ctrl+d", "half_page_down", "Half Page Down"),
|
41
|
+
# Jumping
|
42
|
+
Binding("g", "go_to_top", "Top of File"),
|
43
|
+
Binding("<", "go_to_top", "Top of File"),
|
44
|
+
Binding("escape+<", "go_to_top", "Top of File"),
|
45
|
+
Binding("G", "go_to_bottom", "Bottom of File"),
|
46
|
+
Binding(">", "go_to_bottom", "Bottom of File"),
|
47
|
+
Binding("escape+>", "go_to_bottom", "Bottom of File"),
|
48
|
+
]
|
49
|
+
|
50
|
+
def __init__(self, objects: list[RenderableType]):
|
51
|
+
super().__init__()
|
52
|
+
self._objects = objects
|
53
|
+
|
54
|
+
def compose(self) -> ComposeResult:
|
55
|
+
with VerticalScroll():
|
56
|
+
for obj in self._objects:
|
57
|
+
yield Static(obj)
|
58
|
+
|
59
|
+
def on_mount(self) -> None:
|
60
|
+
self.theme = "textual-ansi"
|
61
|
+
self.viewer = self.query_one(VerticalScroll)
|
62
|
+
|
63
|
+
def action_scroll_down(self) -> None:
|
64
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + 1)
|
65
|
+
|
66
|
+
def action_scroll_up(self) -> None:
|
67
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y - 1)
|
68
|
+
|
69
|
+
def action_page_down(self) -> None:
|
70
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + self.viewer.virtual_size.height)
|
71
|
+
|
72
|
+
def action_page_up(self) -> None:
|
73
|
+
self.viewer.scroll_to(y=max(self.viewer.scroll_y - self.viewer.virtual_size.height, 0))
|
74
|
+
|
75
|
+
def action_half_page_down(self) -> None:
|
76
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + (self.viewer.virtual_size.height / 2))
|
77
|
+
|
78
|
+
def action_go_to_top(self) -> None:
|
79
|
+
self.viewer.scroll_to(y=0)
|
80
|
+
|
81
|
+
def action_go_to_bottom(self) -> None:
|
82
|
+
self.viewer.scroll_to(y=self.viewer.virtual_size.height)
|
@@ -1,29 +1,9 @@
|
|
1
|
-
import
|
2
|
-
from rich.console import Group, RenderableType
|
3
|
-
from rich.markdown import Markdown
|
4
|
-
from rich.panel import Panel
|
5
|
-
from rich.text import Text
|
1
|
+
from rich.console import Group
|
6
2
|
|
7
3
|
from nbcat.main import render_cell
|
8
4
|
from nbcat.schemas import Cell, StreamOutput
|
9
5
|
|
10
6
|
|
11
|
-
@pytest.mark.parametrize(
|
12
|
-
"cell_type,source,expected",
|
13
|
-
[
|
14
|
-
("markdown", "# Heading", Markdown),
|
15
|
-
("code", "print('Hello')", Panel),
|
16
|
-
("raw", "Raw content", Text),
|
17
|
-
("heading", "Heading text", Markdown),
|
18
|
-
],
|
19
|
-
)
|
20
|
-
def test_render_cell_input_rendering(cell_type: str, source: str, expected: RenderableType):
|
21
|
-
cell = Cell(cell_type=cell_type, source=source, execution_count=42, outputs=[])
|
22
|
-
rendered = render_cell(cell)
|
23
|
-
|
24
|
-
assert isinstance(rendered, expected)
|
25
|
-
|
26
|
-
|
27
7
|
def test_render_cell_with_outputs():
|
28
8
|
output_1 = StreamOutput(text=["First output"], execution_count=7, output_type="stream")
|
29
9
|
output_2 = StreamOutput(text=["Second output"], output_type="stream")
|
@@ -214,6 +214,18 @@ wheels = [
|
|
214
214
|
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 },
|
215
215
|
]
|
216
216
|
|
217
|
+
[[package]]
|
218
|
+
name = "linkify-it-py"
|
219
|
+
version = "2.0.3"
|
220
|
+
source = { registry = "https://pypi.org/simple" }
|
221
|
+
dependencies = [
|
222
|
+
{ name = "uc-micro-py" },
|
223
|
+
]
|
224
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2a/ae/bb56c6828e4797ba5a4821eec7c43b8bf40f69cda4d4f5f8c8a2810ec96a/linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048", size = 27946 }
|
225
|
+
wheels = [
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/04/1e/b832de447dee8b582cac175871d2f6c3d5077cc56d5575cadba1fd1cccfa/linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79", size = 19820 },
|
227
|
+
]
|
228
|
+
|
217
229
|
[[package]]
|
218
230
|
name = "markdown-it-py"
|
219
231
|
version = "3.0.0"
|
@@ -226,6 +238,26 @@ wheels = [
|
|
226
238
|
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
227
239
|
]
|
228
240
|
|
241
|
+
[package.optional-dependencies]
|
242
|
+
linkify = [
|
243
|
+
{ name = "linkify-it-py" },
|
244
|
+
]
|
245
|
+
plugins = [
|
246
|
+
{ name = "mdit-py-plugins" },
|
247
|
+
]
|
248
|
+
|
249
|
+
[[package]]
|
250
|
+
name = "mdit-py-plugins"
|
251
|
+
version = "0.4.2"
|
252
|
+
source = { registry = "https://pypi.org/simple" }
|
253
|
+
dependencies = [
|
254
|
+
{ name = "markdown-it-py" },
|
255
|
+
]
|
256
|
+
sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 }
|
257
|
+
wheels = [
|
258
|
+
{ url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316 },
|
259
|
+
]
|
260
|
+
|
229
261
|
[[package]]
|
230
262
|
name = "mdurl"
|
231
263
|
version = "0.1.2"
|
@@ -237,13 +269,14 @@ wheels = [
|
|
237
269
|
|
238
270
|
[[package]]
|
239
271
|
name = "nbcat"
|
240
|
-
version = "0.
|
272
|
+
version = "0.13.0"
|
241
273
|
source = { editable = "." }
|
242
274
|
dependencies = [
|
243
275
|
{ name = "argcomplete" },
|
244
276
|
{ name = "pydantic" },
|
245
277
|
{ name = "requests" },
|
246
278
|
{ name = "rich" },
|
279
|
+
{ name = "textual" },
|
247
280
|
{ name = "timg" },
|
248
281
|
]
|
249
282
|
|
@@ -267,6 +300,7 @@ requires-dist = [
|
|
267
300
|
{ name = "requests" },
|
268
301
|
{ name = "rich" },
|
269
302
|
{ name = "ruff", marker = "extra == 'dev'" },
|
303
|
+
{ name = "textual" },
|
270
304
|
{ name = "timg" },
|
271
305
|
]
|
272
306
|
provides-extras = ["dev"]
|
@@ -368,6 +402,15 @@ wheels = [
|
|
368
402
|
{ url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751 },
|
369
403
|
]
|
370
404
|
|
405
|
+
[[package]]
|
406
|
+
name = "platformdirs"
|
407
|
+
version = "4.3.8"
|
408
|
+
source = { registry = "https://pypi.org/simple" }
|
409
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362 }
|
410
|
+
wheels = [
|
411
|
+
{ url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567 },
|
412
|
+
]
|
413
|
+
|
371
414
|
[[package]]
|
372
415
|
name = "pluggy"
|
373
416
|
version = "1.5.0"
|
@@ -685,6 +728,21 @@ wheels = [
|
|
685
728
|
{ url = "https://files.pythonhosted.org/packages/68/ca/69d7c7752bce162d1516e5592b1cc6b6668e9328c0d270609ddbeeadd7cf/ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177", size = 10677936 },
|
686
729
|
]
|
687
730
|
|
731
|
+
[[package]]
|
732
|
+
name = "textual"
|
733
|
+
version = "3.2.0"
|
734
|
+
source = { registry = "https://pypi.org/simple" }
|
735
|
+
dependencies = [
|
736
|
+
{ name = "markdown-it-py", extra = ["linkify", "plugins"] },
|
737
|
+
{ name = "platformdirs" },
|
738
|
+
{ name = "rich" },
|
739
|
+
{ name = "typing-extensions" },
|
740
|
+
]
|
741
|
+
sdist = { url = "https://files.pythonhosted.org/packages/34/99/8408761a1a1076b2bb69d4859ec110d74be7515552407ac1cb6b68630eb6/textual-3.2.0.tar.gz", hash = "sha256:d2f3b0c39e02535bb5f2aec1c45e10bd3ee7508ed1e240b7505c3cf02a6f00ed", size = 1607281 }
|
742
|
+
wheels = [
|
743
|
+
{ url = "https://files.pythonhosted.org/packages/10/d0/5869999e03ec4ad3a80f36298eb018556faaae0d3309dc305ecd93450b06/textual-3.2.0-py3-none-any.whl", hash = "sha256:c857c6d8dfc9aa915e09df99d227cbe1da3a7ea500b45af9f6b3ecb810c00d77", size = 685595 },
|
744
|
+
]
|
745
|
+
|
688
746
|
[[package]]
|
689
747
|
name = "timg"
|
690
748
|
version = "1.1.6"
|
@@ -757,6 +815,15 @@ wheels = [
|
|
757
815
|
{ url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 },
|
758
816
|
]
|
759
817
|
|
818
|
+
[[package]]
|
819
|
+
name = "uc-micro-py"
|
820
|
+
version = "1.0.3"
|
821
|
+
source = { registry = "https://pypi.org/simple" }
|
822
|
+
sdist = { url = "https://files.pythonhosted.org/packages/91/7a/146a99696aee0609e3712f2b44c6274566bc368dfe8375191278045186b8/uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a", size = 6043 }
|
823
|
+
wheels = [
|
824
|
+
{ url = "https://files.pythonhosted.org/packages/37/87/1f677586e8ac487e29672e4b17455758fce261de06a0d086167bb760361a/uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5", size = 6229 },
|
825
|
+
]
|
826
|
+
|
760
827
|
[[package]]
|
761
828
|
name = "urllib3"
|
762
829
|
version = "2.4.0"
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.12.0"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|