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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.5"
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 None
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
- "text/png": OutputCellType.IMAGE,
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.9.5
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
- # 📦 nbcat
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
- ## 🧪 Testing & Development
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,,
@@ -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