Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ A Python client for the LabArchives API.
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.19599400.svg)](https://doi.org/10.5281/zenodo.19599400)
[![License: CC0-1.0](https://img.shields.io/badge/License-CC0_1.0-lightgrey.svg)](https://creativecommons.org/publicdomain/zero/1.0/)

`labapi` helps you authenticate with LabArchives, navigate notebook trees, and create or update notebook content from Python.
`labapi` authenticates with LabArchives, navigates notebook trees, and creates or updates notebook content from Python.

[Source](https://github.com/nimh-dsst/labapi) | [Docs](https://nimh-dsst.github.io/labapi/) | [Issues](https://github.com/nimh-dsst/labapi/issues)

## Start Here

- New to `labapi`? Follow the [First Success Tutorial](https://nimh-dsst.github.io/labapi/latest/quick_start/tutorial.html) for the fastest path from install to a visible change in LabArchives.
- New to `labapi`? Follow the [First Success Tutorial](https://nimh-dsst.github.io/labapi/latest/quick_start/tutorial.html) to install `labapi`, authenticate, and create your first LabArchives entry.
- Already using `labapi`? Jump to the [Quick Start](https://nimh-dsst.github.io/labapi/latest/quick_start/index.html), [User Guide](https://nimh-dsst.github.io/labapi/latest/guide/index.html), [Examples](https://nimh-dsst.github.io/labapi/latest/examples/index.html), or [FAQ](https://nimh-dsst.github.io/labapi/latest/faq.html).
- Working on the package itself? Start with [CONTRIBUTING.md](https://github.com/nimh-dsst/labapi/blob/main/CONTRIBUTING.md).

Expand Down Expand Up @@ -53,6 +53,8 @@ Extras:

## Configure Credentials

LabArchives issues API keys on request. Ask your institution's LabArchives site administrator or Enterprise Success Team contact to request API access, or contact [support@labarchives.com](mailto:support@labarchives.com). LabArchives provides the Access Key ID, Access Password, and the API base URL for your region.

Add your LabArchives API credentials to a `.env` file:

```env
Expand Down Expand Up @@ -96,13 +98,6 @@ with Client() as client:
page.entries.create(TextEntry, "<p>Hello from labapi!</p>")
```

This is the recommended local workflow:

1. Install `labapi[dotenv,builtin-auth]`.
2. Set `API_URL`, `ACCESS_KEYID`, and `ACCESS_PWD`.
3. Call `default_authenticate()` once the client is open.
4. Start creating or updating notebooks, folders, pages, and entries through the object model.

## Common Tasks

Authenticate in a service or callback-based app:
Expand Down Expand Up @@ -139,12 +134,12 @@ page = notebook.traverse("Experiments/2026/Results")

## Documentation Map

- [First Success Tutorial](https://nimh-dsst.github.io/labapi/latest/quick_start/tutorial.html): shortest path from install to a successful write.
- [First Success Tutorial](https://nimh-dsst.github.io/labapi/latest/quick_start/tutorial.html): install, authenticate, and create a first entry.
- [Quick Start](https://nimh-dsst.github.io/labapi/latest/quick_start/index.html): setup, navigation, page creation, uploads, and basic write operations.
- [Authentication Guide](https://nimh-dsst.github.io/labapi/latest/guide/auth.html): local browser auth, manual flows, and callback-based integration patterns.
- [Authentication Guide](https://nimh-dsst.github.io/labapi/latest/guide/auth.html): browser authentication, terminal/manual authentication, and callback URL authentication.
- [User Guide](https://nimh-dsst.github.io/labapi/latest/guide/index.html): paths, entries, API behavior, exceptions, limits, and architecture notes.
- [Examples](https://nimh-dsst.github.io/labapi/latest/examples/index.html): end-to-end scripts for real workflows.
- [FAQ](https://nimh-dsst.github.io/labapi/latest/faq.html): troubleshooting and environment questions.
- [Examples](https://nimh-dsst.github.io/labapi/latest/examples/index.html): scripts for JSON sync, folder export, and CSV table updates.
- [FAQ](https://nimh-dsst.github.io/labapi/latest/faq.html): authentication, certificate, and environment troubleshooting.

## Development

Expand Down
45 changes: 17 additions & 28 deletions docs/source/examples/csv_table.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,14 @@
CSV Table Upload/Download
=========================

This example uploads CSV data as rich-text HTML tables in LabArchives and can
download those tables back to CSV later. It is a good fit when you want
readable tables in the notebook UI without losing a machine-friendly export
path.
This example uploads a CSV file as a LabArchives rich-text HTML table and
downloads table entries back to CSV.

When to Use It
--------------

This is useful for:

- Uploading experimental data tables for visual display in notebooks.
- Creating formatted data tables that stay readable in the web interface.
- Extracting tabular data back to CSV for downstream analysis.
- Documenting datasets with consistent structure.
- Sharing tables with collaborators in a readable format.
Use it to publish CSV results in notebook pages and retrieve table entries for
downstream analysis.

Requirements
------------
Expand All @@ -44,9 +37,8 @@ You can also provide the same values through shell environment variables. See
How It Works
------------

The example is a single script. ``examples/csv_table/csv_table.py`` defines
small typed option objects, uses LabArchives page and entry APIs, and keeps
CSV/HTML conversion details inside the script.
``examples/csv_table/csv_table.py`` defines typed upload/download options,
converts CSV rows to HTML table markup, and parses table entries back to CSV.

Upload Flow
~~~~~~~~~~~
Expand Down Expand Up @@ -78,19 +70,19 @@ Upload the checked-in sample CSV file:

uv run python csv_table.py upload sample_data.csv "Experiments/Results" --notebook "My Notebook"

Upload a CSV file with every row treated as table data:
Upload a CSV file without treating the first row as a header:

.. code-block:: bash

uv run python csv_table.py upload sample_data.csv "Experiments/Results" --notebook "My Notebook" --no-header

Download the most recent table from a page:
Download the newest text entry on a page that contains an HTML table:

.. code-block:: bash

uv run python csv_table.py download "Experiments/Results" results.csv --notebook "My Notebook"

Download a specific table entry by index:
Download a table from a specific zero-based page entry index:

.. code-block:: bash

Expand Down Expand Up @@ -143,20 +135,17 @@ The script will generate this HTML table:
</tbody>
</table>

The table is displayed with LabArchives' default styling.

Notes and Limitations
---------------------

- Tables are uploaded as rich-text entries, making them readable in the
LabArchives web interface.
- Tables are rendered with LabArchives' default styling and no inline CSS.
- The script preserves table structure and can round-trip CSV to HTML and back
to CSV.
- Multiple tables on one page are supported; by default, the download uses the
most recent table.
- For simple tables, rows and columns are preserved when converting CSV to
HTML and back; leading and trailing whitespace inside cells is stripped on
download.
- Multiple table entries on one page are supported; by default, download
selects the newest text entry containing a table.
- Empty cells in CSV files are preserved in the HTML table.
- CSV files with special characters should use UTF-8 encoding.
- Save non-ASCII CSV files as UTF-8.
- Complex nested tables are not supported.
- Only the first table is extracted if an entry contains multiple tables.

Expand All @@ -170,8 +159,8 @@ Ways to Extend It
5. Generate charts from CSV data and upload them as images.
6. Support HTML table captions.

Source
------
Source Code
-----------

.. literalinclude:: ../../../examples/csv_table/csv_table.py
:language: python
Expand Down
43 changes: 17 additions & 26 deletions docs/source/examples/folder_download.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@
Folder Structure Download
=========================

This example downloads a LabArchives notebook subtree to your local computer
while preserving its directory hierarchy. Pages become folders, and individual
This example exports a notebook, folder, or page to local directories.
LabArchives directories and pages become local directories, and individual
entries are written out as separate files.

When to Use It
--------------

This is useful for:

- Creating local backups of your LabArchives notebooks.
- Exporting notebook content for offline viewing.
- Archiving completed projects.
- Migrating content to other systems.
- Version control integration for notebook content.
Use it to create local backup, offline review, archival, migration, or
version-control copies of notebook content.

Requirements
------------
Expand Down Expand Up @@ -65,17 +60,17 @@ Overwrite an existing output directory:
How It Works
------------

``examples/folder_download/folder_download.py`` contains importable download
functions plus a command-line wrapper. The reusable layer takes an authenticated
``User`` and returns a ``DownloadResult`` instead of printing or exiting.
``examples/folder_download/folder_download.py`` exposes
``download_notebook_or_folder(user, options)``, which writes the export and
returns a ``DownloadResult`` for callers.

The script mirrors the LabArchives structure:

.. code-block:: text

LabArchives Structure: Local File Structure:

My Notebook/ output/
My Notebook/ output/My Notebook/
|- Experiments/ |- Experiments/
| |- Trial 1/ (page) | |- Trial 1/
| | |- Header entry | | |- 001_header.txt
Expand Down Expand Up @@ -103,12 +98,13 @@ Downloaded entries follow this naming pattern:
- Entries are numbered in the order they appear on the page.
- Entry type is indicated in the filename.
- Attachments preserve their original filename.
- Captions are saved in separate ``*_caption.txt`` files.
- When an attachment has a caption, it is saved in a separate
``*_caption.txt`` file.

Output Layout
-------------

Each downloaded location contains:
The exported tree uses these files and subdirectories:

For pages:

Expand All @@ -117,26 +113,21 @@ For pages:

For directories:

- Subdirectories for each child directory.
- Subdirectories for each page.
- A subdirectory for each child directory or page.

Notes
-----

- The script preserves the complete directory structure.
- Filenames are sanitized to be filesystem-safe.
- Widget entries are noted but cannot be fully exported because they are
read-only.
- Large notebooks may take significant time to download.
- The script creates a ``_metadata.txt`` file for each page with additional
information.
- Widget entries are exported as ``*_widget.txt`` placeholder notes; their
content is not exported.
- Download time grows with notebook size and attachment count.

Reusable API
------------

When building your own script, import the download function and call it
directly. Most scripts only need ``DownloadFolderOptions`` and
``download_notebook_or_folder``.
Reuse the exporter by constructing ``DownloadFolderOptions`` and passing it to
``download_notebook_or_folder``:

.. code-block:: python

Expand Down
39 changes: 14 additions & 25 deletions docs/source/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
Example Applications
====================

These runnable examples show end-to-end workflows built on top of the core
``labapi`` APIs. Start with :ref:`installation` if you still need to set up the
recommended local interactive profile.
These examples show complete scripts for JSON sync, folder export, and CSV
table conversion. Start with :ref:`installation` if you still need to set up
the recommended local interactive profile.

.. toctree::
:maxdepth: 1
Expand All @@ -25,28 +25,17 @@ Example Matrix
- Best For
- Extra Packages
* - :doc:`json_sync`
- Syncing JSON attachments and previews between a local folder and a
LabArchives page
- Uploading JSON files to a page and downloading JSON attachments back to
disk
- none
* - :doc:`folder_download`
- Exporting notebook structure to local files for backup, review, or
archival
- Exporting notebook pages and entries to local files for backup or
review
- none
* - :doc:`csv_table`
- Converting CSV data to LabArchives HTML tables and round-tripping back
to CSV
- Converting CSV data to LabArchives HTML tables and back to CSV
- ``beautifulsoup4``

Published Examples
------------------

- :doc:`json_sync` synchronizes JSON files between a local folder and a single
LabArchives page.
- :doc:`folder_download` mirrors a notebook subtree to local files while
preserving page and directory structure.
- :doc:`csv_table` uploads CSV data as HTML tables and downloads those tables
back to CSV.

Getting Started
---------------

Expand All @@ -55,11 +44,11 @@ All published examples assume:
- Python 3.10+.
- The recommended local interactive profile:
``labapi[dotenv,builtin-auth]``.
- A repository-root working directory when you run the ``uv run --project ...``
commands below.
- Notebook-relative page paths paired with ``--notebook "My Notebook"``.
- Run the ``uv run --project ...`` commands below from the repository root.
- Use page paths relative to the notebook root, together with
``--notebook "My Notebook"``.

Use these sample commands as known-good starting points:
Use these sample commands as starting points:

.. code-block:: bash

Expand All @@ -71,8 +60,8 @@ Additional Local Examples
-------------------------

The repository also includes ``examples/model_logging`` and
``examples/notebook_logging``. They are maintained alongside the published
examples above, but do not yet have dedicated Sphinx pages.
``examples/notebook_logging``. They are maintained in the repository but are
not covered by these Sphinx example pages.

Related Pages
-------------
Expand Down
29 changes: 12 additions & 17 deletions docs/source/examples/json_sync.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
JSON Folder Sync
================

This example syncs JSON content between a local folder and a LabArchives page.
Use it when you want a simple batch workflow for moving structured JSON files
in or out of a notebook page.
This example uploads local ``*.json`` files to a LabArchives page and downloads
JSON attachment entries back to disk.

When to Use It
--------------

This is useful for:

- Backing up structured data from LabArchives to your local machine.
- Uploading batches of JSON data files to a LabArchives page.
- Syncing experimental data stored as JSON between local files and LabArchives.
- Archiving API responses or other structured datasets.
Use it to upload batches of JSON files, export JSON attachments for backup, or
archive JSON API responses.

Requirements
------------
Expand Down Expand Up @@ -60,17 +55,18 @@ How It Works

- JSON files are uploaded with
:meth:`~labapi.entry.collection.Entries.create_json_entry`.
- ``examples/json_sync/json_sync.py`` contains importable upload and download
functions plus a command-line ``main()`` guarded by the usual
``if __name__ == "__main__"`` check.
- ``examples/json_sync/json_sync.py`` exposes importable upload and download
functions and a CLI entry point.
- Each upload creates a JSON attachment with ``application/json`` MIME type and
a companion rich-text preview entry.
- Download mode writes each JSON attachment back to a local ``.json`` file.
- Download mode writes each JSON attachment back to a local file named after
the attachment.

Reusable API
------------

When building your own script, import the sync function and call it directly:
When building your own script, import ``upload_json_files`` and call it
directly:

.. code-block:: python

Expand All @@ -96,10 +92,9 @@ Notes and Limitations

- Invalid JSON files are skipped with an error message.
- The script creates the output folder if it does not exist during download.
- The reusable functions return a ``FileResult`` for each file they try to sync.
- The reusable functions return a ``FileResult`` for each JSON file processed,
including failures.
- The CLI handles terminal output and process exit codes.
- The sample upload command uses the checked-in files under
``examples/json_sync/sample_data``.

Ways to Extend It
-----------------
Expand Down
Loading