# Origami
<p align="center">
<img src="docs/papersnake.svg" width="250px" />
<br />
Launch, edit, and share Jupyter notebooks <i>in automation</i>.
</p>
<p align="center">
<a href="https://github.com/noteable-io/origami/actions/workflows/ci.yaml">
<img src="https://github.com/noteable-io/origami/actions/workflows/ci.yaml/badge.svg" alt="CI" />
</a>
<a href="https://codecov.io/gh/noteable-io/origami" >
<img src="https://codecov.io/gh/noteable-io/origami/branch/main/graph/badge.svg" alt="codecov code coverage"/>
</a>
<img alt="PyPI - License" src="https://img.shields.io/pypi/l/noteable-origami" />
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/noteable-origami" />
<img alt="PyPI" src="https://img.shields.io/pypi/v/noteable-origami">
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
</p>
---
[Install](#installation) | [Getting Started](#getting-started) | [Documentation](https://noteable-origami.readthedocs.io) | [License](./LICENSE) | [Code of Conduct](./CODE_OF_CONDUCT.md) | [Contributing](./CONTRIBUTING.md)
<!-- --8<-- [start:intro] -->
## Intro to Origami
Origami is a 🐍 Python library for talking to [Noteable notebooks](https://noteable.io/). This is the official way to access the full breadth of API calls and access patterns in async Python for rich programmatic access to notebooks. You can use [Noteable for free](https://app.noteable.io) with a quick signup.
<!-- --8<-- [end:intro] -->
<!-- --8<-- [start:requirements] -->
## Requirements
Python 3.8+
<!-- --8<-- [end:requirements] -->
<!-- --8<-- [start:install] -->
## Installation
For stable release:
```bash
pip install noteable-origami
```
```bash
poetry add noteable-origami
```
For alpha pre-release:
```bash
pip install noteable-origami --pre
```
<!-- --8<-- [end:install] -->
## Getting Started
> **Note**
> Developer note: For pre-1.0 release information, see the [pre-1.0 README](https://github.com/noteable-io/origami/blob/release/0.0.35/README.md)
### API Tokens
<!-- --8<-- [start:api-tokens] -->
The Noteable API requires an authentication token. You can manage tokens at the Noteable user settings page.
1. Log in to [Noteable](https://app.noteable.io) (sign up is free).
2. In the User Settings tab, navigate to `API Tokens` and generate a new token.
![](./screenshots/user_settings__api_tokens.png)
3. Copy the generated token to the clipboard and save in a secure location, to be read into your Python environment later.
![](./screenshots/user_settings__api_tokens2.png)
The token can be passed directly in to `APIClient` on initialization, or set it as env var `NOTEABLE_TOKEN`.
### Usage
<!-- --8<-- [end:api-tokens] -->
The example below will guide you through the basics of creating a notebook, adding content, executing code, and seeing the output. For more examples, see our [Use Cases](../usage) section.
### Setting up the `APIClient`
<!-- --8<-- [start:api-client] -->
Using the API token you created previously, load it into your notebook environment so it can be passed into the `APIClient` directly. (If you're in [Noteable](https://app.noteable.io), you can create a [Secret](https://docs.noteable.io/product-docs/collaborate/access-and-visibility/secrets-permissions) that can be read in as an environment variable.)
```python
import os
from origami.clients.api import APIClient
# if we have the `NOTEABLE_TOKEN` environment variable set,
# we don't need to pass it in to the APIClient directly
api_client = APIClient()
```
*The `APIClient` is what we'll use to make HTTP requests to Noteable's REST API.*
<!-- --8<-- [end:api-client] -->
### Checking your user information
<!-- --8<-- [start:user-info] -->
```python
user = await api_client.user_info()
user
```
``` {.python .no-copy }
User(
id=UUID('f1a2b3c4-5678-4d90-ef01-23456789abcd'),
created_at=datetime.datetime(2023, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
updated_at=datetime.datetime(2023, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
deleted_at=None,
handle='ori.gami',
email='origami@noteable.io',
first_name='Ori',
last_name='Gami',
origamist_default_project_id=UUID('a1b2c3d4-e5f6-4a7b-8123-abcdef123456'),
principal_sub='pat:0a1b2c3d4e5f6g7h8i9j10k11l',
auth_type='pat:0a1b2c3d4e5f6g7h8i9j10k11l'
)
```
(The information returned should match your user account information associated with the previously-generated API token.)
<!-- --8<-- [end:user-info] -->
### Creating a new Notebook
> **Note**
> For this example, we're using the `origamist_default_project_id`, which is the default project designed to be used by the ChatGPT plugin. Feel free to replace it with projects you have access to in [Noteable](https://app.noteable.io/)!
<!-- --8<-- [start:create-notebook] -->
Provide a file `path` as well as a `project_id` (UUID) where the Notebook will exist.
```python
project_id = user.origamist_default_project_id
file = await api_client.create_notebook(
project_id=project_id,
path="Origami Demo.ipynb"
)
file
```
``` {.python .no-copy }
File(
id=UUID('bcd12345-6789-4abc-d012-3456abcdef90'),
created_at=datetime.datetime(2023, 2, 2, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
updated_at=datetime.datetime(2023, 2, 2, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),
deleted_at=None,
filename='Origami Demo.ipynb',
path=PosixPath('Origami Demo.ipynb'),
project_id=UUID('a1b2c3d4-e5f6-4a7b-8123-abcdef123456'),
space_id=UUID('7890ab12-3412-4cde-8901-2345abcdef67'),
size=0,
mimetype=None,
type='notebook',
current_version_id=None,
presigned_download_url=None,
url='https://app.noteable.io/f/abc12312-3412-4abc-8123-abc12312abc1/Origami Demo.ipynb'
)
```
<!-- --8<-- [end:create-notebook] -->
### Launching a Kernel
<!-- --8<-- [start:launch-kernel] -->
At a minimum, the `file_id` from the Notebook is required. Additionally, you can specify:
+ `kernel_name` (default `python3`, see more about [available kernels](https://docs.noteable.io/product-docs/work-with-notebooks/manage-kernels/noteable-provided-kernels))
+ `hardware_size` (default `small`, see more about [hardware options](https://docs.noteable.io/product-docs/work-with-notebooks/manage-hardware)).
```python
kernel_session = await api_client.launch_kernel(file_id=file.id)
kernel_session
```
```{.python .no-copy}
KernelSession(
id=UUID('e1f2a345-6789-4b01-cdef-1234567890ab'),
kernel=KernelDetails(
name='python3',
last_activity=datetime.datetime(2023, 2, 2, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),
execution_state='idle'
)
)
```
<!-- --8<-- [end:launch-kernel] -->
### Adding Cells
<!-- --8<-- [start:connect-rtu] -->
Content updates and code execution is handled through the Noteable Real-Time Update (RTU) websocket connection.
```python
realtime_notebook = await api_client.connect_realtime(file)
```
<!-- --8<-- [end:connect-rtu] -->
> **Warning**
> You may see messages like `Received un-modeled RTU message msg.channel= ...`. This is expected as we update the Noteable backend services' messaging.
<!-- --8<-- [start:add-cells] -->
Once the RTU client is connected, we can begin adding cells, executing code, and more! First, let's add a code cell with a basic Python `print` statement.
```python
from origami.models.notebook import CodeCell
cell = CodeCell(source="print('Hello World')")
await realtime_notebook.add_cell(cell=cell)
```
(You can also pass code source directly into `.add_cell(source='CODE HERE')` as a shortcut.)
<!-- --8<-- [end:add-cells] -->
### Running a Code Cell
<!-- --8<-- [start:run-code-cell] -->
The returned value is a dictionary of `asyncio.Future`s. Awaiting those futures will block until the cells have completed execution.
The return value of the Futures is the up-to-date cell. If there's output, an output collection id will be set on the cell metadata.
```python
import asyncio
queued_execution = await realtime_notebook.queue_execution(cell.id)
cells = await asyncio.gather(*queued_execution)
cell = cells[0]
cell
```
```{.python .no-copy}
CodeCell(
id='2345ab6c-de78-4901-bcde-f1234567890a',
source="print('Hello World')",
metadata={
'noteable': {'output_collection_id': UUID('d1234e5f-6789-4a0b-c123-4567890abcdef')},
'ExecuteTime': {
'start_time': '2023-02-02T01:00:00.000000+00:00',
'end_time': '2023-02-02T01:00:00.050000+00:00'
}
},
cell_type='code',
execution_count=None,
outputs=[]
)
```
<!-- --8<-- [end:run-code-cell] -->
### Getting Cell Output
<!-- --8<-- [start:get-cell-output] -->
We can call the `.output_collection_id` property on cells directly, rather than having to parse the cell metadata.
```python
output_collection = await api_client.get_output_collection(cell.output_collection_id)
output_collection
```
```{.python .no-copy}
KernelOutputCollection(
id=UUID('d1234e5f-6789-4a0b-c123-4567890abcdef'),
created_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),
updated_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),
deleted_at=None,
cell_id='2345ab6c-de78-4901-bcde-f1234567890a',
widget_model_id=None,
file_id=UUID('bcd12345-6789-4abc-d012-3456abcdef90'),
outputs=[
KernelOutput(
id=UUID('abcdef90-1234-4a56-7890-abcdef123456'),
created_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),
updated_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),
deleted_at=None,
type='stream',
display_id=None,
available_mimetypes=['text/plain'],
content_metadata=KernelOutputContent(raw='{"name":"stdout"}', url=None, mimetype='application/json'),
content=KernelOutputContent(raw='Hello World\n', url=None, mimetype='text/plain'),
content_for_llm=KernelOutputContent(raw='Hello World\n', url=None, mimetype='text/plain'),
parent_collection_id=UUID('d1234e5f-6789-4a0b-c123-4567890abcdef')
)
]
)
```
<!-- --8<-- [end:get-cell-output] -->
## CLI
Origami has a small CLI for fetching the content of a Notebook, and tailing a Notebook to see all RTU messages being emitted on the relevant RTU channels.
```
pip install noteable-origami[cli]
poetry install -E cli
```
1. Fetch the content of a Notebook and write to file: `origami fetch <file-id> > notebook.ipynb`
2. Tail a Notebook, useful when debugging RTU messages: `origami tail <file-id>`
## Dev ENV settings
- Use `NOTEABLE_API_URL` to point to non-production clusters, such as `http://localhost:8001/api` for local Gate development
- E2E tests will use `TEST_SPACE_ID`, `TEST_PROJECT_ID`, and `TEST_USER_ID` env vars when running, useful in CI
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md).
---
<p align="center">Open sourced with ❤️ by <a href="https://noteable.io">Noteable</a> for the community.</p>
<img href="https://pages.noteable.io/private-beta-access" src="https://assets.noteable.io/github/2022-07-29/noteable.png" alt="Boost Data Collaboration with Notebooks">
Raw data
{
"_id": null,
"home_page": "https://github.com/noteable-io/origami",
"name": "noteable-origami",
"maintainer": "Matt Seal",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "matt@noteable.io",
"keywords": "notebook,api,noteable",
"author": "Matt Seal",
"author_email": "matt@noteable.io",
"download_url": "https://files.pythonhosted.org/packages/d7/9a/42faa16f403551761e596e2c9c95fb41a3da45c161c5ca0181d9afced824/noteable_origami-2.0.0.tar.gz",
"platform": null,
"description": "# Origami\n\n<p align=\"center\">\n<img src=\"docs/papersnake.svg\" width=\"250px\" />\n<br />\nLaunch, edit, and share Jupyter notebooks <i>in automation</i>.\n</p>\n\n<p align=\"center\">\n<a href=\"https://github.com/noteable-io/origami/actions/workflows/ci.yaml\">\n <img src=\"https://github.com/noteable-io/origami/actions/workflows/ci.yaml/badge.svg\" alt=\"CI\" />\n</a>\n<a href=\"https://codecov.io/gh/noteable-io/origami\" > \n <img src=\"https://codecov.io/gh/noteable-io/origami/branch/main/graph/badge.svg\" alt=\"codecov code coverage\"/> \n </a>\n<img alt=\"PyPI - License\" src=\"https://img.shields.io/pypi/l/noteable-origami\" />\n<img alt=\"PyPI - Python Version\" src=\"https://img.shields.io/pypi/pyversions/noteable-origami\" />\n<img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/noteable-origami\">\n<a href=\"https://github.com/psf/black\"><img alt=\"Code style: black\" src=\"https://img.shields.io/badge/code%20style-black-000000.svg\"></a>\n</p>\n\n---\n\n[Install](#installation) | [Getting Started](#getting-started) | [Documentation](https://noteable-origami.readthedocs.io) | [License](./LICENSE) | [Code of Conduct](./CODE_OF_CONDUCT.md) | [Contributing](./CONTRIBUTING.md)\n\n<!-- --8<-- [start:intro] -->\n\n## Intro to Origami\n\nOrigami is a \ud83d\udc0d Python library for talking to [Noteable notebooks](https://noteable.io/). This is the official way to access the full breadth of API calls and access patterns in async Python for rich programmatic access to notebooks. You can use [Noteable for free](https://app.noteable.io) with a quick signup.\n\n<!-- --8<-- [end:intro] -->\n\n<!-- --8<-- [start:requirements] -->\n\n## Requirements\n\nPython 3.8+\n\n<!-- --8<-- [end:requirements] -->\n\n<!-- --8<-- [start:install] -->\n\n## Installation\n\nFor stable release:\n\n```bash\npip install noteable-origami\n```\n\n```bash\npoetry add noteable-origami\n```\n\nFor alpha pre-release:\n\n```bash\npip install noteable-origami --pre\n```\n\n<!-- --8<-- [end:install] -->\n\n## Getting Started\n\n> **Note**\n> Developer note: For pre-1.0 release information, see the [pre-1.0 README](https://github.com/noteable-io/origami/blob/release/0.0.35/README.md)\n\n### API Tokens\n<!-- --8<-- [start:api-tokens] -->\nThe Noteable API requires an authentication token. You can manage tokens at the Noteable user settings page.\n\n1. Log in to [Noteable](https://app.noteable.io) (sign up is free).\n2. In the User Settings tab, navigate to `API Tokens` and generate a new token.\n![](./screenshots/user_settings__api_tokens.png)\n3. Copy the generated token to the clipboard and save in a secure location, to be read into your Python environment later.\n![](./screenshots/user_settings__api_tokens2.png)\n\nThe token can be passed directly in to `APIClient` on initialization, or set it as env var `NOTEABLE_TOKEN`.\n\n### Usage\n<!-- --8<-- [end:api-tokens] -->\n\nThe example below will guide you through the basics of creating a notebook, adding content, executing code, and seeing the output. For more examples, see our [Use Cases](../usage) section.\n\n### Setting up the `APIClient`\n<!-- --8<-- [start:api-client] -->\nUsing the API token you created previously, load it into your notebook environment so it can be passed into the `APIClient` directly. (If you're in [Noteable](https://app.noteable.io), you can create a [Secret](https://docs.noteable.io/product-docs/collaborate/access-and-visibility/secrets-permissions) that can be read in as an environment variable.)\n\n```python\nimport os\nfrom origami.clients.api import APIClient\n\n# if we have the `NOTEABLE_TOKEN` environment variable set,\n# we don't need to pass it in to the APIClient directly\napi_client = APIClient()\n```\n*The `APIClient` is what we'll use to make HTTP requests to Noteable's REST API.*\n<!-- --8<-- [end:api-client] -->\n\n### Checking your user information\n<!-- --8<-- [start:user-info] -->\n```python\nuser = await api_client.user_info()\nuser\n```\n``` {.python .no-copy }\nUser(\n id=UUID('f1a2b3c4-5678-4d90-ef01-23456789abcd'),\n created_at=datetime.datetime(2023, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),\n updated_at=datetime.datetime(2023, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),\n deleted_at=None,\n handle='ori.gami',\n email='origami@noteable.io',\n first_name='Ori',\n last_name='Gami',\n origamist_default_project_id=UUID('a1b2c3d4-e5f6-4a7b-8123-abcdef123456'),\n principal_sub='pat:0a1b2c3d4e5f6g7h8i9j10k11l',\n auth_type='pat:0a1b2c3d4e5f6g7h8i9j10k11l'\n)\n```\n(The information returned should match your user account information associated with the previously-generated API token.)\n<!-- --8<-- [end:user-info] -->\n\n### Creating a new Notebook\n\n> **Note**\n> For this example, we're using the `origamist_default_project_id`, which is the default project designed to be used by the ChatGPT plugin. Feel free to replace it with projects you have access to in [Noteable](https://app.noteable.io/)!\n\n<!-- --8<-- [start:create-notebook] -->\nProvide a file `path` as well as a `project_id` (UUID) where the Notebook will exist.\n```python\nproject_id = user.origamist_default_project_id\n\nfile = await api_client.create_notebook(\n project_id=project_id,\n path=\"Origami Demo.ipynb\"\n)\nfile\n```\n``` {.python .no-copy }\nFile(\n id=UUID('bcd12345-6789-4abc-d012-3456abcdef90'),\n created_at=datetime.datetime(2023, 2, 2, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),\n updated_at=datetime.datetime(2023, 2, 2, 0, 0, 0, 0, tzinfo=datetime.timezone.utc),\n deleted_at=None,\n filename='Origami Demo.ipynb',\n path=PosixPath('Origami Demo.ipynb'),\n project_id=UUID('a1b2c3d4-e5f6-4a7b-8123-abcdef123456'),\n space_id=UUID('7890ab12-3412-4cde-8901-2345abcdef67'),\n size=0,\n mimetype=None,\n type='notebook',\n current_version_id=None,\n presigned_download_url=None,\n url='https://app.noteable.io/f/abc12312-3412-4abc-8123-abc12312abc1/Origami Demo.ipynb'\n)\n```\n<!-- --8<-- [end:create-notebook] -->\n\n### Launching a Kernel\n<!-- --8<-- [start:launch-kernel] -->\nAt a minimum, the `file_id` from the Notebook is required. Additionally, you can specify:\n\n+ `kernel_name` (default `python3`, see more about [available kernels](https://docs.noteable.io/product-docs/work-with-notebooks/manage-kernels/noteable-provided-kernels))\n+ `hardware_size` (default `small`, see more about [hardware options](https://docs.noteable.io/product-docs/work-with-notebooks/manage-hardware)).\n\n```python\nkernel_session = await api_client.launch_kernel(file_id=file.id)\nkernel_session\n```\n```{.python .no-copy}\nKernelSession(\n id=UUID('e1f2a345-6789-4b01-cdef-1234567890ab'),\n kernel=KernelDetails(\n name='python3',\n last_activity=datetime.datetime(2023, 2, 2, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),\n execution_state='idle'\n )\n)\n```\n<!-- --8<-- [end:launch-kernel] -->\n\n### Adding Cells\n<!-- --8<-- [start:connect-rtu] -->\nContent updates and code execution is handled through the Noteable Real-Time Update (RTU) websocket connection.\n```python\nrealtime_notebook = await api_client.connect_realtime(file)\n```\n<!-- --8<-- [end:connect-rtu] -->\n\n> **Warning**\n> You may see messages like `Received un-modeled RTU message msg.channel= ...`. This is expected as we update the Noteable backend services' messaging.\n\n<!-- --8<-- [start:add-cells] -->\nOnce the RTU client is connected, we can begin adding cells, executing code, and more! First, let's add a code cell with a basic Python `print` statement.\n```python\nfrom origami.models.notebook import CodeCell\n\ncell = CodeCell(source=\"print('Hello World')\")\nawait realtime_notebook.add_cell(cell=cell)\n```\n(You can also pass code source directly into `.add_cell(source='CODE HERE')` as a shortcut.)\n<!-- --8<-- [end:add-cells] -->\n\n### Running a Code Cell\n<!-- --8<-- [start:run-code-cell] -->\nThe returned value is a dictionary of `asyncio.Future`s. Awaiting those futures will block until the cells have completed execution.\nThe return value of the Futures is the up-to-date cell. If there's output, an output collection id will be set on the cell metadata.\n```python\nimport asyncio\n\nqueued_execution = await realtime_notebook.queue_execution(cell.id)\ncells = await asyncio.gather(*queued_execution)\ncell = cells[0]\ncell\n```\n```{.python .no-copy}\nCodeCell(\n id='2345ab6c-de78-4901-bcde-f1234567890a',\n source=\"print('Hello World')\",\n metadata={\n 'noteable': {'output_collection_id': UUID('d1234e5f-6789-4a0b-c123-4567890abcdef')},\n 'ExecuteTime': {\n 'start_time': '2023-02-02T01:00:00.000000+00:00',\n 'end_time': '2023-02-02T01:00:00.050000+00:00'\n }\n },\n cell_type='code',\n execution_count=None,\n outputs=[]\n)\n```\n<!-- --8<-- [end:run-code-cell] -->\n\n### Getting Cell Output\n<!-- --8<-- [start:get-cell-output] -->\nWe can call the `.output_collection_id` property on cells directly, rather than having to parse the cell metadata.\n```python\noutput_collection = await api_client.get_output_collection(cell.output_collection_id)\noutput_collection\n```\n```{.python .no-copy}\nKernelOutputCollection(\n id=UUID('d1234e5f-6789-4a0b-c123-4567890abcdef'),\n created_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),\n updated_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),\n deleted_at=None,\n cell_id='2345ab6c-de78-4901-bcde-f1234567890a',\n widget_model_id=None,\n file_id=UUID('bcd12345-6789-4abc-d012-3456abcdef90'),\n outputs=[\n KernelOutput(\n id=UUID('abcdef90-1234-4a56-7890-abcdef123456'),\n created_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),\n updated_at=datetime.datetime(2023, 2, 2, 1, 0, 1, 000000, tzinfo=datetime.timezone.utc),\n deleted_at=None,\n type='stream',\n display_id=None,\n available_mimetypes=['text/plain'],\n content_metadata=KernelOutputContent(raw='{\"name\":\"stdout\"}', url=None, mimetype='application/json'),\n content=KernelOutputContent(raw='Hello World\\n', url=None, mimetype='text/plain'),\n content_for_llm=KernelOutputContent(raw='Hello World\\n', url=None, mimetype='text/plain'),\n parent_collection_id=UUID('d1234e5f-6789-4a0b-c123-4567890abcdef')\n )\n ]\n)\n```\n<!-- --8<-- [end:get-cell-output] -->\n\n## CLI\n\nOrigami has a small CLI for fetching the content of a Notebook, and tailing a Notebook to see all RTU messages being emitted on the relevant RTU channels.\n\n```\npip install noteable-origami[cli]\npoetry install -E cli\n```\n\n1. Fetch the content of a Notebook and write to file: `origami fetch <file-id> > notebook.ipynb`\n2. Tail a Notebook, useful when debugging RTU messages: `origami tail <file-id>`\n\n## Dev ENV settings\n\n- Use `NOTEABLE_API_URL` to point to non-production clusters, such as `http://localhost:8001/api` for local Gate development\n- E2E tests will use `TEST_SPACE_ID`, `TEST_PROJECT_ID`, and `TEST_USER_ID` env vars when running, useful in CI\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n---\n\n<p align=\"center\">Open sourced with \u2764\ufe0f by <a href=\"https://noteable.io\">Noteable</a> for the community.</p>\n\n<img href=\"https://pages.noteable.io/private-beta-access\" src=\"https://assets.noteable.io/github/2022-07-29/noteable.png\" alt=\"Boost Data Collaboration with Notebooks\">\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "The Noteable API interface",
"version": "2.0.0",
"project_urls": {
"Homepage": "https://github.com/noteable-io/origami",
"Repository": "https://github.com/noteable-io/origami"
},
"split_keywords": [
"notebook",
"api",
"noteable"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f1b4cfd3a0a3a580a11e78825202d4c948e88bda897c040f34a287e96d8b035c",
"md5": "1cb887a5305ecd9f99dacffcccf67fb0",
"sha256": "5bee40b8cae7b1e78ac75ffec3a88d71e818c1edfb27d2ebd919712d24b3e416"
},
"downloads": -1,
"filename": "noteable_origami-2.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1cb887a5305ecd9f99dacffcccf67fb0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 50408,
"upload_time": "2023-11-06T20:04:58",
"upload_time_iso_8601": "2023-11-06T20:04:58.393446Z",
"url": "https://files.pythonhosted.org/packages/f1/b4/cfd3a0a3a580a11e78825202d4c948e88bda897c040f34a287e96d8b035c/noteable_origami-2.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d79a42faa16f403551761e596e2c9c95fb41a3da45c161c5ca0181d9afced824",
"md5": "558527f3be2a20c3c7456d55c7f861a5",
"sha256": "9d96f9c48902adbb8b633c806a73563ee461b5e1c64c9894fa00e6890c240aa8"
},
"downloads": -1,
"filename": "noteable_origami-2.0.0.tar.gz",
"has_sig": false,
"md5_digest": "558527f3be2a20c3c7456d55c7f861a5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 43055,
"upload_time": "2023-11-06T20:05:00",
"upload_time_iso_8601": "2023-11-06T20:05:00.239123Z",
"url": "https://files.pythonhosted.org/packages/d7/9a/42faa16f403551761e596e2c9c95fb41a3da45c161c5ca0181d9afced824/noteable_origami-2.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-06 20:05:00",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "noteable-io",
"github_project": "origami",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "noteable-origami"
}