Metadata-Version: 2.3
Name: neno
Version: 0.2.1
Summary: NeNo (Network Notebooks) is a tool that allows you manage and trigger your Jupyter notebooks remotely over the network using HTTP.
Project-URL: Homepage, https://github.com/snophey/nota
Project-URL: Issues, https://github.com/snophey/nota/issues
Author-email: Alex Rovner <rovnero@gmail.com>
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Requires-Dist: marshmallow==3.21.1
Requires-Dist: prettytable==3.10.0
Requires-Dist: requests==2.31.0
Requires-Dist: typer==0.12.3
Requires-Dist: typing-extensions==4.11.0
Provides-Extra: server
Requires-Dist: anyio==4.3.0; extra == 'server'
Requires-Dist: appnope==0.1.4; extra == 'server'
Requires-Dist: argon2-cffi-bindings==21.2.0; extra == 'server'
Requires-Dist: argon2-cffi==23.1.0; extra == 'server'
Requires-Dist: arrow==1.3.0; extra == 'server'
Requires-Dist: asttokens==2.4.1; extra == 'server'
Requires-Dist: async-lru==2.0.4; extra == 'server'
Requires-Dist: attrs==23.2.0; extra == 'server'
Requires-Dist: babel==2.15.0; extra == 'server'
Requires-Dist: bash-kernel==0.9.3; extra == 'server'
Requires-Dist: beautifulsoup4==4.12.3; extra == 'server'
Requires-Dist: bleach==6.1.0; extra == 'server'
Requires-Dist: blinker==1.7.0; extra == 'server'
Requires-Dist: certifi==2024.2.2; extra == 'server'
Requires-Dist: cffi==1.16.0; extra == 'server'
Requires-Dist: charset-normalizer==3.3.2; extra == 'server'
Requires-Dist: click==8.1.7; extra == 'server'
Requires-Dist: comm==0.2.2; extra == 'server'
Requires-Dist: debugpy==1.8.1; extra == 'server'
Requires-Dist: decorator==5.1.1; extra == 'server'
Requires-Dist: defusedxml==0.7.1; extra == 'server'
Requires-Dist: entrypoints==0.4; extra == 'server'
Requires-Dist: exceptiongroup==1.2.1; extra == 'server'
Requires-Dist: executing==2.0.1; extra == 'server'
Requires-Dist: fastjsonschema==2.19.1; extra == 'server'
Requires-Dist: flask==3.0.2; extra == 'server'
Requires-Dist: fqdn==1.5.1; extra == 'server'
Requires-Dist: gunicorn==22.0.0; extra == 'server'
Requires-Dist: h11==0.14.0; extra == 'server'
Requires-Dist: httpcore==1.0.5; extra == 'server'
Requires-Dist: httpx==0.27.0; extra == 'server'
Requires-Dist: idna==3.6; extra == 'server'
Requires-Dist: importlib-metadata==7.1.0; extra == 'server'
Requires-Dist: ipykernel==6.29.4; extra == 'server'
Requires-Dist: ipython==8.18.1; extra == 'server'
Requires-Dist: isoduration==20.11.0; extra == 'server'
Requires-Dist: itsdangerous==2.1.2; extra == 'server'
Requires-Dist: jedi==0.19.1; extra == 'server'
Requires-Dist: jinja2==3.1.3; extra == 'server'
Requires-Dist: json5==0.9.25; extra == 'server'
Requires-Dist: jsonpointer==2.4; extra == 'server'
Requires-Dist: jsonschema-specifications==2023.12.1; extra == 'server'
Requires-Dist: jsonschema==4.21.1; extra == 'server'
Requires-Dist: jupyter-client==8.6.1; extra == 'server'
Requires-Dist: jupyter-core==5.7.2; extra == 'server'
Requires-Dist: jupyter-events==0.10.0; extra == 'server'
Requires-Dist: jupyter-lsp==2.2.5; extra == 'server'
Requires-Dist: jupyter-server-terminals==0.5.3; extra == 'server'
Requires-Dist: jupyter-server==2.14.0; extra == 'server'
Requires-Dist: jupyterlab-pygments==0.3.0; extra == 'server'
Requires-Dist: jupyterlab-server==2.27.1; extra == 'server'
Requires-Dist: jupyterlab==4.2.0; extra == 'server'
Requires-Dist: markdown-it-py==3.0.0; extra == 'server'
Requires-Dist: markupsafe==2.1.5; extra == 'server'
Requires-Dist: matplotlib-inline==0.1.6; extra == 'server'
Requires-Dist: mdurl==0.1.2; extra == 'server'
Requires-Dist: mistune==3.0.2; extra == 'server'
Requires-Dist: nbclient==0.10.0; extra == 'server'
Requires-Dist: nbconvert==7.16.4; extra == 'server'
Requires-Dist: nbformat==5.10.3; extra == 'server'
Requires-Dist: nest-asyncio==1.6.0; extra == 'server'
Requires-Dist: notebook-shim==0.2.4; extra == 'server'
Requires-Dist: numpy==1.26.4; extra == 'server'
Requires-Dist: overrides==7.7.0; extra == 'server'
Requires-Dist: packaging==24.0; extra == 'server'
Requires-Dist: pandas==2.2.1; extra == 'server'
Requires-Dist: pandocfilters==1.5.1; extra == 'server'
Requires-Dist: papermill==2.5.0; extra == 'server'
Requires-Dist: parso==0.8.3; extra == 'server'
Requires-Dist: pexpect==4.9.0; extra == 'server'
Requires-Dist: piny==1.1.0; extra == 'server'
Requires-Dist: platformdirs==4.2.0; extra == 'server'
Requires-Dist: prometheus-client==0.20.0; extra == 'server'
Requires-Dist: prompt-toolkit==3.0.43; extra == 'server'
Requires-Dist: psutil==5.9.8; extra == 'server'
Requires-Dist: ptyprocess==0.7.0; extra == 'server'
Requires-Dist: pure-eval==0.2.2; extra == 'server'
Requires-Dist: pyarrow==15.0.2; extra == 'server'
Requires-Dist: pycparser==2.22; extra == 'server'
Requires-Dist: pygments==2.17.2; extra == 'server'
Requires-Dist: python-dateutil==2.9.0.post0; extra == 'server'
Requires-Dist: python-json-logger==2.0.7; extra == 'server'
Requires-Dist: pytz==2024.1; extra == 'server'
Requires-Dist: pyyaml==6.0.1; extra == 'server'
Requires-Dist: pyzmq==25.1.2; extra == 'server'
Requires-Dist: referencing==0.34.0; extra == 'server'
Requires-Dist: rfc3339-validator==0.1.4; extra == 'server'
Requires-Dist: rfc3986-validator==0.1.1; extra == 'server'
Requires-Dist: rich==13.7.1; extra == 'server'
Requires-Dist: rpds-py==0.18.0; extra == 'server'
Requires-Dist: scheduler==0.8.5; extra == 'server'
Requires-Dist: send2trash==1.8.3; extra == 'server'
Requires-Dist: shellingham==1.5.4; extra == 'server'
Requires-Dist: six==1.16.0; extra == 'server'
Requires-Dist: sniffio==1.3.1; extra == 'server'
Requires-Dist: soupsieve==2.5; extra == 'server'
Requires-Dist: stack-data==0.6.3; extra == 'server'
Requires-Dist: tenacity==8.2.3; extra == 'server'
Requires-Dist: terminado==0.18.1; extra == 'server'
Requires-Dist: tinycss2==1.3.0; extra == 'server'
Requires-Dist: tomli==2.0.1; extra == 'server'
Requires-Dist: tornado==6.4; extra == 'server'
Requires-Dist: tqdm==4.66.2; extra == 'server'
Requires-Dist: traitlets==5.14.2; extra == 'server'
Requires-Dist: typeguard==4.2.1; extra == 'server'
Requires-Dist: types-python-dateutil==2.9.0.20240316; extra == 'server'
Requires-Dist: tzdata==2024.1; extra == 'server'
Requires-Dist: uri-template==1.3.0; extra == 'server'
Requires-Dist: wcwidth==0.2.13; extra == 'server'
Requires-Dist: webcolors==1.13; extra == 'server'
Requires-Dist: webencodings==0.5.1; extra == 'server'
Requires-Dist: websocket-client==1.8.0; extra == 'server'
Requires-Dist: werkzeug==3.0.1; extra == 'server'
Requires-Dist: zipp==3.18.2; extra == 'server'
Description-Content-Type: text/markdown

