Skip to content
Merged
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
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.4.8] - 2026-04-02

This release adds for version-enforcing by eLabFTW micro versions, bug fixes and some minor improvements.

### Added

- Add support for eLabFTW versions `5.3.10`-`5.5.5`
- Add `abort_minor_only` and `warn_minor_only` to `elab_strict_version_match` configuration field.
See [documentation](https://github.com/uhd-urz/elAPI?tab=readme-ov-file#advanced-configuration)
- Add ["Talks"](https://github.com/uhd-urz/elAPI/tree/dev?tab=readme-ov-file#talks-workshops-and-publications) section
to `README.md`
- Add [elAPI Plugins](https://github.com/sfb1638/elAPI_Plugins) by [SFB1638](https://github.com/sfb1638)
to [Third-party plugins/apps](https://github.com/uhd-urz/elAPI/tree/dev?tab=readme-ov-file#third-party-pluginsapps)

### Fixed

- Fixed a bug where the whoami command wouldn't work with old-style API tokens (GH #175, reported by @Cs137)

## [2.4.7] - 2025-12-10

This release adds support for eLabFTW micro versions `5.3.8`, `5.3.9` and some bug fixes.
Expand All @@ -17,7 +35,6 @@ This release adds support for eLabFTW micro versions `5.3.8`, `5.3.9` and some b

- Fix a bill-teams issue [GL 63](https://gitlab.urz.uni-heidelberg.de/urz-elabftw/elapi/-/issues/63).


## [2.4.6] - 2025-11-12

This is a hotpatch release. See the **version 2.4.5 changelog below** for the main changes.
Expand Down
99 changes: 68 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
</a>
<a href="#compatibility">
<img alt="Static Badge" src="https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-%230d7dbe">
<img alt="Static Badge" src="https://img.shields.io/badge/eLabFTW%20support-5.1%20%7C%205.2%20%7C%205.3+-%2323b3be">
<img alt="Static Badge" src="https://img.shields.io/badge/eLabFTW%20support-5.1%20%7C%205.2%20%7C%205.3%20%7C%205.4%20%7C%205.5+-%2323b3be">
</a>
<a href="#talks-workshops-and-publications">
<img alt="Static Badge" src="https://img.shields.io/badge/DOI-10.11588%2FDATA%2FE4XHXZ-blue?style=plastic&link=https%3A%2F%2Fdoi.org%2F10.11588%2FDATA%2FE4XHXZ">
</a>
</p>

Expand All @@ -30,10 +33,10 @@ From [the API documentation](https://doc.elabftw.net/api/v2/#/Users/read-user):
With elAPI you can do the following:

```sh
$ elapi get experiments --format csv --export ~/Downloads/
elapi get experiments --format csv --export ~/Downloads/
```

Once the command is run, in the background, elAPI will read host (eLab server) address, API key and various other
Once the command is run, in the background, elAPI will read host (eLab server) address, API key, and various other
settings (see [configuration](#configuration)) from the configuration file `elapi.yml`, perform validation (e.g.,
whether the server address is valid), fetch all _experiments_ list, convert them to `CSV`, and export them to your
local `~/Downloads/` folder.
Expand All @@ -46,7 +49,7 @@ install packages in isolated virtual environments, so elAPI installed as a CLI t
installed inside other virtual environments.

```shell
$ uv tool install elapi
uv tool install elapi
# elAPI can be updated to the latest version with
# uv tool upgrade elapi
```
Expand Down Expand Up @@ -79,7 +82,7 @@ Once you have elAPI [installed](#installation), to **quickly** get started, run
questions about your eLabFTW server with examples to help you fill in the answers. Here's a demo:

```shell
$ elapi init
elapi init
```

<video src='https://github.com/user-attachments/assets/8d5f69ed-b644-4d75-b816-d06d4e937105'> </video>
Expand All @@ -93,7 +96,9 @@ your configuration details.

elAPI is compatible with the following Python versions: `3.11`, `3.12`, `3.13`, `3.14`. elAPI supports
the [eLabFTW REST API v2](https://doc.elabftw.net/api/v2/), and can be used with the following eLabFTW
versions: `5.3.9`, `5.3.8`, `5.3.7`, ```5.3.6`, `5.3.5`, `5.3.4`, `5.3.3`, `5.3.2`, `5.3.1`, `5.3.0`, `5.2.8`, `5.2.7`, `5.2.6`, `5.2.5`, `5.2.4`,
versions: `5.5.5`, `5.5.4`, `5.5.3`, `5.5.2`, `5.5.1`, `5.5.0`, `5.4.6`, `5.4.5`, `5.4.4`, `5.4.3`, `5.4.2`, `5.4.1`,
`5.4.0`, `5.3.11`, `5.3.10`, `5.3.9`, `5.3.8`, `5.3.7`, `5.3.6`,
`5.3.5`, `5.3.4`, `5.3.3`, `5.3.2`, `5.3.1`, `5.3.0`, `5.2.8`, `5.2.7`, `5.2.6`, `5.2.5`, `5.2.4`,
`5.2.3`, `5.2.2`, `5.2.1`, `5.2.0`, `5.1.1`.

### elAPI strict version support
Expand Down Expand Up @@ -136,7 +141,7 @@ host: <host API url>
api_token: <token with at least read-access>
# "A.k.a API key". You can generate an API token from eLabFTW user panel -> API keys tab.
export_dir: ~/Downloads/elAPI
elab_strict_version_match: "warn"
elab_strict_version_match: "warn_minor_only"
unsafe_api_token_warning: true
enable_http2: false
verify_ssl: true
Expand All @@ -153,12 +158,20 @@ development_mode: false
- `elab_strict_version_match` controls what elAPI should do if an unsupported eLabFTW version is detected. eLabFTW does
introduce breaking API change from time to time. Starting from elAPI 2.4.5, elAPI maintains [a strict set of eLabFTW
versions](#compatibility), i.e., elAPI and its plugins are expected to work for these versions. This is to prevent
unexpected behavior due to the breaking changes. If the detected eLabFTW server version is not supported, elAPI by
default (`elab_strict_version_match: warn`) will throw a warning
message and continue to run any command/plugin. When `elab_strict_version_match` is set to `abort`, elAPI will show an
`ERROR`
message and abort immediately. When `elab_strict_version_match` is set to `yolo`, elAPI will ignore any version
support conflict.
unexpected behavior due to the breaking changes. If the detected eLabFTW server majo.minor version is not supported,
elAPI by default (`elab_strict_version_match: warn_minor_only`) will throw a warning
message and continue normally. `elab_strict_version_match` currently accepts the following
modes/values:
- `abort`: elAPI will show an `ERROR` message and abort immediately.
- `abort_minor_only`: elAPI will ignore the eLabFTW version patch number in _major.minor.patch_ version (
e.g., `1` is the patch number in version `5.5.1`). If the _major.minor_ version isn't
supported, elAPI will abort immediately.
- `warn`: elAPI will show an `WARNING` message and continue normally.
- `warn_minor_only`: The **default**. elAPI will ignore the eLabFTW version patch number in _major.minor.patch_
version (
e.g., `1` is the patch number in version `5.5.1`). If the _major.minor_ version isn't
supported, elAPI will show a warning and continue normally.
- `yolo`: elAPI will ignore any version support conflict.
- `enable_http2` enables HTTP/2 protocol support which by default is turned off. Be aware
of [known issues](https://github.com/encode/httpx/discussions/2112) with HTTP/2 if you are making async requests with
a heavy load.
Expand All @@ -183,7 +196,7 @@ You can get an overview of detected configuration with `elapi show-config`. `sho
which configuration values are actually used by elAPI – especially if you are working with multiple configuration files.

```shell
$ elapi show-config # host username: "culdesac"
elapi show-config # host username: "culdesac"
```

![elAPI show-config output](https://heibox.uni-heidelberg.de/f/00a8dabbf2124087aae4/?dl=1)
Expand All @@ -206,7 +219,7 @@ juggling between multiple API keys can still lead to confusion as to which API k
`2.4.1` adds the `whomai` command that shows the essential information about the requesting eLab user.

```shell
$ elapi whoami
elapi whoami
```

![elapi whoami output](https://heibox.uni-heidelberg.de/f/e3096d5659db45e58a94/?dl=1)
Expand All @@ -230,7 +243,7 @@ Check out the [examples directory](https://github.com/uhd-urz/elAPI/tree/main/ex
examples with elAPI. elAPI CLI usage details can be displayed with:

```shell
$ elapi --help
elapi --help

```

Expand All @@ -239,21 +252,21 @@ $ elapi --help
Request an overview of a running eLabFTW server:

```shell
$ elapi get info -F yml
elapi get info -F yml
# Here -F (or --format) defines the output format
```

You can request a list o all active experiments and export it to a `JSON` file.

```shell
$ elapi get experiments --export ~/Downoads/experiments.json
elapi get experiments --export ~/Downoads/experiments.json
```

Enable built-in syntax highlighting with `--highlight` or `-H`. Here, the following command will fetch team information
of the team with team ID 1.

```shell
$ elapi get -H teams --id 1
elapi get -H teams --id 1
```

elAPI runs a weak endpoint name validation against your eLabFTW API version. Run `elapi get --help` to see the
Expand All @@ -266,42 +279,42 @@ supported endpoint names for your eLabFTW server:
Create a new user by the name 'John Doe':

```shell
$ elapi post users --id <user id> -d '{"firstname": "John", "lastname": "Doe", "email": "test_test@itnerd.de"}'
elapi post users --id <user id> -d '{"firstname": "John", "lastname": "Doe", "email": "test_test@itnerd.de"}'
```

### `PATCH` requests

Update an existing user's email address:

```shell
$ elapi patch users --id <user id> -d '{"email": "new_email@itnerd.de"}'
elapi patch users --id <user id> -d '{"email": "new_email@itnerd.de"}'
```

`patch` command allows us to make changes to eLabFTW server settings. E.g., you can update the time (in minutes)
after which the authentication cookie will expire.

```shell
$ elapi patch config -d '{"cookie_validity_time": 43200}'
elapi patch config -d '{"cookie_validity_time": 43200}'
```

You can publish an announcement to all the members.

```shell
$ elapi patch config -d '{"announcement": "Notice: Server will be down tomorrow at midnight due to scheduled maintenance."}'
elapi patch config -d '{"announcement": "Notice: Server will be down tomorrow at midnight due to scheduled maintenance."}'
```

### `DELETE` requests

Delete all the tags associated with an experiment:

```shell
$ elapi delete experiments -i <experiment ID> --sub tags
elapi delete experiments -i <experiment ID> --sub tags
```

You can reset the configuration to default values.

```shell
$ elapi delete config
elapi delete config
```

### `experiments` built-in plugin
Expand All @@ -310,28 +323,28 @@ $ elapi delete config
to `~/Downloads` directory.

```shell
$ elapi experiments get -i <experiment unique elabid> -F pdf --export ~/Downloads/
elapi experiments get -i <experiment unique elabid> -F pdf --export ~/Downloads/
```

Append text in Markdown to an existing experiment by its ID:

```shell
$ elapi experiments append --id <experiment ID> -M -t "**New content.**"
elapi experiments append --id <experiment ID> -M -t "**New content.**"
```

You can also upload an attachment to an experiment.

```shell
$ elapi experiments upload-attachment --id <experiment ID> --path <path to attachment file> --comment <comment for your attachment>
elapi experiments upload-attachment --id <experiment ID> --path <path to attachment file> --comment <comment for your attachment>
```

### `mail` built-in plugin

Sometimes when a script has finished, you and your team would want to receive an email about its success/failure. elAPI
offers a no-code solution for this: the `mail` plugin. The `mail` plugin is not enabled by default. To enable it,
install elAPI with the optional dependency `mail`: `pip install elapi[mail]` or `uv add elapi[mail]`. [__See the wiki__](https://github.com/uhd-urz/elAPI/wiki/mail-plugin)
to read more about how to configure the `mail` plugin with your
mail server configuration and trigger conditions. In a
install elAPI with the optional dependency `mail`: `pip install elapi[mail]` or `uv add elapi[mail]`.
[__See the wiki__](https://github.com/uhd-urz/elAPI/wiki/mail-plugin) to read more about how to configure the `mail`
plugin with your mail server configuration and trigger conditions. In a
nutshell, the `mail` plugin will scan the logs when a script/plugin is done to look for pre-configured trigger
conditions, and if found, it will send an email. The trigger conditions can be atomic and scope-based, i.e., an email
can be sent only when a specific plugin task/command is finished, and/or when a matching log state and/or a matching log
Expand Down Expand Up @@ -399,3 +412,27 @@ project_dir: ~/awesome # Path to the project root directory where the plugin is
This metadata file of plugin `awesome` must be placed inside `~/.local/share/elapi/plugins/awesome`. Notice, the plugin
name must also match the parent directory name of `elapi_plugin_metadata.yml`. This way we ensure a plugin name remains
unique.

## Talks, workshops, and publications

elAPI was presented/discussed in the following talks and workshops at various conferences and meetups:

1. [Automation in eLabFTW](https://www.fdm.nrw/wp-content/uploads/2025/06/Program_FDMWerkstatt_2024.pdf) at
FDM-Werkstatt 2024, RWTH Aachen University by [fdm.nrw](https://www.fdm.nrw/)
2. [elAPI 2.0 (Third-party plugins)](https://www.uni-muenster.de/Forschungsdaten/en/angebote/veranstaltungen/#top) at
eLab training 2024, University of Münster by [fdm.nrw](https://www.fdm.nrw/)
3. [Boost your productivity: Exploring eLabFTW's API live](https://web.archive.org/web/20240712155250/https://www.uni-marburg.de/en/hefdi/hefdi-data-event/hefdi-data-week-2024#hefdi-data-week-programme-overview)
at HeFDI Data Week 2024, Online
4. [elAPI](https://www.youtube.com/watch?v=UrX7a-IgGnI)
at [eLabFTW Community Meeting III](https://www.deltablot.com/posts/community-meeting-3/)
by [eLabFTW](https://github.com/elabftw/elabftw)
5. elAPI [poster](https://archiv.ub.uni-heidelberg.de/volltextserver/36226/3/elAPI_Poster_E-Science-Tage_2025.pdf)
and [paper](https://books.ub.uni-heidelberg.de/heibooks/catalog/book/1652/chapter/23952)
at [E-Science-Tage 2025](https://e-science-tage.de/en/programme-2025) by Heidelberg University, Germany

## Third-party plugins/apps

1. [elAPI Plugins](https://github.com/sfb1638/elAPI_Plugins): elAPI Plugins is a desktop application for bulk importing
and exporting resources and experiments in eLabFTW instances. The project is developed as part of the INF Project of
[CRC 1638](https://www.sfb1638.de/) at
the [Heidelberg University Biochemistry Center (BZH)](https://bzh.db-engine.de/).
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
# For date information to create folders
import calendar
from datetime import datetime

# To catch JSONDecodeError when parsing experiment metadata
from json import JSONDecodeError
from pathlib import Path
Expand All @@ -58,18 +59,21 @@

# For handling HTTP connections
from elapi.api import FixedEndpoint

# For logging
from elapi.loggers import Logger

# For handling paths (An extension of Python pathlib's Path)
from elapi.path import ProperPath

# For terminating the program
from elapi.validators import Exit
# For making sure we have the appropriate permission
from elapi.validators import (
Validate,
ValidationError,
Exit,
HostIdentityValidator,
PathValidator,
Validate,
ValidationError,
)

# First we create a FixedEndpoint instance with the endpoint of our interest "experiments" as its only argument.
Expand Down Expand Up @@ -113,7 +117,7 @@ def get_all_experiments_data() -> List[dict]:
)
raise Exit(1)
expected_limit = offset = len(all_experiments_data)
continuous_batch = []
continuous_batch: list[dict] = []
while len(continuous_batch) != 0:
continuous_batch_response = experiment_endpoint.get(
endpoint_id=None, query={"offset": offset, **default_query}
Expand Down
28 changes: 10 additions & 18 deletions examples/python/manage_teams/expire_teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@
# 3. We iterate over each user data and check if the user "teams" field contains the target team ID
# we want to expire. If it does, that indicates the user does belong to the target team.
# 4. We PATCH the user with the new expiry date
from json import JSONDecodeError

import asyncio

from elapi.api import PATCHRequest, GlobalSharedSession
from elapi.api import GETRequest, GlobalSharedSession, PATCHRequest
from elapi.loggers import Logger
from elapi.plugins.commons import RecursiveInformation

# commons is a plugin with some helpful CLI functions, but commons plugin itself does not come with a CLI
from elapi.validators import Validate, PermissionValidator, HostIdentityValidator
from elapi.validators import HostIdentityValidator, PermissionValidator, Validate

logger = Logger() # Handles logging to elAPI log file and to STDERR

Expand All @@ -55,21 +54,13 @@
validate()

with GlobalSharedSession():
patch = PATCHRequest() # the connection is not open yet!
get, patch = GETRequest(), PATCHRequest() # the connection is not open yet!
TARGET_TEAM_ID = "95" # ID of the team to expire.
EXPIRY_DATE = "3001-01-01" # the new expiry date to set for target users.
try:
users_information = asyncio.run(
RecursiveInformation(
endpoint_name="users", endpoint_id_key_name="userid"
).items() # verbose=False will disable the progress bar
# RecursiveInformation().items() method asynchronously fetches a list of dictionaries,
# where each dictionary correspondents to a single user data.
)
except (RuntimeError, InterruptedError) as e:
raise InterruptedError(
"Getting users data was not successful."
) from e # elAPI handles most of the cleanup already.
users_information = get("users").json()
except JSONDecodeError as e:
raise RuntimeError("Getting users data was not successful.") from e

for user in users_information:
if len(user["teams"]) > 1:
Expand All @@ -87,5 +78,6 @@
data={"valid_until": EXPIRY_DATE},
) # the connection opens here
logger.info(
f"An expiration date for the user with user ID {user['userid']} has been successfully set."
f"An expiration date for the user with user ID {user['userid']} "
f"has been successfully set."
)
2 changes: 1 addition & 1 deletion mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ printf "Downloading vendor packages with vendy..."
printf "\n"
printf "_________________________________________"
printf "\n\n"
/Users/culdesac/Workshop/elapi/.venv/bin/python -m vendy
.venv/bin/python -m vendy
printf "\n"
printf "Removing unnecessary haggis files/folder..."
printf "\n"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "elapi"
version = "2.4.7"
version = "2.4.8"
description = "elAPI is a powerful, extensible API client for eLabFTW."
authors = [{ name = "Alexander Haller, Mahadi Xion", email = "elabftw@uni-heidelberg.de" }]
requires-python = ">=3.11.0,<4"
Expand Down
Loading