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
2 changes: 1 addition & 1 deletion src/hermes/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# from hermes.commands.base import HermesVersionCommand
# from hermes.commands.clean.base import HermesCleanCommand
# from hermes.commands.init.base import HermesInitCommand
# from hermes.commands.curate.base import HermesCurateCommand
from hermes.commands.curate.base import HermesCurateCommand
from hermes.commands.harvest.base import HermesHarvestCommand
# from hermes.commands.process.base import HermesProcessCommand
# from hermes.commands.deposit.base import HermesDepositCommand
Expand Down
4 changes: 2 additions & 2 deletions src/hermes/commands/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# from hermes.commands import (HermesHelpCommand, HermesVersionCommand, HermesCleanCommand,
# HermesHarvestCommand, HermesProcessCommand, HermesCurateCommand,
# HermesDepositCommand, HermesPostprocessCommand, HermesInitCommand)
from hermes.commands import HermesHarvestCommand
from hermes.commands import HermesCurateCommand, HermesHarvestCommand
from hermes.commands.base import HermesCommand


Expand Down Expand Up @@ -44,7 +44,7 @@ def main() -> None:
# HermesCleanCommand(parser),
HermesHarvestCommand(parser),
# HermesProcessCommand(parser),
# HermesCurateCommand(parser),
HermesCurateCommand(parser),
# HermesDepositCommand(parser),
# HermesPostprocessCommand(parser),
):
Expand Down
38 changes: 22 additions & 16 deletions src/hermes/commands/curate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
# SPDX-FileContributor: Michael Meinel

import argparse
import os
import shutil
import sys

from pydantic import BaseModel

from hermes.commands.base import HermesCommand
from hermes.model.context import CodeMetaContext
from hermes.model import SoftwareMetadata
from hermes.model.context_manager import HermesContext
from hermes.model.error import HermesValidationError


class _CurateSettings(BaseModel):
class CurateSettings(BaseModel):
"""Generic deposition settings."""

pass
Expand All @@ -25,23 +24,30 @@ class HermesCurateCommand(HermesCommand):
""" Curate the unified metadata before deposition. """

command_name = "curate"
settings_class = _CurateSettings
settings_class = CurateSettings

def init_command_parser(self, command_parser: argparse.ArgumentParser) -> None:
pass

def __call__(self, args: argparse.Namespace) -> None:

self.log.info("# Metadata curation")

ctx = CodeMetaContext()
process_output = ctx.hermes_dir / 'process' / (ctx.hermes_name + ".json")
ctx = HermesContext()
ctx.prepare_step("curate")

ctx.prepare_step("process")
with ctx["result"] as process_ctx:
expanded_data = process_ctx["expanded"]
context_data = process_ctx["context"]
ctx.finalize_step("process")

try:
data = SoftwareMetadata(expanded_data[0], context_data["@context"][1])
except Exception as e:
raise HermesValidationError("The results of the process step are invalid.") from e

if not process_output.is_file():
self.log.error(
"No processed metadata found. Please run `hermes process` before curation."
)
sys.exit(1)
with ctx["result"] as curate_ctx:
curate_ctx["expanded"] = data.ld_value
curate_ctx["context"] = {"@context": data.full_context}

os.makedirs(ctx.hermes_dir / 'curate', exist_ok=True)
shutil.copy(process_output, ctx.hermes_dir / 'curate' / (ctx.hermes_name + '.json'))
ctx.finalize_step("curate")
115 changes: 112 additions & 3 deletions test/hermes_test/model/test_api_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

import pytest
import sys
from hermes.model import context_manager, SoftwareMetadata
from hermes.model import SoftwareMetadata
from hermes.model.context_manager import HermesContext
from hermes.commands import cli


Expand Down Expand Up @@ -181,12 +182,16 @@ def test_cff_harvest(tmp_path, monkeypatch, cff, res):
sys.argv = ["hermes", "harvest", "--path", str(tmp_path), "--config", str(config_file)]
result = {}
try:
monkeypatch.setattr(context_manager.HermesContext.__init__, "__defaults__", (tmp_path.cwd(),))
monkeypatch.setattr(HermesContext.__init__, "__defaults__", (tmp_path.cwd(),))
cli.main()
except SystemExit:
<<<<<<< feature/454-e2e-curate
manager = HermesContext()
=======
print("TODO: Delete when package is working again or mock cli")
finally:
manager = context_manager.HermesContext()
>>>>>>> feature/454-e2e-test-plugin-api
manager.prepare_step("harvest")
with manager["cff"] as cache:
result = SoftwareMetadata(cache["codemeta"])
Expand Down Expand Up @@ -342,16 +347,120 @@ def test_codemeta_harvest(tmp_path, monkeypatch, codemeta, res):
sys.argv = ["hermes", "harvest", "--path", str(tmp_path), "--config", str(config_file)]
result = {}
try:
monkeypatch.setattr(context_manager.HermesContext.__init__, "__defaults__", (tmp_path.cwd(),))
monkeypatch.setattr(HermesContext.__init__, "__defaults__", (tmp_path.cwd(),))
cli.main()
except SystemExit:
<<<<<<< feature/454-e2e-curate
manager = HermesContext()
=======
print("TODO: Delete when package is working again or mock cli")
finally:
manager = context_manager.HermesContext()
>>>>>>> feature/454-e2e-test-plugin-api
manager.prepare_step("harvest")
with manager["codemeta"] as cache:
result = SoftwareMetadata(cache["codemeta"])
manager.finalize_step("harvest")
sys.argv = orig_argv

