notebookx-py 0.1.4__cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.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.
notebookx/__init__.py ADDED
@@ -0,0 +1,45 @@
1
+ """notebookx - Fast, lightweight notebook conversion library.
2
+
3
+ This library provides a unified representation for Jupyter notebooks
4
+ and supports conversion between different notebook formats.
5
+
6
+ Example:
7
+ >>> from notebookx import Notebook, Format
8
+ >>>
9
+ >>> # Load a notebook
10
+ >>> nb = Notebook.from_file("example.ipynb")
11
+ >>>
12
+ >>> # Convert to percent format
13
+ >>> nb.to_file("example.pct.py")
14
+ >>>
15
+ >>> # Clean a notebook
16
+ >>> clean_nb = nb.clean(remove_outputs=True)
17
+ """
18
+
19
+ from notebookx._notebookx import (
20
+ Notebook,
21
+ Format,
22
+ CleanOptions,
23
+ convert,
24
+ clean_notebook,
25
+ run_cli,
26
+ NotebookError,
27
+ format_from_extension,
28
+ format_from_path,
29
+ format_extension,
30
+ )
31
+
32
+ __all__ = [
33
+ "Notebook",
34
+ "Format",
35
+ "CleanOptions",
36
+ "convert",
37
+ "clean_notebook",
38
+ "run_cli",
39
+ "NotebookError",
40
+ "format_from_extension",
41
+ "format_from_path",
42
+ "format_extension",
43
+ ]
44
+
45
+ __version__ = "0.1.0"
notebookx/__init__.pyi ADDED
@@ -0,0 +1,293 @@
1
+ """Type stubs for notebookx."""
2
+
3
+ from enum import Enum
4
+ from typing import Optional, List
5
+
6
+ class Format(Enum):
7
+ """Supported notebook formats."""
8
+ Ipynb = ...
9
+ Percent = ...
10
+
11
+
12
+ def format_from_extension(ext: str) -> Optional[Format]:
13
+ """Infer the format from a file extension.
14
+
15
+ Args:
16
+ ext: File extension (e.g., "ipynb", "pct.py"). Leading dot is optional.
17
+
18
+ Returns:
19
+ The inferred format, or None if the extension is not recognized.
20
+
21
+ Example:
22
+ >>> format_from_extension("ipynb")
23
+ Format.Ipynb
24
+ >>> format_from_extension(".pct.py")
25
+ Format.Percent
26
+ """
27
+ ...
28
+
29
+
30
+ def format_from_path(path: str) -> Optional[Format]:
31
+ """Infer the format from a file path.
32
+
33
+ Handles compound extensions like `.pct.py`.
34
+
35
+ Args:
36
+ path: Path to a notebook file.
37
+
38
+ Returns:
39
+ The inferred format, or None if the format cannot be determined.
40
+
41
+ Example:
42
+ >>> format_from_path("notebook.ipynb")
43
+ Format.Ipynb
44
+ >>> format_from_path("/path/to/file.pct.py")
45
+ Format.Percent
46
+ """
47
+ ...
48
+
49
+
50
+ def format_extension(format: Format) -> str:
51
+ """Get the canonical file extension for a format.
52
+
53
+ Args:
54
+ format: The notebook format.
55
+
56
+ Returns:
57
+ The file extension (e.g., "ipynb", "pct.py").
58
+
59
+ Example:
60
+ >>> format_extension(Format.Ipynb)
61
+ 'ipynb'
62
+ >>> format_extension(Format.Percent)
63
+ 'pct.py'
64
+ """
65
+ ...
66
+
67
+ class CleanOptions:
68
+ """Options for cleaning a notebook."""
69
+
70
+ remove_outputs: bool
71
+ remove_execution_counts: bool
72
+ remove_cell_metadata: bool
73
+ remove_notebook_metadata: bool
74
+ remove_kernel_info: bool
75
+ preserve_cell_ids: bool
76
+ remove_output_metadata: bool
77
+ remove_output_execution_counts: bool
78
+ allowed_cell_metadata_keys: Optional[List[str]]
79
+ allowed_notebook_metadata_keys: Optional[List[str]]
80
+
81
+ def __init__(
82
+ self,
83
+ remove_outputs: bool = False,
84
+ remove_execution_counts: bool = False,
85
+ remove_cell_metadata: bool = False,
86
+ remove_notebook_metadata: bool = False,
87
+ remove_kernel_info: bool = False,
88
+ preserve_cell_ids: bool = False,
89
+ remove_output_metadata: bool = False,
90
+ remove_output_execution_counts: bool = False,
91
+ allowed_cell_metadata_keys: Optional[List[str]] = None,
92
+ allowed_notebook_metadata_keys: Optional[List[str]] = None,
93
+ ) -> None: ...
94
+
95
+ @staticmethod
96
+ def for_vcs() -> CleanOptions:
97
+ """Create options for version control (removes cell metadata, execution counts, and output metadata/execution counts)."""
98
+ ...
99
+
100
+ @staticmethod
101
+ def strip_all() -> CleanOptions:
102
+ """Create options that strip all metadata and outputs."""
103
+ ...
104
+
105
+ class Notebook:
106
+ """A Jupyter notebook."""
107
+
108
+ @property
109
+ def code_cell_count(self) -> int:
110
+ """Get the number of code cells."""
111
+ ...
112
+
113
+ @property
114
+ def markdown_cell_count(self) -> int:
115
+ """Get the number of markdown cells."""
116
+ ...
117
+
118
+ @property
119
+ def raw_cell_count(self) -> int:
120
+ """Get the number of raw cells."""
121
+ ...
122
+
123
+ @property
124
+ def nbformat(self) -> int:
125
+ """Get the nbformat version."""
126
+ ...
127
+
128
+ @property
129
+ def nbformat_minor(self) -> int:
130
+ """Get the nbformat minor version."""
131
+ ...
132
+
133
+ def __init__(self) -> None:
134
+ """Create a new empty notebook."""
135
+ ...
136
+
137
+ @staticmethod
138
+ def from_file(path: str, format: Optional[Format] = None) -> Notebook:
139
+ """Load a notebook from a file.
140
+
141
+ Args:
142
+ path: Path to the notebook file.
143
+ format: Optional format. If not specified, inferred from extension.
144
+
145
+ Returns:
146
+ The loaded notebook.
147
+
148
+ Raises:
149
+ ValueError: If the file cannot be parsed.
150
+ IOError: If the file cannot be read.
151
+ """
152
+ ...
153
+
154
+ @staticmethod
155
+ def from_string(content: str, format: Format) -> Notebook:
156
+ """Load a notebook from a string.
157
+
158
+ Args:
159
+ content: The notebook content as a string.
160
+ format: The format of the content.
161
+
162
+ Returns:
163
+ The loaded notebook.
164
+
165
+ Raises:
166
+ ValueError: If the content cannot be parsed.
167
+ """
168
+ ...
169
+
170
+ def to_file(self, path: str, format: Optional[Format] = None) -> None:
171
+ """Save the notebook to a file.
172
+
173
+ Args:
174
+ path: Path to save the notebook to.
175
+ format: Optional format. If not specified, inferred from extension.
176
+
177
+ Raises:
178
+ ValueError: If the notebook cannot be serialized.
179
+ IOError: If the file cannot be written.
180
+ """
181
+ ...
182
+
183
+ def to_string(self, format: Format) -> str:
184
+ """Serialize the notebook to a string.
185
+
186
+ Args:
187
+ format: The format to serialize to.
188
+
189
+ Returns:
190
+ The notebook as a string.
191
+
192
+ Raises:
193
+ ValueError: If the notebook cannot be serialized.
194
+ """
195
+ ...
196
+
197
+ def clean(self, options: Optional[CleanOptions] = None) -> Notebook:
198
+ """Clean the notebook according to the specified options.
199
+
200
+ This returns a new notebook with the requested content removed.
201
+ The original notebook is not modified.
202
+
203
+ Args:
204
+ options: Cleaning options. If not specified, uses default options.
205
+
206
+ Returns:
207
+ A new cleaned notebook.
208
+ """
209
+ ...
210
+
211
+ def is_empty(self) -> bool:
212
+ """Check if the notebook is empty."""
213
+ ...
214
+
215
+ def __len__(self) -> int:
216
+ """Get the number of cells in the notebook."""
217
+ ...
218
+
219
+ def __repr__(self) -> str: ...
220
+
221
+ class NotebookError(Exception):
222
+ """Custom exception for notebook errors."""
223
+ ...
224
+
225
+ def convert(
226
+ input_path: str,
227
+ output_path: str,
228
+ from_fmt: Optional[Format] = None,
229
+ to_fmt: Optional[Format] = None,
230
+ ) -> None:
231
+ """Convert a notebook between formats.
232
+
233
+ Args:
234
+ input_path: Path to the input notebook.
235
+ output_path: Path to save the converted notebook.
236
+ from_fmt: Optional input format. If not specified, inferred from extension.
237
+ to_fmt: Optional output format. If not specified, inferred from extension.
238
+
239
+ Raises:
240
+ ValueError: If formats cannot be inferred or conversion fails.
241
+ IOError: If files cannot be read or written.
242
+ """
243
+ ...
244
+
245
+ def clean_notebook(
246
+ input_path: str,
247
+ output_path: Optional[str] = None,
248
+ remove_outputs: bool = False,
249
+ remove_execution_counts: bool = False,
250
+ remove_cell_metadata: bool = False,
251
+ remove_notebook_metadata: bool = False,
252
+ remove_kernel_info: bool = False,
253
+ preserve_cell_ids: bool = False,
254
+ remove_output_metadata: bool = False,
255
+ remove_output_execution_counts: bool = False,
256
+ ) -> None:
257
+ """Clean a notebook file.
258
+
259
+ Args:
260
+ input_path: Path to the input notebook.
261
+ output_path: Optional path to save the cleaned notebook.
262
+ If not specified, cleans in place.
263
+ remove_outputs: Remove all outputs from code cells.
264
+ remove_execution_counts: Remove execution counts from code cells.
265
+ remove_cell_metadata: Remove cell-level metadata.
266
+ remove_notebook_metadata: Remove notebook-level metadata.
267
+ remove_kernel_info: Remove kernel specification.
268
+ preserve_cell_ids: Preserve cell IDs.
269
+ remove_output_metadata: Remove metadata from outputs (ExecuteResult, DisplayData).
270
+ remove_output_execution_counts: Remove execution counts from output results.
271
+
272
+ Raises:
273
+ ValueError: If the file cannot be parsed.
274
+ IOError: If files cannot be read or written.
275
+ """
276
+ ...
277
+
278
+ def run_cli(args: List[str]) -> int:
279
+ """Run the nbx CLI with the given arguments.
280
+
281
+ This function runs the Rust CLI directly, providing the same functionality
282
+ as the standalone `nbx` binary.
283
+
284
+ Args:
285
+ args: Command-line arguments (including the program name as first element).
286
+
287
+ Returns:
288
+ Exit code (0 for success, non-zero for errors).
289
+ """
290
+ ...
291
+
292
+ __version__: str
293
+ __all__: List[str]
Binary file
notebookx/cli.py ADDED
@@ -0,0 +1,18 @@
1
+ """Command-line interface for notebookx.
2
+
3
+ This module provides the `nbx` command when notebookx is installed via pip.
4
+ It's a thin wrapper that calls the Rust CLI implementation directly.
5
+ """
6
+
7
+ import sys
8
+
9
+ from notebookx._notebookx import run_cli
10
+
11
+
12
+ def cli_main():
13
+ """Entry point that runs the Rust CLI and exits with its return code."""
14
+ sys.exit(run_cli(sys.argv))
15
+
16
+
17
+ if __name__ == "__main__":
18
+ cli_main()
notebookx/py.typed ADDED
File without changes
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: notebookx-py
3
+ Version: 0.1.4
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.8
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Rust
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Requires-Dist: pytest>=7.0 ; extra == 'dev'
16
+ Requires-Dist: mypy>=1.0 ; extra == 'dev'
17
+ Provides-Extra: dev
18
+ License-File: LICENSE
19
+ Summary: Fast, lightweight notebook conversion library
20
+ Keywords: jupyter,notebook,conversion,ipynb
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
23
+ Project-URL: Homepage, https://github.com/lukastk/notebookx
24
+ Project-URL: Repository, https://github.com/lukastk/notebookx
25
+
26
+ # notebookx
27
+
28
+ A fast, lightweight notebook conversion library written in Rust with Python bindings.
29
+
30
+ notebookx is a Rust-based alternative to Python's nbconvert, providing fast notebook conversion between formats like `.ipynb` and percent format (`.pct.py`).
31
+
32
+ ## Features
33
+
34
+ - **Fast**: Written in Rust for maximum performance
35
+ - **Multiple interfaces**: Use as a Rust library, CLI tool (`nbx`), or Python package
36
+ - **Format conversion**: Convert between ipynb and percent format
37
+ - **Notebook cleaning**: Strip outputs, execution counts, and metadata for version control
38
+ - **Cross-platform**: Works on Linux, macOS, and Windows
39
+
40
+ ## Installation
41
+
42
+ ### Python
43
+
44
+ ```bash
45
+ pip install notebookx-py
46
+ ```
47
+
48
+ ### Rust
49
+
50
+ Add to your `Cargo.toml`:
51
+
52
+ ```toml
53
+ [dependencies]
54
+ notebookx = "0.1"
55
+ ```
56
+
57
+ ### CLI
58
+
59
+ ```bash
60
+ cargo install notebookx --features cli
61
+ ```
62
+
63
+ ## Usage
64
+
65
+ ### Python
66
+
67
+ ```python
68
+ from notebookx import Notebook, Format, CleanOptions
69
+
70
+ # Load a notebook
71
+ nb = Notebook.from_file("example.ipynb")
72
+
73
+ # Convert to percent format
74
+ nb.to_file("example.pct.py")
75
+
76
+ # Or get as string
77
+ percent_content = nb.to_string(Format.Percent)
78
+
79
+ # Clean notebook for version control
80
+ clean_nb = nb.clean(CleanOptions(
81
+ remove_outputs=True,
82
+ remove_execution_counts=True,
83
+ ))
84
+ clean_nb.to_file("clean.ipynb")
85
+
86
+ # Convenience functions
87
+ from notebookx import convert, clean_notebook
88
+
89
+ convert("input.ipynb", "output.pct.py")
90
+ clean_notebook("notebook.ipynb", remove_outputs=True)
91
+ ```
92
+
93
+ ### CLI (`nbx`)
94
+
95
+ ```bash
96
+ # Convert ipynb to percent format
97
+ nbx convert notebook.ipynb --to notebook.pct.py
98
+
99
+ # Convert percent to ipynb
100
+ nbx convert notebook.pct.py --to notebook.ipynb
101
+
102
+ # Clean a notebook (remove outputs)
103
+ nbx clean notebook.ipynb --output clean.ipynb --remove-outputs
104
+
105
+ # Clean in place
106
+ nbx clean notebook.ipynb --in-place --remove-outputs --remove-execution-counts
107
+
108
+ # Use stdin/stdout
109
+ cat notebook.ipynb | nbx convert - --from-fmt ipynb --to - --to-fmt percent
110
+ ```
111
+
112
+ ### Rust
113
+
114
+ ```rust
115
+ use notebookx::{Notebook, NotebookFormat, CleanOptions};
116
+
117
+ // Parse from file
118
+ let content = std::fs::read_to_string("example.ipynb")?;
119
+ let notebook = NotebookFormat::Ipynb.parse(&content)?;
120
+
121
+ // Convert to percent format
122
+ let percent = NotebookFormat::Percent.serialize(&notebook)?;
123
+
124
+ // Clean notebook
125
+ let options = CleanOptions {
126
+ remove_outputs: true,
127
+ remove_execution_counts: true,
128
+ ..Default::default()
129
+ };
130
+ let clean = notebook.clean(&options);
131
+
132
+ // Save to file
133
+ let output = NotebookFormat::Ipynb.serialize(&clean)?;
134
+ std::fs::write("clean.ipynb", output)?;
135
+ ```
136
+
137
+ ## Supported Formats
138
+
139
+ | Format | Extension | Description |
140
+ |--------|-----------|-------------|
141
+ | ipynb | `.ipynb` | Standard Jupyter notebook format (JSON) |
142
+ | percent | `.pct.py` | Percent format used by Jupytext, VSCode, etc. |
143
+
144
+ ## Clean Options
145
+
146
+ When cleaning notebooks, you can control what gets removed:
147
+
148
+ | Option | Description |
149
+ |--------|-------------|
150
+ | `remove_outputs` | Remove all cell outputs |
151
+ | `remove_execution_counts` | Reset execution counts to null |
152
+ | `remove_cell_metadata` | Remove cell-level metadata |
153
+ | `remove_notebook_metadata` | Remove notebook-level metadata |
154
+ | `remove_kernel_info` | Remove kernel specification |
155
+ | `preserve_cell_ids` | Keep cell IDs (default: regenerate) |
156
+ | `remove_output_metadata` | Remove metadata from outputs |
157
+ | `remove_output_execution_counts` | Remove execution counts from outputs |
158
+
159
+ ### Presets
160
+
161
+ **Python:**
162
+ ```python
163
+ # For version control (removes cell metadata, execution counts, and output metadata)
164
+ # Preserves outputs so rendered content remains visible
165
+ options = CleanOptions.for_vcs()
166
+
167
+ # Strip everything (including outputs)
168
+ options = CleanOptions.strip_all()
169
+ ```
170
+
171
+ ## CLI Reference
172
+
173
+ ### `nbx convert`
174
+
175
+ Convert notebooks between formats.
176
+
177
+ ```
178
+ nbx convert <INPUT> --to <OUTPUT> [OPTIONS]
179
+
180
+ Options:
181
+ --from-fmt <FORMAT> Input format (ipynb, percent). Inferred from extension if not specified.
182
+ --to-fmt <FORMAT> Output format (ipynb, percent). Inferred from extension if not specified.
183
+ -h, --help Print help
184
+ ```
185
+
186
+ ### `nbx clean`
187
+
188
+ Clean notebooks by removing outputs and metadata.
189
+
190
+ ```
191
+ nbx clean <INPUT> [OPTIONS]
192
+
193
+ Options:
194
+ -o, --output <FILE> Output file (default: stdout)
195
+ -i, --in-place Modify file in place
196
+ -O, --remove-outputs Remove all outputs
197
+ -e, --remove-execution-counts Remove execution counts
198
+ --remove-cell-metadata Remove cell metadata
199
+ --remove-notebook-metadata Remove notebook metadata
200
+ --remove-kernel-info Remove kernel specification
201
+ -h, --help Print help
202
+ ```
203
+
204
+ ## Development
205
+
206
+ ### Building from source
207
+
208
+ ```bash
209
+ # Clone the repository
210
+ git clone https://github.com/lukastk/notebookx.git
211
+ cd notebookx
212
+
213
+ # Build Rust library and CLI
214
+ cargo build --release
215
+
216
+ # Build Python package
217
+ pip install maturin
218
+ maturin develop
219
+ ```
220
+
221
+ ### Running tests
222
+
223
+ ```bash
224
+ # Rust tests
225
+ cargo test --workspace
226
+
227
+ # Python tests
228
+ pytest tests/python
229
+ ```
230
+
231
+ ## License
232
+
233
+ MIT
234
+
235
+ ## Acknowledgements
236
+
237
+ Example notebooks in `nb_format_examples/` are from the [Jupytext demo](https://github.com/mwouts/jupytext/tree/main/demo).
238
+
@@ -0,0 +1,10 @@
1
+ notebookx/__init__.py,sha256=kK7_P9a02_SBXfaYDWEE5DYqhPgMA6A_YJrSdrtOTGk,957
2
+ notebookx/__init__.pyi,sha256=WXRgS5OX-tr0UpdnJmdgcFrBmo317363GULeEcSAqVQ,8113
3
+ notebookx/_notebookx.abi3.so,sha256=0WgbiXL_YRdOQAXDat3s-k0fJdsRA6Tq0Vo_T9cyz7Y,1923944
4
+ notebookx/cli.py,sha256=k8gV4XZb_P7y0eUFNJ5RYT6lH43p8yo2Luo4Mj-rBCU,416
5
+ notebookx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ notebookx_py-0.1.4.dist-info/METADATA,sha256=jjnN-xwxh90d9KGVf0uvoIhxOW0inSlWdKwqmxxtCO4,6115
7
+ notebookx_py-0.1.4.dist-info/WHEEL,sha256=fqFHtOCr25M-h-Mnj-0-ZSwuoI9vJMsUUAJdvV4MPAM,145
8
+ notebookx_py-0.1.4.dist-info/entry_points.txt,sha256=a8b4xNM2VIhf_DwwW3BzuxQKjdh7auuXAbJM0R7xdHk,45
9
+ notebookx_py-0.1.4.dist-info/licenses/LICENSE,sha256=HMBDSL1PculP-vHW-UyR_8pG7x63usGRPXThVLs2b-k,1078
10
+ notebookx_py-0.1.4.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp38-abi3-manylinux_2_17_aarch64
5
+ Tag: cp38-abi3-manylinux2014_aarch64
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ nbx=notebookx.cli:cli_main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Lukas Takaaki Kikuchi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.