nbcat 0.9.5__py3-none-any.whl → 0.10.0__py3-none-any.whl
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/__init__.py +1 -1
- nbcat/image.py +28 -0
- nbcat/main.py +3 -2
- nbcat/markdown.py +51 -0
- nbcat/schemas.py +1 -1
- {nbcat-0.9.5.dist-info → nbcat-0.10.0.dist-info}/METADATA +8 -3
- nbcat-0.10.0.dist-info/RECORD +13 -0
- nbcat-0.9.5.dist-info/RECORD +0 -11
- {nbcat-0.9.5.dist-info → nbcat-0.10.0.dist-info}/WHEEL +0 -0
- {nbcat-0.9.5.dist-info → nbcat-0.10.0.dist-info}/entry_points.txt +0 -0
- {nbcat-0.9.5.dist-info → nbcat-0.10.0.dist-info}/licenses/LICENSE +0 -0
nbcat/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.10.0"
|
nbcat/image.py
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
import base64
|
2
|
+
import shutil
|
3
|
+
from io import BytesIO
|
4
|
+
from platform import system
|
5
|
+
|
6
|
+
from PIL import Image as PilImage
|
7
|
+
from rich.console import Console, ConsoleOptions, RenderResult
|
8
|
+
from rich.text import Text
|
9
|
+
from timg import METHODS, Renderer
|
10
|
+
|
11
|
+
|
12
|
+
class Image:
|
13
|
+
def __init__(self, image: str):
|
14
|
+
img = BytesIO(base64.b64decode(image.replace("\n", "")))
|
15
|
+
self.image = PilImage.open(img)
|
16
|
+
|
17
|
+
@property
|
18
|
+
def method_class(self):
|
19
|
+
# TODO: auto detect terminal to benefit from sixel protocol support
|
20
|
+
method = "a24h" if system() != "Windows" else "ascii"
|
21
|
+
return METHODS[method]["class"]
|
22
|
+
|
23
|
+
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
|
24
|
+
img = Renderer()
|
25
|
+
img.load_image(self.image)
|
26
|
+
img.resize(shutil.get_terminal_size()[0] - 1)
|
27
|
+
output = img.to_string(self.method_class)
|
28
|
+
yield Text.from_ansi(output)
|
nbcat/main.py
CHANGED
@@ -9,7 +9,6 @@ from argcomplete.completers import FilesCompleter
|
|
9
9
|
from pydantic import ValidationError
|
10
10
|
from rich import box
|
11
11
|
from rich.console import Console, RenderableType
|
12
|
-
from rich.markdown import Markdown
|
13
12
|
from rich.panel import Panel
|
14
13
|
from rich.pretty import Pretty
|
15
14
|
from rich.syntax import Syntax
|
@@ -23,6 +22,8 @@ from .exceptions import (
|
|
23
22
|
NotebookNotFoundError,
|
24
23
|
UnsupportedNotebookTypeError,
|
25
24
|
)
|
25
|
+
from .image import Image
|
26
|
+
from .markdown import Markdown
|
26
27
|
from .schemas import Cell, Notebook
|
27
28
|
|
28
29
|
console = Console()
|
@@ -94,7 +95,7 @@ def render_cell(cell: Cell) -> list[tuple[Union[str, None], RenderableType]]:
|
|
94
95
|
return Text(input)
|
95
96
|
|
96
97
|
def _render_image(input: str) -> None:
|
97
|
-
return
|
98
|
+
return Image(input)
|
98
99
|
|
99
100
|
def _render_json(input: str) -> Pretty:
|
100
101
|
return Pretty(input)
|
nbcat/markdown.py
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# In an ideal world, this code shouldn't exist. However, for reasons unknown to me,
|
2
|
+
# `rich` decided to format markdown headers in a way that makes them unusable
|
3
|
+
# in the terminal: they are centered and wrapped in a Panel, which causes them to
|
4
|
+
# blend in with the rest of the content. It takes me time to understand what I'm
|
5
|
+
# looking at.
|
6
|
+
#
|
7
|
+
# Instead, I override the default implementation by adding colors and preserving
|
8
|
+
# the original formatting, so that the headers remain recognizable even on
|
9
|
+
# black-and-white screens.
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from typing import ClassVar
|
14
|
+
|
15
|
+
from rich import markdown as md
|
16
|
+
from rich.console import Console, ConsoleOptions, RenderResult
|
17
|
+
from rich.text import Text
|
18
|
+
|
19
|
+
|
20
|
+
class Heading(md.Heading):
|
21
|
+
"""A heading."""
|
22
|
+
|
23
|
+
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
|
24
|
+
styles = {
|
25
|
+
"h1": "bold cyan",
|
26
|
+
"h2": "bold magenta",
|
27
|
+
"h3": "bold yellow",
|
28
|
+
}
|
29
|
+
indent = int(self.tag.strip("h"))
|
30
|
+
yield Text(f"{'#' * indent} {self.text}", style=styles.get(self.tag, "dim white"))
|
31
|
+
|
32
|
+
|
33
|
+
class Markdown(md.Markdown):
|
34
|
+
elements: ClassVar[dict[str, type[md.MarkdownElement]]] = {
|
35
|
+
"paragraph_open": md.Paragraph,
|
36
|
+
"heading_open": Heading,
|
37
|
+
"fence": md.CodeBlock,
|
38
|
+
"code_block": md.CodeBlock,
|
39
|
+
"blockquote_open": md.BlockQuote,
|
40
|
+
"hr": md.HorizontalRule,
|
41
|
+
"bullet_list_open": md.ListElement,
|
42
|
+
"ordered_list_open": md.ListElement,
|
43
|
+
"list_item_open": md.ListItem,
|
44
|
+
"image": md.ImageItem,
|
45
|
+
"table_open": md.TableElement,
|
46
|
+
"tbody_open": md.TableBodyElement,
|
47
|
+
"thead_open": md.TableHeaderElement,
|
48
|
+
"tr_open": md.TableRowElement,
|
49
|
+
"td_open": md.TableDataElement,
|
50
|
+
"th_open": md.TableDataElement,
|
51
|
+
}
|
nbcat/schemas.py
CHANGED
@@ -34,7 +34,7 @@ class DisplayDataOutput(BaseOutput):
|
|
34
34
|
def output(self) -> Union[CellOutput, None]:
|
35
35
|
data_type_map = {
|
36
36
|
"text/html": OutputCellType.HTML,
|
37
|
-
"
|
37
|
+
"image/png": OutputCellType.IMAGE,
|
38
38
|
"text/plain": OutputCellType.PLAIN,
|
39
39
|
"application/vnd.raw.v1+json": OutputCellType.JSON,
|
40
40
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nbcat
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.10.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: timg
|
36
37
|
Provides-Extra: dev
|
37
38
|
Requires-Dist: pytest; extra == 'dev'
|
38
39
|
Requires-Dist: pytest-cov; extra == 'dev'
|
@@ -41,10 +42,14 @@ Requires-Dist: pytest-responses; extra == 'dev'
|
|
41
42
|
Requires-Dist: ruff; extra == 'dev'
|
42
43
|
Description-Content-Type: text/markdown
|
43
44
|
|
44
|
-
#
|
45
|
+
# nbcat
|
45
46
|
|
46
47
|
`nbcat` let you preview Jupyter notebooks directly in your terminal. Think of it as `cat`, but for `.ipynb` files.
|
47
48
|
|
49
|
+
<p align="center">
|
50
|
+
<a href="docs/screenshot.png" target="blank"><img src="docs/screenshot.png" width="400" /></a>
|
51
|
+
</p>
|
52
|
+
|
48
53
|
## Features
|
49
54
|
|
50
55
|
- Very fast and lightweight with minimal dependencies
|
@@ -87,7 +92,7 @@ Example use case with `fzf` command that lists all `.ipynb` files and uses `nbca
|
|
87
92
|
find . -type f -name "*.ipynb" | fzf --preview 'nbcat {}'
|
88
93
|
```
|
89
94
|
|
90
|
-
##
|
95
|
+
## Testing & Development
|
91
96
|
|
92
97
|
Run the tests:
|
93
98
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
nbcat/__init__.py,sha256=v4zmKjsKOPZbp6BrWoz7iK4ST0sdZdUh9bQSJmluZ5o,23
|
2
|
+
nbcat/enums.py,sha256=Fn8PIcLl_uY4nQIs1EUvmKTwfhNUIZgmhRFiCSJk9wk,411
|
3
|
+
nbcat/exceptions.py,sha256=Ho7LQz9K70VtIMDNtAwuAtGmb-lFKxGxSj7MN3-EpDA,321
|
4
|
+
nbcat/image.py,sha256=xv_IH2JMyzelUvLjVUbubfc8blmRuxqa-FcKXn25LSk,909
|
5
|
+
nbcat/main.py,sha256=89qxlA6viuRP6_ugbf7zRE4clH4oX67-1t1EbpABUfA,5838
|
6
|
+
nbcat/markdown.py,sha256=K6yL9rY3uTxMPsRIJnxqNHmCX2Qc-f3my8eiHxTLfic,1835
|
7
|
+
nbcat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
nbcat/schemas.py,sha256=a7GoKgPTHgun199-J-sZq-ahkdQwvyRaCdQVg1gC798,3135
|
9
|
+
nbcat-0.10.0.dist-info/METADATA,sha256=jAKupKwXwBtwqMmTT96IE1LihLl3GUhrfLBd0dfTAxw,4103
|
10
|
+
nbcat-0.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
+
nbcat-0.10.0.dist-info/entry_points.txt,sha256=io_GRDsecAkYuCZALsjyea3VBq91VCoSznqlZEAJshY,42
|
12
|
+
nbcat-0.10.0.dist-info/licenses/LICENSE,sha256=7GjUnahXdd5opdvlpJdb1BisLbiXt2iOFhzIUduhdkE,1072
|
13
|
+
nbcat-0.10.0.dist-info/RECORD,,
|
nbcat-0.9.5.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
nbcat/__init__.py,sha256=ORAtCCI2THBDcdzIbh6oBsoshDvkkmXUWpmO4Q5McAk,22
|
2
|
-
nbcat/enums.py,sha256=Fn8PIcLl_uY4nQIs1EUvmKTwfhNUIZgmhRFiCSJk9wk,411
|
3
|
-
nbcat/exceptions.py,sha256=Ho7LQz9K70VtIMDNtAwuAtGmb-lFKxGxSj7MN3-EpDA,321
|
4
|
-
nbcat/main.py,sha256=H2gQgJYzf00DLOVp8v6yKbcKW3ZL3O9jb65VZEM7IZ0,5809
|
5
|
-
nbcat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
nbcat/schemas.py,sha256=fjSbdXa4pHKRV1Z-vUESkYZywkojanCvSu8s7rc9Xkw,3134
|
7
|
-
nbcat-0.9.5.dist-info/METADATA,sha256=6X7lT_xc9vkN1HI6pCbxE9cIK7dqeIB6NJQ1ATuLJlU,3970
|
8
|
-
nbcat-0.9.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
nbcat-0.9.5.dist-info/entry_points.txt,sha256=io_GRDsecAkYuCZALsjyea3VBq91VCoSznqlZEAJshY,42
|
10
|
-
nbcat-0.9.5.dist-info/licenses/LICENSE,sha256=7GjUnahXdd5opdvlpJdb1BisLbiXt2iOFhzIUduhdkE,1072
|
11
|
-
nbcat-0.9.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|