assert result.data_dict == res.data_dict


@pytest.mark.parametrize(
"process_result, res",
[
2 * (
SoftwareMetadata({
"@type": ["http://schema.org/SoftwareSourceCode"],
"http://schema.org/description": [{"@value": "for testing"}],
"http://schema.org/name": [{"@value": "Test"}]
}),
),
2 * (
SoftwareMetadata({
"@type": ["http://schema.org/SoftwareSourceCode"],
"http://schema.org/applicationCategory": [{"@id": "Testing"}],
"http://schema.org/author": [
{
"@list": [
{
"@id": "_:author_1",
"@type": ["http://schema.org/Person"],
"http://schema.org/email": [{"@value": "test.testi@test.testi"}],
"http://schema.org/familyName": [{"@value": "Testi"}],
"http://schema.org/givenName": [{"@value": "Test"}]
}
]
}
],
"http://schema.org/codeRepository": [{"@id": "https://github.com/softwarepub/hermes"}],
"http://schema.org/contributor": [
{
"@id": "_:contributor_1",
"@type": ["http://schema.org/Person"],
"http://schema.org/email": [{"@value": "test.testi@test.testi"}],
"http://schema.org/familyName": [{"@value": "Testi"}],
"http://schema.org/givenName": [{"@value": "Test"}]
}
],
"http://schema.org/dateCreated": [{"@type": "http://schema.org/Date", "@value": "2026-01-16"}],
"http://schema.org/dateModified": [{"@type": "http://schema.org/Date", "@value": "2026-01-16"}],
"http://schema.org/datePublished": [{"@type": "http://schema.org/Date", "@value": "2026-01-16"}],
"http://schema.org/description": [{"@value": "for testing"}],
"http://schema.org/funder": [
{
"@type": ["http://schema.org/Organization"],
"http://schema.org/name": [{"@value": "TestsTests"}]
}
],
"http://schema.org/keywords": [{"@value": "testing"}, {"@value": "more testing"}],
"http://schema.org/license": [
{"@id": "https://spdx.org/licenses/Adobe-2006"},
{"@id": "https://spdx.org/licenses/Abstyles"},
{"@id": "https://spdx.org/licenses/AGPL-1.0-only"}
],
"http://schema.org/name": [{"@value": "Test"}],
"http://schema.org/operatingSystem": [{"@value": "Windows"}],
"http://schema.org/programmingLanguage": [{"@value": "Python"}, {"@value": "Python 3"}],
"http://schema.org/relatedLink": [{"@id": "https://docs.software-metadata.pub/en/latest"}],
"http://schema.org/releaseNotes": [{"@value": "get it now"}],
"http://schema.org/version": [{"@value": "1.1.1"}],
"https://codemeta.github.io/terms/developmentStatus": [{"@id": "abandoned"}],
"https://codemeta.github.io/terms/funding": [{"@value": "none :("}],
"https://codemeta.github.io/terms/isSourceCodeOf": [{"@id": "HERMES"}],
"https://codemeta.github.io/terms/issueTracker": [
{"@id": "https://github.com/softwarepub/hermes/issues"}
],
"https://codemeta.github.io/terms/referencePublication": [{"@id": "https://arxiv.org/abs/2201.09015"}]
}),
),
]
)
def test_do_nothing_curate(tmp_path, monkeypatch, process_result, res):
monkeypatch.chdir(tmp_path)

manager = HermesContext(tmp_path)
manager.prepare_step("process")
with manager["result"] as cache:
cache["expanded"] = process_result.ld_value
cache["context"] = {"@context": process_result.full_context}
manager.finalize_step("process")

config_file = tmp_path / "hermes.toml"
config_file.write_text("")

orig_argv = sys.argv[:]
sys.argv = ["hermes", "curate", "--path", str(tmp_path), "--config", str(config_file)]
result = {}
try:
monkeypatch.setattr(HermesContext.__init__, "__defaults__", (tmp_path.cwd(),))
cli.main()
except SystemExit:
manager.prepare_step("curate")
with manager["result"] as cache:
result = SoftwareMetadata(cache["expanded"][0], cache["context"]["@context"][1])
manager.finalize_step("curate")
finally:
sys.argv = orig_argv

assert result.data_dict == res.data_dict
Loading