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#
eLabFTW content type for experiment body text. |
|
eLabFTW experiment state enumeration. |
|
Low-level client for eLabFTW API v2. |
Functions#
Get configured eLabFTW client from settings. |
API#
- exception nexusLIMS.utils.elabftw.ELabFTWError[source]#
Bases:
ExceptionBase exception for eLabFTW API errors.
- exception nexusLIMS.utils.elabftw.ELabFTWAuthenticationError[source]#
Bases:
nexusLIMS.utils.elabftw.ELabFTWErrorAuthentication failed (invalid or missing API key).
- exception nexusLIMS.utils.elabftw.ELabFTWNotFoundError[source]#
Bases:
nexusLIMS.utils.elabftw.ELabFTWErrorRequested resource not found (404).
- class nexusLIMS.utils.elabftw.ContentType[source]#
Bases:
enum.IntEnumeLabFTW content type for experiment body text.
Specifies how the body text of an experiment should be interpreted and rendered by eLabFTW.
- Variables:
- HTML#
1
- MARKDOWN#
2
- class nexusLIMS.utils.elabftw.State[source]#
Bases:
enum.IntEnumeLabFTW 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:
- Variables:
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)
metadata (dict, optional) –
Experiment metadata. Can be either:
Flat key-value pairs (simple):
{"key": "value", "number": 123}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:
- Raises:
ELabFTWAuthenticationError – If API key is invalid
ELabFTWError – If creation fails
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:
- Raises:
ELabFTWNotFoundError – If experiment doesn’t exist
ELabFTWError – If retrieval fails
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:
- Returns:
List of experiment data dicts
- Return type:
- 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:
Flat key-value pairs (simple):
{"key": "value", "number": 123}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:
- Raises:
ELabFTWNotFoundError – If experiment doesn’t exist
ELabFTWError – If update fails
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:
ELabFTWNotFoundError – If experiment doesn’t exist
ELabFTWError – If deletion fails
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:
- Returns:
Upload result data
- Return type:
- Raises:
FileNotFoundError – If file doesn’t exist
ELabFTWNotFoundError – If experiment doesn’t exist
ELabFTWError – If upload fails
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:
- 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)