Skip to content

Commit e5065c2

Browse files
Merge pull request #469 from softwarepub/feature/454-e2e-deposit
Merged implementation for process and deposit step back into the feature branches base branch.
2 parents 1e781ca + 57cdfb0 commit e5065c2

23 files changed

Lines changed: 2139 additions & 257 deletions

src/hermes/commands/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
# "unused import" errors.
99
# flake8: noqa
1010

11-
# from hermes.commands.base import HermesHelpCommand
12-
# from hermes.commands.base import HermesVersionCommand
13-
# from hermes.commands.clean.base import HermesCleanCommand
11+
from hermes.commands.base import HermesHelpCommand
12+
from hermes.commands.base import HermesVersionCommand
13+
from hermes.commands.clean.base import HermesCleanCommand
1414
# from hermes.commands.init.base import HermesInitCommand
1515
from hermes.commands.curate.base import HermesCurateCommand
1616
from hermes.commands.harvest.base import HermesHarvestCommand
17-
# from hermes.commands.process.base import HermesProcessCommand
18-
# from hermes.commands.deposit.base import HermesDepositCommand
17+
from hermes.commands.process.base import HermesProcessCommand
18+
from hermes.commands.deposit.base import HermesDepositCommand
1919
# from hermes.commands.postprocess.base import HermesPostprocessCommand

src/hermes/commands/base.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ def __call__(self, command: HermesCommand) -> None:
175175

176176

177177
class HermesHelpSettings(BaseModel):
178+
"""Intentionally empty settings class for the help command."""
178179
pass
179180

180181

@@ -200,3 +201,23 @@ def __call__(self, args: argparse.Namespace) -> None:
200201
# Otherwise, simply show the general help and exit (cleanly).
201202
self.parser.print_help()
202203
self.parser.exit()
204+
205+
206+
class HermesVersionSettings(BaseModel):
207+
"""Intentionally empty settings class for the version command."""
208+
pass
209+
210+
211+
class HermesVersionCommand(HermesCommand):
212+
"""Show HERMES version and exit."""
213+
214+
command_name = "version"
215+
settings_class = HermesVersionSettings
216+
217+
def load_settings(self, args: argparse.Namespace):
218+
"""Pass loading settings as not necessary for this command."""
219+
pass
220+
221+
def __call__(self, args: argparse.Namespace) -> None:
222+
self.log.info(metadata.version("hermes"))
223+
self.parser.exit()

src/hermes/commands/cli.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
# from hermes.commands import (HermesHelpCommand, HermesVersionCommand, HermesCleanCommand,
1717
# HermesHarvestCommand, HermesProcessCommand, HermesCurateCommand,
1818
# HermesDepositCommand, HermesPostprocessCommand, HermesInitCommand)
19-
from hermes.commands import HermesCurateCommand, HermesHarvestCommand
19+
from hermes.commands import (HermesCurateCommand, HermesDepositCommand,
20+
HermesHarvestCommand, HermesHelpCommand,
21+
HermesProcessCommand, HermesVersionCommand)
2022
from hermes.commands.base import HermesCommand
2123

2224

@@ -38,15 +40,15 @@ def main() -> None:
3840
setting_types = {}
3941

4042
for command in (
41-
# HermesHelpCommand(parser),
42-
# HermesVersionCommand(parser),
43-
# HermesInitCommand(parser),
4443
# HermesCleanCommand(parser),
45-
HermesHarvestCommand(parser),
46-
# HermesProcessCommand(parser),
4744
HermesCurateCommand(parser),
48-
# HermesDepositCommand(parser),
45+
HermesDepositCommand(parser),
46+
HermesHarvestCommand(parser),
47+
HermesHelpCommand(parser),
48+
# HermesInitCommand(parser),
4949
# HermesPostprocessCommand(parser),
50+
HermesProcessCommand(parser),
51+
HermesVersionCommand(parser),
5052
):
5153
if command.settings_class is not None:
5254
setting_types[command.command_name] = command.settings_class

src/hermes/commands/deposit/base.py

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@
77

88
import abc
99
import argparse
10-
import json
11-
import sys
1210

1311
from pydantic import BaseModel
1412

1513
from hermes.commands.base import HermesCommand, HermesPlugin
16-
from hermes.model.context import CodeMetaContext
17-
from hermes.model.path import ContextPath
18-
from hermes.model.errors import HermesValidationError
14+
from hermes.model.context_manager import HermesContext
15+
from hermes.model import SoftwareMetadata
16+
from hermes.model.error import HermesValidationError
1917

2018