# NeNo

NeNo (Network Notebooks) is a server and CLI utility that allows you to deploy your jupyter notebooks and trigger their execution
by calling an API endpoint.
You can then use the CLI to view the execution history and inspect the outputs.
Great for scheduled tasks and prototyping APIs.

## Installation

If you want just the CLI utility, you can install it with pip:

```bash
pip install neno
```

Then you can start the utility with `python -m neno`. For convenience, you can create an alias in your shell configuration:

```bash
alias neno="python -m neno"
```

If you want to run the neno server locally, you need to install some optional dependencies:

```bash
pip install "neno[server]"
```

## Launching the server

To start the server, first create a `config.yaml` file:

```yaml
host: "localhost"
port: 5000
backends:
  # For this simple example, we will use the filesystem to store the data and configuration
  dataBackend:
    filesystem:
      path: "backend/data"
  configBackend:
    filesystem:
      path: "backend/config"
```

Then you can start the server with:

```bash
neno serve --config-file config.yaml
```

## Usage

If your server runs somewhere other than `localhost:5000`, point the `NENO_SERVER_URL` environment variable to the correct URL:

```bash
export NENO_SERVER_URL=http://localhost:5001
```

You can then use the CLI to interact with the server:

```bash
# Upload a notebook as a new endpoint. The endpoint will be available at $NENO_SERVER_URL/api/gen-report. We can also use the `--file` option as many times as we want to upload additional files that the notebook needs.
neno add endpoint gen-report --notebook create-report.ipynb --file credentials.json --keep-runs=always

# List all the endpoints
neno get endpoints

# List all endpoints and print a curl command for triggering each one of them
neno get endpoints --show-curl

# List recent executions of the `gen-report` endpoint. By default, it will show the last 10 executions.
neno get runs gen-report

# List last 50 executions of the `gen-report` endpoint
neno get runs gen-report --limit 50

# Download the output (output notebook, any additional files) of the execution of `gen-report` with ID 12345
neno fetch run gen-report 12345

# Download the output of run 12345 and open it in a local jupyterlab instance (jupyterlab must be installed: `pip install jupyterlab`)
neno fetch run gen-report 12345 --inspect
```
