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
8 changes: 3 additions & 5 deletions docs/source/dev/plugin_structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ This is necessary for collection of provenance information.
The class structure of a process plugin should look like this:

```{code-block} python
from typing import Union

from hermes.commands.process.base import HermesProcessCommand, HermesProcessPlugin, ObjectStrategies
from hermes.model.merge.action import MergeAction
from pydantic import BaseModel
Expand Down Expand Up @@ -176,7 +174,7 @@ The returned object may be the object `metadata` passed to `__call__`.
The class structure of a deposit plugin should look like this:

```{code-block} python
from hermes.commands.deposit.base import BaseDepositPlugin
from hermes.commands.deposit.base import HermesDepositPlugin
from hermes.model import SoftwareMetadata
from pydantic import BaseModel

Expand All @@ -186,7 +184,7 @@ class YourDepositSettings(BaseModel):
pass


class YourDepositPlugin(BaseDepositPlugin):
class YourDepositPlugin(HermesDepositPlugin):
settings_class = YourDepositSettings

def prepare(self) -> None:
Expand Down Expand Up @@ -234,7 +232,7 @@ class YourDepositPlugin(BaseDepositPlugin):

A deposit plugin doesn't implement a `__call__` method like plugins for other steps.
Instead it can (and in some cases has to) implement methods, which will be called in a predefined order.
For information on the order and the purpose of a single function see {py:class}`~hermes.commands.deposit.base.BaseDepositPlugin`.
For information on the order and the purpose of a single function see {py:class}`~hermes.commands.deposit.base.HermesDepositPlugin`.

The plugin still has access to the command (via `self.command`) and the metadata for the software (via `self.metadata`).

Expand Down
4 changes: 2 additions & 2 deletions docs/source/dev/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ This is not necessary if you only want to use HERMES or want to develop an exten

## Prepare your environment

First, install Python 3.10 (or later).
First, install Python 3.11 (or later).

