Package: noteable-origami
OrigamiLaunch, edit, and share Jupyter notebooksin automation.Install|Getting Started|Documentation|License|Code of Conduct|ContributingIntro to OrigamiOrigami is a 🐍 Python library for talking toNoteable notebooks. 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 useNoteable for freewith a quick signup.RequirementsPython 3.8+InstallationFor stable release:pipinstallnoteable-origamipoetryaddnoteable-origamiFor alpha pre-release:pipinstallnoteable-origami--preGetting StartedNoteDeveloper note: For pre-1.0 release information, see thepre-1.0 READMEAPI TokensThe Noteable API requires an authentication token. You can manage tokens at the Noteable user settings page.Log in toNoteable(sign up is free).In the User Settings tab, navigate toAPI Tokensand generate a new token.Copy the generated token to the clipboard and save in a secure location, to be read into your Python environment later.The token can be passed directly in toAPIClienton initialization, or set it as env varNOTEABLE_TOKEN.UsageThe example below will guide you through the basics of creating a notebook, adding content, executing code, and seeing the output. For more examples, see ourUse Casessection.Setting up theAPIClientUsing the API token you created previously, load it into your notebook environment so it can be passed into theAPIClientdirectly. (If you're inNoteable, you can create aSecretthat can be read in as an environment variable.)importosfromorigami.clients.apiimportAPIClient# if we have the `NOTEABLE_TOKEN` environment variable set,# we don't need to pass it in to the APIClient directlyapi_client=APIClient()TheAPIClientis what we'll use to make HTTP requests to Noteable's REST API.Checking your user informationuser=awaitapi_client.user_info()userUser(
    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.)Creating a new NotebookNoteFor this example, we're using theorigamist_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 inNoteable!Provide a filepathas well as aproject_id(UUID) where the Notebook will exist.project_id=user.origamist_default_project_idfile=awaitapi_client.create_notebook(project_id=project_id,path="Origami Demo.ipynb")fileFile(
    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'
)Launching a KernelAt a minimum, thefile_idfrom the Notebook is required. Additionally, you can specify:kernel_name(defaultpython3, see more aboutavailable kernels)hardware_size(defaultsmall, see more abouthardware options).kernel_session=awaitapi_client.launch_kernel(file_id=file.id)kernel_sessionKernelSession(
    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'
    )
)Adding CellsContent updates and code execution is handled through the Noteable Real-Time Update (RTU) websocket connection.realtime_notebook=awaitapi_client.connect_realtime(file)WarningYou may see messages likeReceived un-modeled RTU message msg.channel= .... This is expected as we update the Noteable backend services' messaging.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 Pythonprintstatement.fromorigami.models.notebookimportCodeCellcell=CodeCell(source="print('Hello World')")awaitrealtime_notebook.add_cell(cell=cell)(You can also pass code source directly into.add_cell(source='CODE HERE')as a shortcut.)Running a Code CellThe returned value is a dictionary ofasyncio.Futures. 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.importasyncioqueued_execution=awaitrealtime_notebook.queue_execution(cell.id)cells=awaitasyncio.gather(*queued_execution)cell=cells[0]cellCodeCell(
    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=[]
)Getting Cell OutputWe can call the.output_collection_idproperty on cells directly, rather than having to parse the cell metadata.output_collection=awaitapi_client.get_output_collection(cell.output_collection_id)output_collectionKernelOutputCollection(
    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')
        )
    ]
)CLIOrigami 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 cliFetch the content of a Notebook and write to file:origami fetch <file-id> > notebook.ipynbTail a Notebook, useful when debugging RTU messages:origami tail <file-id>Dev ENV settingsUseNOTEABLE_API_URLto point to non-production clusters, such ashttp://localhost:8001/apifor local Gate developmentE2E tests will useTEST_SPACE_ID,TEST_PROJECT_ID, andTEST_USER_IDenv vars when running, useful in CIContributingSeeCONTRIBUTING.md.Open sourced with ❤️ byNoteablefor the community.