nexusLIMS.utils.elabftw#

Low-level API client for eLabFTW electronic lab notebook.

This module provides a reusable client for interacting with eLabFTW’s REST API v2. It handles authentication, request/response formatting, and error handling for CRUD operations on experiments.

eLabFTW API Documentation: https://doc.elabftw.net/api/v2/

Example usage: >>> from nexusLIMS.utils.elabftw import get_elabftw_client >>> client = get_elabftw_client() >>> exp = client.create_experiment( … title=”My Experiment”, … body=”Experiment description”, … tags=[“microscopy”, “nexuslims”] … ) >>> print(f”Created experiment {exp[‘id’]}”)

Module Contents#

Classes#

ContentType

eLabFTW content type for experiment body text.

State

eLabFTW experiment state enumeration.

ELabFTWClient

Low-level client for eLabFTW API v2.

Functions#

get_elabftw_client

Get configured eLabFTW client from settings.

API#

exception nexusLIMS.utils.elabftw.ELabFTWError[source]#

Bases: Exception

Base exception for eLabFTW API errors.

exception nexusLIMS.utils.elabftw.ELabFTWAuthenticationError[source]#

Bases: nexusLIMS.utils.elabftw.ELabFTWError

Authentication failed (invalid or missing API key).

exception nexusLIMS.utils.elabftw.ELabFTWNotFoundError[source]#

Bases: nexusLIMS.utils.elabftw.ELabFTWError

Requested resource not found (404).

class nexusLIMS.utils.elabftw.ContentType[source]#

Bases: enum.IntEnum

eLabFTW content type for experiment body text.

Specifies how the body text of an experiment should be interpreted and rendered by eLabFTW.

Variables:
  • HTML (int) – Body text is HTML formatted (value: 1, default in eLabFTW)

  • MARKDOWN (int) – Body text is Markdown formatted (value: 2)

HTML#

1

MARKDOWN#

2

class nexusLIMS.utils.elabftw.State[source]#

Bases: enum.IntEnum

eLabFTW experiment state enumeration.

These states represent the lifecycle status of experiments in eLabFTW. Values correspond to the eLabFTW database schema.

Variables:
  • Normal (int) – Standard active experiment (value: 1)

  • Archived (int) – Experiment has been archived (value: 2)

  • Deleted (int) – Experiment has been soft-deleted (value: 3)

  • Pending (int) – Experiment is pending approval or processing (value: 4)

  • Processing (int) – Experiment is currently being processed (value: 5)

  • Error (int) – Experiment encountered an error state (value: 6)

Normal#

1

Archived#

2

Deleted#

3

Pending#

4

Processing#

5

Error#

6

class nexusLIMS.utils.elabftw.ELabFTWClient(base_url: str, api_key: str)[source]#

Low-level client for eLabFTW API v2.

This client provides basic CRUD operations for eLabFTW experiments using the REST API v2. It handles authentication via API key and provides consistent error handling.