Additionally, you need to [install `poetry >= 1.2.0`](https://python-poetry.org/docs/#installation), either globally, or
Additionally, you need to [install `poetry >= 2.0.0`](https://python-poetry.org/docs/#installation), either globally, or
within an environment of your choice. As a project, we chose `poetry` to manage our dependencies, builds, and deposits
as a state of the art solution within the Python ecosystem.

Expand Down
23 changes: 23 additions & 0 deletions docs/source/tutorials/publish-your-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
SPDX-FileCopyrightText: 2026 German Aerospace Center (DLR)

SPDX-License-Identifier: CC-BY-SA-4.0
-->

<!--
SPDX-FileContributor: Michael Fritzsche
-->

# Publish your own HERMES plugin

To publish your plugin to the [marketplace](./../index.md#plugins), you first need to publish it to [PyPi](https://pypi.org/) or a public git repository.

Publishing to PyPi can be done following [this tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/) while creating a git repository can be created like [this](https://docs.github.com/en/repositories/creating-and-managing-repositories/quickstart-for-repositories) or [this](https://docs.gitlab.com/user/project/).

Next create a new issue in the [HERMES repository](https://github.com/softwarepub/hermes) by going to the section [issues](https://github.com/softwarepub/hermes/issues), then click `New issue` and after that choose `Add Plugin to Marketplace`.
Fill out the form and hit `Create`.

Now you can sit back and wait until an author adds your plugin or gets back to you.
This might take some time, please be patient, we are humans too.

After your plugin has been published, you should find it [here](../index.md#plugins).
23 changes: 23 additions & 0 deletions docs/source/tutorials/write-your-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
SPDX-FileCopyrightText: 2026 German Aerospace Center (DLR)

SPDX-License-Identifier: CC-BY-SA-4.0
-->

# Write your own HERMES plugin

To write your own HERMES plugin, you can follow one of the following guides, dependending on the step the plugin is for:

Write your own...
```{toctree}
:glob:
:maxdepth: 1
writing_plugin_tutorials/writ*
```

General information on the structure of the plugins can be found [here](./../dev/plugin_structure.md).

# Sharing your work

If you already wrote your plugin, please consider publishing it to the [marketplace](./../index.md#plugins).
You can do that following [this](./publish-your-plugin.md) tutorial.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!--
SPDX-FileCopyrightText: 2026 German Aerospace Center (DLR)

SPDX-License-Identifier: CC-BY-SA-4.0
-->

<!--
SPDX-FileContributor: Michael Fritzsche
-->

# Curate plugin

In this tutorial we are going to write a curate plugin called `censor_author_emails` that deletes all author email in the curate step.
For simplicity's sake our plugin will only do this, but extending it to do more will be easy.

## Setup

To follow this tutorial you'll need to have HERMES with version >=0.10 installed.
You can install it like this:

First, install Python 3.11 (or later).

Additionally, you need to [install `poetry >= 2.0.0`](https://python-poetry.org/docs/#installation), either globally, or
within an environment of your choice. As a project, we chose `poetry` to manage our dependencies, builds, and deposits
as a state of the art solution within the Python ecosystem.

In case you still want to install on your machine, you can (for example) use `pip`:

```shell
pip install hermes
```

## Writing the plugin

First we'll start with a new python file that contains the following code:

```{code-block} python
from hermes.commands.curate.base import HermesCurateCommand, HermesCuratePlugin
from hermes.model import SoftwareMetadata
from pydantic import BaseModel


class RedactCurateSettings(BaseModel):
pass


class RedactCuratePlugin(HermesCuratePlugin):
settings_class = YourCurateSettings

def __call__(self, command: HermesCurateCommand, metadata: SoftwareMetadata) -> SoftwareMetadata:
data = SoftwareMetadata()

return data
```

First let's add a setting to our plugin that specifies with what the emails should be replaced.
To do that we have to modify `RedactCurateSettings` like this:

```{code-block} python
:emphasize-lines: 7
from hermes.commands.curate.base import HermesCurateCommand, HermesCuratePlugin
from hermes.model import SoftwareMetadata
from pydantic import BaseModel


class RedactCurateSettings(BaseModel):
redact_with: str = "_REDACTED_"


class RedactCuratePlugin(HermesCuratePlugin):
settings_class = YourCurateSettings

def __call__(self, command: HermesCurateCommand, metadata: SoftwareMetadata) -> SoftwareMetadata:
data = SoftwareMetadata()

return data
```

By doing this we named our setting `redact_with` and let pydantic enforce that its value is a string.
It also has a default value, `"_REDACTED_"`.

Now we only have to replace all author emails.

That can be achieved for example like this:

```{code-block} python
:emphasize-lines: 13-17
from hermes.commands.curate.base import HermesCurateCommand, HermesCuratePlugin
from hermes.model import SoftwareMetadata
from pydantic import BaseModel


class RedactCurateSettings(BaseModel):
redact_with: str = "_REDACTED_"


class RedactCuratePlugin(HermesCuratePlugin):
settings_class = YourCurateSettings

def __call__(self, command: HermesCurateCommand, metadata: SoftwareMetadata) -> SoftwareMetadata:
redact_with = command.settings.censor_author_emails.redact_with
for author in metadata.get("schema:author", []):
if "schema:email" in author:
author["schema:email] = len(author["schema:email"]) * [redact_with]

return metadata
```

## Configuring HERMES to use your plugin

Now use the build tool of your choice to build the python package containing your plugin, so that you can import it.
Suppose in your project you want to use HERMES your plugin class is available as `redact_plugin.RedactProcessPlugin`.

Then in this projects `pyproject.toml`, you have to add `hermes` as a dependency as well as adding `redact_plugin:RedactProcessPlugin` as an entrypoint named `censor_author_emails` for `"hermes.harvest"`.

For HERMES to use our plugin when harvesting, just add `"censor_author_emails"` as the plugin to be used inside of your `hermes.toml` like this:

```{code-block}
[curate]
plugin = "censor_author_emails"
```
Loading
Loading