jupyter-nbmodel-client 0.1.1__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.
@@ -0,0 +1,18 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "monthly"
7
+ groups:
8
+ actions:
9
+ patterns:
10
+ - "*"
11
+ - package-ecosystem: "pip"
12
+ directory: "/"
13
+ schedule:
14
+ interval: "monthly"
15
+ groups:
16
+ pip:
17
+ patterns:
18
+ - "*"
@@ -0,0 +1,104 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+
8
+ defaults:
9
+ run:
10
+ shell: bash -eux {0}
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest, windows-latest]
19
+ python-version: ["3.9", "3.13"]
20
+
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Base Setup
26
+ uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
27
+
28
+ - name: Install the extension
29
+ run: |
30
+ python -m pip install ".[test]"
31
+
32
+ - name: Test the extension
33
+ run: |
34
+ pytest .
35
+
36
+ - name: Build the extension
37
+ run: |
38
+ pip install build
39
+ python -m build --sdist
40
+ cp dist/*.tar.gz my_server_extension.tar.gz
41
+ pip uninstall -y "jupyter_kernel_client"
42
+ rm -rf "jupyter_kernel_client"
43
+
44
+ - uses: actions/upload-artifact@v4
45
+ with:
46
+ name: my_server_extension-sdist
47
+ path: my_server_extension.tar.gz
48
+
49
+ check_links:
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
54
+ - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1
55
+
56
+ test_lint:
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+ - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
61
+ - name: Run Linters
62
+ run: |
63
+ bash ./.github/workflows/lint.sh
64
+
65
+ test_sdist:
66
+ needs: build
67
+ runs-on: ubuntu-latest
68
+
69
+ steps:
70
+ - name: Checkout
71
+ uses: actions/checkout@v4
72
+ - name: Install Python
73
+ uses: actions/setup-python@v5
74
+ with:
75
+ python-version: "3.12"
76
+ architecture: "x64"
77
+ - uses: actions/download-artifact@v4
78
+ with:
79
+ name: my_server_extension-sdist
80
+ - name: Install and Test
81
+ run: |
82
+ pip install my_server_extension.tar.gz
83
+ pip list 2>&1 | grep -ie "jupyter_kernel_client"
84
+ python -c "import jupyter_kernel_client"
85
+
86
+ check_release:
87
+ needs: test_sdist
88
+ runs-on: ubuntu-latest
89
+ steps:
90
+ - uses: actions/checkout@v4
91
+ - name: Base Setup
92
+ uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
93
+ - name: Install Dependencies
94
+ run: |
95
+ pip install -e .
96
+ - name: Check Release
97
+ uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2
98
+ with:
99
+ token: ${{ secrets.GITHUB_TOKEN }}
100
+ - name: Upload Distributions
101
+ uses: actions/upload-artifact@v4
102
+ with:
103
+ name: jupyter_kernel_client-releaser-dist-${{ github.run_number }}
104
+ path: .jupyter_releaser_checkout/dist
@@ -0,0 +1,62 @@
1
+ name: Fix License Headers
2
+
3
+ on:
4
+ pull_request_target:
5
+
6
+ concurrency:
7
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
8
+ cancel-in-progress: true
9
+
10
+ jobs:
11
+ header-license-fix:
12
+ runs-on: ubuntu-latest
13
+
14
+ permissions:
15
+ contents: write
16
+ pull-requests: write
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ with:
22
+ token: ${{ secrets.GITHUB_TOKEN }}
23
+
24
+ - name: Checkout the branch from the PR that triggered the job
25
+ run: gh pr checkout ${{ github.event.pull_request.number }}
26
+ env:
27
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28
+
29
+ - name: Fix License Header
30
+ # pin to include https://github.com/apache/skywalking-eyes/pull/168
31
+ uses: apache/skywalking-eyes/header@e19b828cea6a6027cceae78f05d81317347d21be
32
+ with:
33
+ mode: fix
34
+
35
+ - name: List files changed
36
+ id: files-changed
37
+ shell: bash -l {0}
38
+ run: |
39
+ set -ex
40
+ export CHANGES=$(git status --porcelain | tee /tmp/modified.log | wc -l)
41
+ cat /tmp/modified.log
42
+
43
+ echo "N_CHANGES=${CHANGES}" >> $GITHUB_OUTPUT
44
+
45
+ git diff
46
+
47
+ - name: Commit any changes
48
+ if: steps.files-changed.outputs.N_CHANGES != '0'
49
+ shell: bash -l {0}
50
+ run: |
51
+ git config user.name "github-actions[bot]"
52
+ git config user.email "github-actions[bot]@users.noreply.github.com"
53
+
54
+ git pull --no-tags
55
+
56
+ git add *
57
+ git commit -m "Automatic application of license header"
58
+
59
+ git config push.default upstream
60
+ git push
61
+ env:
62
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ pip install -e ".[lint, typing]"
3
+ mypy --install-types --non-interactive .
4
+ ruff check .
5
+ mdformat --check *.md
6
+ pipx run 'validate-pyproject[all]' pyproject.toml
@@ -0,0 +1,48 @@
1
+ name: "Step 1: Prep Release"
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ version_spec:
6
+ description: "New Version Specifier"
7
+ default: "next"
8
+ required: false
9
+ branch:
10
+ description: "The branch to target"
11
+ required: false
12
+ post_version_spec:
13
+ description: "Post Version Specifier"
14
+ required: false
15
+ # silent:
16
+ # description: "Set a placeholder in the changelog and don't publish the release."
17
+ # required: false
18
+ # type: boolean
19
+ since:
20
+ description: "Use PRs with activity since this date or git reference"
21
+ required: false
22
+ since_last_stable:
23
+ description: "Use PRs with activity since the last stable git tag"
24
+ required: false
25
+ type: boolean
26
+ jobs:
27
+ prep_release:
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ contents: write
31
+ steps:
32
+ - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
33
+
34
+ - name: Prep Release
35
+ id: prep-release
36
+ uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
37
+ with:
38
+ token: ${{ secrets.GITHUB_TOKEN }}
39
+ version_spec: ${{ github.event.inputs.version_spec }}
40
+ # silent: ${{ github.event.inputs.silent }}
41
+ post_version_spec: ${{ github.event.inputs.post_version_spec }}
42
+ branch: ${{ github.event.inputs.branch }}
43
+ since: ${{ github.event.inputs.since }}
44
+ since_last_stable: ${{ github.event.inputs.since_last_stable }}
45
+
46
+ - name: "** Next Step **"
47
+ run: |
48
+ echo "Optional): Review Draft Release: ${{ steps.prep-release.outputs.release_url }}"
@@ -0,0 +1,58 @@
1
+ name: "Step 2: Publish Release"
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ branch:
6
+ description: "The target branch"
7
+ required: false
8
+ release_url:
9
+ description: "The URL of the draft GitHub release"
10
+ required: false
11
+ steps_to_skip:
12
+ description: "Comma separated list of steps to skip"
13
+ required: false
14
+
15
+ jobs:
16
+ publish_release:
17
+ runs-on: ubuntu-latest
18
+ environment: release
19
+ permissions:
20
+ id-token: write
21
+ steps:
22
+ - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
23
+
24
+ - uses: actions/create-github-app-token@v1
25
+ id: app-token
26
+ with:
27
+ app-id: ${{ vars.APP_ID }}
28
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
29
+
30
+ - name: Populate Release
31
+ id: populate-release
32
+ uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
33
+ with:
34
+ token: ${{ steps.app-token.outputs.token }}
35
+ branch: ${{ github.event.inputs.branch }}
36
+ release_url: ${{ github.event.inputs.release_url }}
37
+ steps_to_skip: ${{ github.event.inputs.steps_to_skip }}
38
+
39
+ - name: Finalize Release
40
+ id: finalize-release
41
+ env:
42
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
43
+ uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
44
+ with:
45
+ token: ${{ steps.app-token.outputs.token }}
46
+ release_url: ${{ steps.populate-release.outputs.release_url }}
47
+
48
+ - name: "** Next Step **"
49
+ if: ${{ success() }}
50
+ run: |
51
+ echo "Verify the final release"
52
+ echo ${{ steps.finalize-release.outputs.release_url }}
53
+
54
+ - name: "** Failure Message **"
55
+ if: ${{ failure() }}
56
+ run: |
57
+ echo "Failed to Publish the Draft Release Url:"
58
+ echo ${{ steps.populate-release.outputs.release_url }}
@@ -0,0 +1,106 @@
1
+ *.egg-info/
2
+ .ipynb_checkpoints
3
+
4
+ # Created by https://www.gitignore.io/api/python
5
+ # Edit at https://www.gitignore.io/?templates=python
6
+
7
+ ### Python ###
8
+ # Byte-compiled / optimized / DLL files
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+
13
+ # C extensions
14
+ *.so
15
+
16
+ # Distribution / packaging
17
+ .Python
18
+ build/
19
+ dist/
20
+ downloads/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ pip-wheel-metadata/
28
+ share/python-wheels/
29
+ .installed.cfg
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Scrapy stuff:
59
+ .scrapy
60
+
61
+ # Sphinx documentation
62
+ docs/_build/
63
+
64
+ # PyBuilder
65
+ target/
66
+
67
+ # pyenv
68
+ .python-version
69
+
70
+ # celery beat schedule file
71
+ celerybeat-schedule
72
+
73
+ # SageMath parsed files
74
+ *.sage.py
75
+
76
+ # Spyder project settings
77
+ .spyderproject
78
+ .spyproject
79
+
80
+ # Rope project settings
81
+ .ropeproject
82
+
83
+ # Mr Developer
84
+ .mr.developer.cfg
85
+ .project
86
+ .pydevproject
87
+
88
+ # mkdocs documentation
89
+ /site
90
+
91
+ # mypy
92
+ .mypy_cache/
93
+ .dmypy.json
94
+ dmypy.json
95
+
96
+ # ruff
97
+ .ruff_cache
98
+
99
+ # Pyre type checker
100
+ .pyre/
101
+
102
+ # End of https://www.gitignore.io/api/python
103
+
104
+ # OSX files
105
+ .DS_Store
106
+ .jupyter_ystore.db
@@ -0,0 +1,16 @@
1
+ header:
2
+ license:
3
+ spdx-id: BSD-3-Clause
4
+ copyright-owner: Datalayer, Inc.
5
+ copyright-year: 2023-2024
6
+ software-name: jupyter-kernel-client
7
+
8
+ paths-ignore:
9
+ - '**/*.ipynb'
10
+ - '**/*.json'
11
+ - '**/*.yaml'
12
+ - '**/*.yml'
13
+ - '**/.*'
14
+ - 'LICENSE'
15
+
16
+ comment: on-failure
@@ -0,0 +1,38 @@
1
+ ci:
2
+ autoupdate_schedule: monthly
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v5.0.0
7
+ hooks:
8
+ - id: end-of-file-fixer
9
+ - id: check-case-conflict
10
+ - id: check-executables-have-shebangs
11
+ - id: requirements-txt-fixer
12
+ - id: check-added-large-files
13
+ - id: check-case-conflict
14
+ - id: check-toml
15
+ - id: check-yaml
16
+ - id: debug-statements
17
+ - id: forbid-new-submodules
18
+ - id: check-builtin-literals
19
+ - id: trailing-whitespace
20
+
21
+ - repo: https://github.com/python-jsonschema/check-jsonschema
22
+ rev: 0.29.4
23
+ hooks:
24
+ - id: check-github-workflows
25
+
26
+ - repo: https://github.com/executablebooks/mdformat
27
+ rev: 0.7.19
28
+ hooks:
29
+ - id: mdformat
30
+ additional_dependencies:
31
+ [mdformat-gfm, mdformat-frontmatter, mdformat-footnote]
32
+
33
+ - repo: https://github.com/charliermarsh/ruff-pre-commit
34
+ rev: v0.8.0
35
+ hooks:
36
+ - id: ruff
37
+ args: ["--fix"]
38
+ - id: ruff-format
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ <!-- <START NEW CHANGELOG ENTRY> -->
4
+
5
+ ## 0.1.1
6
+
7
+ ([Full Changelog](https://github.com/datalayer/jupyter-nbmodel-client/compare/aef1fe634cfe585219a2c8ec8a3f9373e6834fec...aae60dc27cc23cf84fe6b4d263506495adb97dd6))
8
+
9
+ ### Enhancements made
10
+
11
+ - Return outputs from `execute_cell` [#8](https://github.com/datalayer/jupyter-nbmodel-client/pull/8) ([@fcollonval](https://github.com/fcollonval))
12
+ - Make client inherit from model directly [#7](https://github.com/datalayer/jupyter-nbmodel-client/pull/7) ([@fcollonval](https://github.com/fcollonval))
13
+ - Add releaser workflows [#6](https://github.com/datalayer/jupyter-nbmodel-client/pull/6) ([@fcollonval](https://github.com/fcollonval))
14
+
15
+ ### Documentation improvements
16
+
17
+ - Return outputs from `execute_cell` [#8](https://github.com/datalayer/jupyter-nbmodel-client/pull/8) ([@fcollonval](https://github.com/fcollonval))
18
+
19
+ ### Contributors to this release
20
+
21
+ ([GitHub contributors page for this release](https://github.com/datalayer/jupyter-nbmodel-client/graphs/contributors?from=2024-12-02&to=2024-12-04&type=c))
22
+
23
+ [@fcollonval](https://github.com/search?q=repo%3Adatalayer%2Fjupyter-nbmodel-client+involves%3Afcollonval+updated%3A2024-12-02..2024-12-04&type=Issues)
24
+
25
+ <!-- <END NEW CHANGELOG ENTRY> -->
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Datalayer
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.3
2
+ Name: jupyter_nbmodel_client
3
+ Version: 0.1.1
4
+ Project-URL: Home, https://github.com/datalayer/jupyter-nbmodel-client
5
+ Author-email: Datalayer <info@datalayer.io>
6
+ License: BSD 3-Clause License
7
+
8
+ Copyright (c) 2024, Datalayer
9
+ All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimer.
16
+
17
+ 2. Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ 3. Neither the name of the copyright holder nor the names of its
22
+ contributors may be used to endorse or promote products derived from
23
+ this software without specific prior written permission.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ Keywords: Jupyter
36
+ Classifier: Framework :: Jupyter
37
+ Classifier: License :: OSI Approved :: BSD License
38
+ Classifier: Programming Language :: Python
39
+ Classifier: Programming Language :: Python :: 3
40
+ Requires-Python: >=3.9
41
+ Requires-Dist: jupyter-ydoc<4.0.0,>=2.1.2
42
+ Requires-Dist: nbformat~=5.0
43
+ Requires-Dist: pycrdt<0.11.0,>=0.10.3
44
+ Requires-Dist: requests
45
+ Requires-Dist: websocket-client
46
+ Provides-Extra: lint
47
+ Requires-Dist: mdformat-gfm>=0.3.5; extra == 'lint'
48
+ Requires-Dist: mdformat>0.7; extra == 'lint'
49
+ Requires-Dist: ruff; extra == 'lint'
50
+ Provides-Extra: test
51
+ Requires-Dist: httpx-ws; extra == 'test'
52
+ Requires-Dist: jupyter-server-ydoc~=1.0.0; extra == 'test'
53
+ Requires-Dist: pytest-jupyter[server]>=0.6; extra == 'test'
54
+ Requires-Dist: pytest>=7.0; extra == 'test'
55
+ Provides-Extra: typing
56
+ Requires-Dist: mypy>=0.990; extra == 'typing'
57
+ Description-Content-Type: text/markdown
58
+
59
+ # jupyter_nbmodel_client
60
+
61
+ [![Github Actions Status](https://github.com/datalayer/jupyter-nbmodel-client/workflows/Build/badge.svg)](https://github.com/datalayer/jupyter-nbmodel-client/actions/workflows/build.yml)
62
+
63
+ Client to interact with Jupyter notebook model.
64
+
65
+ ## Install
66
+
67
+ To install the extension, execute:
68
+
69
+ ```bash
70
+ pip install jupyter_nbmodel_client
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ 1. Ensure you have an environment with `jupyter-server-ydoc` installed.
76
+
77
+ > To reproduce the above video you will need to install `jupyterlab`, `jupyter-collaboration` and `scikit-learn` and `matplotlib` for the notebook demo.
78
+
79
+ 1. Start the server `jupyter server` (or JupyterLab like in the video)
80
+
81
+ 1. Write down the URL (usually `http://localhost:8888`) and the server token
82
+
83
+ 1. Open a Python terminal
84
+
85
+ 1. Execute the following snippet to add a cell
86
+
87
+ ```py
88
+ from jupyter_nbmodel_client import NbModelClient
89
+
90
+ with NbModelClient(server_url="http://localhost:8888", token="...", path="test.ipynb") as notebook:
91
+ notebook.add_code_cell("print('hello world')")
92
+ ```
93
+
94
+ 1. Another example adding a cell and executing within a kernel process
95
+
96
+ ```py
97
+ from jupyter_kernel_client import KernelClient
98
+ from jupyter_nbmodel_client import NbModelClient
99
+
100
+ with KernelClient(server_url="http://localhost:8888", token="...") as kernel:
101
+ with NbModelClient(server_url="http://localhost:8888", token="...", path="test.ipynb") as notebook:
102
+ cell_index = notebook.add_code_cell("print('hello world')")
103
+ results = notebook.execute_cell(cell_index, kernel)
104
+
105
+ assert results["status"] == "ok"
106
+ assert len(results["outputs"]) > 0
107
+ ```
108
+
109
+ > [!NOTE]
110
+ > Instead of using the clients as context manager, you can call the ``start()`` and ``stop()`` methods.
111
+
112
+ ```py
113
+ from jupyter_nbmodel_client import NbModelClient
114
+
115
+ kernel = KernelClient(server_url="http://localhost:8888", token="...")
116
+ kernel.start()
117
+ try:
118
+ notebook = NbModelClient(server_url="http://localhost:8888", token="...", path="test.ipynb"):
119
+ notebook.start()
120
+ try:
121
+ cell_index = notebook.add_code_cell("print('hello world')")
122
+ results = notebook.execute_cell(cell_index, kernel)
123
+ finally:
124
+ notebook.stop()
125
+ finally:
126
+ kernel.stop()
127
+ ```
128
+
129
+ ## Uninstall
130
+
131
+ To remove the extension, execute:
132
+
133
+ ```bash
134
+ pip uninstall jupyter_nbmodel_client
135
+ ```
136
+
137
+ ## Troubleshoot
138
+
139
+ If you are seeing the frontend extension, but it is not working, check
140
+ that the server extension is enabled:
141
+
142
+ ```bash
143
+ jupyter server extension list
144
+ ```
145
+
146
+ ## Contributing
147
+
148
+ ### Development install
149
+
150
+ ```bash
151
+ # Clone the repo to your local environment
152
+ # Change directory to the jupyter_nbmodel_client directory
153
+ # Install package in development mode - will automatically enable
154
+ # The server extension.
155
+ pip install -e ".[test,lint,typing]"
156
+ ```
157
+
158
+ ### Running Tests
159
+
160
+ Install dependencies:
161
+
162
+ ```bash
163
+ pip install -e ".[test]"
164
+ ```
165
+
166
+ To run the python tests, use:
167
+
168
+ ```bash
169
+ pytest
170
+ ```
171
+
172
+ ### Development uninstall
173
+
174
+ ```bash
175
+ pip uninstall jupyter_nbmodel_client
176
+ ```
177
+
178
+ ### Packaging the extension
179
+
180
+ See [RELEASE](RELEASE.md)