Parameters:
  • base_url (str) – Root URL of the eLabFTW instance (e.g., “https://elabftw.example.com”). Do not include the API path - it will be appended automatically.

  • api_key (str) – API key from eLabFTW user panel. Must have write permissions for creating/updating experiments.

Variables:
  • base_url (str) – Root URL of eLabFTW instance

  • api_key (str) – API authentication key

  • experiments_endpoint (str) – Full URL to experiments API endpoint

Examples:

>>> client = ELabFTWClient(
...     base_url="https://elabftw.example.com",
...     api_key="your-api-key-here"
... )
>>> experiments = client.list_experiments(limit=5)
>>> for exp in experiments:
...     print(f"{exp['id']}: {exp['title']}")
create_experiment(title: str, body: str | None = None, tags: list[str] | None = None, metadata: dict[str, Any] | None = None, category: int | None = None, status: int | None = None, content_type: ContentType | None = None) dict[str, Any][source]#

Create a new experiment in eLabFTW.

Parameters:
  • title (str) – Experiment title (required)

  • body (str, optional) – Experiment body content (supports markdown)

  • tags (list of str, optional) – List of tag strings to apply

  • metadata (dict, optional) –

    Experiment metadata. Can be either:

    1. Flat key-value pairs (simple): {"key": "value", "number": 123}

    2. eLabFTW extra_fields schema (recommended): {     "extra_fields": {         "Field Name": {             "type": "text|date|datetime-local|email|number|url|...",             "value": "field value",             "description": "Optional description",             "position": 1,             "group_id": 1,             ...         },         ...     },     "elabftw": {         "display_main_text": true,         "extra_fields_groups": [             {"id": 1, "name": "Group Name"},             ...         ]     } }

    For extra_fields schema details, see: https://doc.elabftw.net/metadata.html#schema-description

  • category (int, optional) – Category ID (uses eLabFTW default if not specified)

  • status (int, optional) – Status ID (uses eLabFTW default if not specified)

  • content_type (ContentType, optional) – Content type for body text (HTML or MARKDOWN). Defaults to eLabFTW’s default (HTML) if not specified.

Returns:

Created experiment data including ‘id’ field

Return type:

dict

Raises:

Examples:

Simple metadata (flat key-value pairs):

>>> from nexusLIMS.utils.elabftw import ContentType
>>> exp = client.create_experiment(
...     title="TEM Analysis",
...     body="Sample characterization with TEM",
...     tags=["microscopy", "analysis"],
...     metadata={"instrument": "FEI Titan", "operator": "jsmith"}
... )
>>> print(f"Created experiment ID: {exp['id']}")

With Markdown body:

>>> exp = client.create_experiment(
...     title="TEM Analysis",
...     body=(
...         "## Sample Analysis\\n\\n- **Sample**: Steel alloy\\n"
...         "- **Method**: TEM imaging"
...     ),
...     content_type=ContentType.MARKDOWN,
...     tags=["microscopy"]
... )
>>> print(f"Created experiment ID: {exp['id']}")

Structured extra_fields (recommended):

>>> exp = client.create_experiment(
...     title="TEM Analysis",
...     metadata={
...         "extra_fields": {
...             "Instrument": {
...                 "type": "text",
...                 "value": "FEI Titan",
...                 "description": "Instrument used",
...                 "position": 1,
...                 "group_id": 1
...             },
...             "Start Time": {
...                 "type": "datetime-local",
...                 "value": "2025-01-27T10:30",
...                 "description": "Session start time",
...                 "position": 2,
...                 "group_id": 1
...             },
...             "CDCS Record": {
...                 "type": "url",
...                 "value": "https://cdcs.example.com/record/123",
...                 "description": "Link to related CDCS record",
...                 "position": 3,
...                 "group_id": 2
...             }
...         },
...         "elabftw": {
...             "display_main_text": True,
...             "extra_fields_groups": [
...                 {"id": 1, "name": "Session Information"},
...                 {"id": 2, "name": "Related Records"}
...             ]
...         }
...     }
... )
get_experiment(experiment_id: int) dict[str, Any][source]#

Retrieve an experiment by ID.

Parameters:

experiment_id (int) – Experiment ID to retrieve

Returns:

Full experiment data. Note that the ‘tags’ field is automatically converted from eLabFTW’s pipe-separated string format to a list of strings for convenience.

Return type:

dict

Raises:

Examples:

>>> exp = client.get_experiment(42)
>>> print(exp['title'])
>>> print(exp['tags'])  # ['tag1', 'tag2', 'tag3']
list_experiments(limit: int = 15, offset: int = 0, query: str | None = None) list[dict[str, Any]][source]#

List experiments with pagination and optional search.

Parameters:
  • limit (int, optional) – Maximum number of results to return (default: 15)

  • offset (int, optional) – Number of results to skip (for pagination) (default: 0)

  • query (str, optional) – Full-text search query

Returns:

List of experiment data dicts

Return type:

list of dict

Raises:

ELabFTWError – If listing fails

Examples:

>>> # Get first 10 experiments
>>> experiments = client.list_experiments(limit=10)
>>>
>>> # Search for experiments
>>> results = client.list_experiments(query="microscopy")
>>>
>>> # Pagination
>>> page2 = client.list_experiments(limit=10, offset=10)
update_experiment(experiment_id: int, title: str | None = None, body: str | None = None, tags: list[str] | None = None, metadata: dict[str, Any] | None = None, category: int | None = None, status: int | None = None) dict[str, Any][source]#

Update an existing experiment.

Only fields provided as arguments will be updated. Other fields remain unchanged.

Parameters:
  • experiment_id (int) – ID of experiment to update

  • title (str, optional) – New title

  • body (str, optional) – New body content

  • tags (list of str, optional) – New tag list (replaces existing tags)

  • metadata (dict, optional) –

    New metadata (replaces existing metadata). Can be either:

    1. Flat key-value pairs (simple): {"key": "value", "number": 123}

    2. eLabFTW extra_fields schema (recommended): See create_experiment() for full schema documentation.

    For extra_fields schema details, see: https://doc.elabftw.net/metadata.html#schema-description

  • category (int, optional) – New category ID

  • status (int, optional) – New status ID

Returns:

Updated experiment data

Return type:

dict

Raises:

Examples:

Update title only:

>>> client.update_experiment(42, title="New Title")

Update multiple fields with flat metadata:

>>> client.update_experiment(
...     42,
...     body="Updated description",
...     tags=["new-tag"],
...     metadata={"updated": "2025-01-31"}
... )

Update with extra_fields schema:

>>> client.update_experiment(
...     42,
...     metadata={
...         "extra_fields": {
...             "Status": {
...                 "type": "text",
...                 "value": "Completed",
...                 "description": "Experiment status",
...                 "position": 1
...             }
...         },
...         "elabftw": {"display_main_text": True}
...     }
... )
delete_experiment(experiment_id: int) None[source]#

Delete an experiment.

Note: This is a soft delete in eLabFTW - the experiment is marked as deleted but can be restored by administrators.

Parameters:

experiment_id (int) – ID of experiment to delete

Raises:

Examples:

>>> client.delete_experiment(42)
upload_file_to_experiment(experiment_id: int, file_path: Path | str, comment: str | None = None) dict[str, Any][source]#

Upload a file as attachment to an experiment.

Parameters:
  • experiment_id (int) – ID of experiment to attach file to

  • file_path (Path or str) – Path to file to upload

  • comment (str, optional) – Comment/description for the uploaded file

Returns:

Upload result data

Return type:

dict

Raises:

Examples:

>>> result = client.upload_file_to_experiment(
...     experiment_id=42,
...     file_path="data.xml",
...     comment="NexusLIMS XML record"
... )
nexusLIMS.utils.elabftw.get_elabftw_client() ELabFTWClient[source]#

Get configured eLabFTW client from settings.

Convenience function that creates a client using credentials from the NexusLIMS configuration.

Returns:

Configured client instance

Return type:

ELabFTWClient

Raises:

ValueError – If NX_ELABFTW_API_KEY or NX_ELABFTW_URL not configured

Examples:

>>> from nexusLIMS.utils.elabftw import get_elabftw_client
>>> client = get_elabftw_client()
>>> experiments = client.list_experiments(limit=10)