2119
class BaseDepositPlugin(HermesPlugin):
@@ -24,26 +22,35 @@ class BaseDepositPlugin(HermesPlugin):
2422
TODO: describe workflow... needs refactoring to be less stateful!
2523
"""
2624

27-
def __init__(self, command, ctx):
28-
self.command = command
29-
self.ctx = ctx
30-
3125
def __call__(self, command: HermesCommand) -> None:
3226
"""Initiate the deposition process.
3327
3428
This calls a list of additional methods on the class, none of which need to be implemented.
3529
"""
3630
self.command = command
31+
self.ctx = HermesContext()
32+
33+
self.ctx.prepare_step("curate")
34+
self.metadata = SoftwareMetadata.load_from_cache(self.ctx, "result")
35+
self.ctx.finalize_step("curate")
3736

3837
self.prepare()
39-
self.map_metadata()
38+
deposit = self.map_metadata()
39+
self.ctx.prepare_step("deposit")
40+
with self.ctx[command.settings.target] as cache:
41+
cache["deposit"] = deposit
42+
self.ctx.finalize_step("deposit")
4043

4144
if self.is_initial_publication():
4245
self.create_initial_version()
4346
else:
4447
self.create_new_version()
4548

46-
self.update_metadata()
49+
deposit = self.update_metadata()
50+
self.ctx.prepare_step("deposit")
51+
with self.ctx["deposit"] as cache:
52+
cache["result"] = deposit
53+
self.ctx.finalize_step("deposit")
4754
self.delete_artifacts()
4855
self.upload_artifacts()
4956
self.publish()
@@ -58,8 +65,8 @@ def prepare(self) -> None:
5865
pass
5966

6067
@abc.abstractmethod
61-
def map_metadata(self) -> None:
62-
"""Map the given metadata to the target schema of the deposition platform.
68+
def map_metadata(self) -> dict:
69+
"""Map the given metadata to the target schema of the deposition platform and return it.
6370
6471
When mapping metadata, make sure to add traces to the HERMES software, e.g. via
6572
DataCite's ``relatedIdentifier`` using the ``isCompiledBy`` relation. Ideally, the value
@@ -88,8 +95,9 @@ def create_new_version(self) -> None:
8895
"""Create a new version of an existing publication on the target platform."""
8996
pass
9097

91-
def update_metadata(self) -> None:
92-
"""Update the metadata of the newly created version."""
98+
@abc.abstractmethod
99+
def update_metadata(self) -> dict:
100+
"""Update the metadata of the newly created version and return it even if it hasn't changed."""
93101
pass
94102

95103
def delete_artifacts(self) -> None:
@@ -106,7 +114,7 @@ def publish(self) -> None:
106114
pass
107115

108116

109-
class _DepositSettings(BaseModel):
117+
class DepositSettings(BaseModel):
110118
"""Generic deposition settings."""
111119

112120
target: str = ""
@@ -116,7 +124,7 @@ class HermesDepositCommand(HermesCommand):
116124
""" Deposit the curated metadata to repositories. """
117125

118126
command_name = "deposit"
119-
settings_class = _DepositSettings
127+
settings_class = DepositSettings
120128

121129
def init_command_parser(self, command_parser: argparse.ArgumentParser) -> None:
122130
command_parser.add_argument('--file', '-f', nargs=1, action='append',
@@ -128,26 +136,13 @@ def __call__(self, args: argparse.Namespace) -> None:
128136
self.args = args
129137
plugin_name = self.settings.target
130138

131-
ctx = CodeMetaContext()
132-
codemeta_file = ctx.get_cache("curate", ctx.hermes_name)
133-
if not codemeta_file.exists():
134-
self.log.error("You must run the 'curate' command before deposit")
135-
sys.exit(1)
136-
137-
codemeta_path = ContextPath("codemeta")
138-
with open(codemeta_file) as codemeta_fh:
139-
ctx.update(codemeta_path, json.load(codemeta_fh))
140-
141139
try:
142-
plugin_func = self.plugins[plugin_name](self, ctx)
143-
140+
plugin_func = self.plugins[plugin_name]()
144141
except KeyError as e:
145142
self.log.error("Plugin '%s' not found.", plugin_name)
146143
self.errors.append(e)
147-
148144
try:
149145
plugin_func(self)
150-
151146
except HermesValidationError as e:
152147
self.log.error("Error while executing %s: %s", plugin_name, e)
153148
self.errors.append(e)

src/hermes/commands/deposit/file.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,23 @@
1111
from pydantic import BaseModel
1212

1313
from hermes.commands.deposit.base import BaseDepositPlugin
14-
from hermes.model.path import ContextPath
1514

1615

1716
class FileDepositSettings(BaseModel):
18-
filename: str = 'hermes.json'
17+
filename: str = 'codemeta.json'
1918

2019

2120
class FileDepositPlugin(BaseDepositPlugin):
2221
settings_class = FileDepositSettings
2322

24-
def map_metadata(self) -> None:
25-
self.ctx.update(ContextPath.parse('deposit.file'), self.ctx['codemeta'])
23+
def map_metadata(self) -> dict:
24+
return self.metadata.compact()
25+
26+
def update_metadata(self) -> dict:
27+
return self.metadata.compact()
2628

2729
def publish(self) -> None:
2830
file_config = self.command.settings.file
29-
output_data = self.ctx['deposit.file']
3031

3132
with open(file_config.filename, 'w') as deposition_file:
32-
json.dump(output_data, deposition_file, indent=2)
33+
json.dump(self.metadata.compact(), deposition_file, indent=2)

0 commit comments

Comments
 (0)