Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F7124799
D1419.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Subscribers
None
D1419.diff
View Options
diff --git a/swh/deposit/cli/deposit.py b/swh/deposit/cli/deposit.py
--- a/swh/deposit/cli/deposit.py
+++ b/swh/deposit/cli/deposit.py
@@ -3,11 +3,13 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-import logging
import os
+import logging
+import tempfile
import uuid
import click
+import xmltodict
from swh.deposit.client import PublicApiDepositClient
from swh.deposit.cli import cli
@@ -30,11 +32,60 @@
return str(uuid.uuid4())
+def generate_metadata_file(name, authors):
+ """Generate a temporary metadata file with the minimum required metadata
+
+ This generates a xml file in a temporary location and returns the
+ path to that file.
+
+ This is up to the client of that function to clean up the
+ temporary file.
+
+ """
+ _, tmpfile = tempfile.mkstemp(prefix='swh.deposit.cli.')
+
+ # generate a metadata file with the minimum required metadata
+ codemetadata = {
+ 'entry': {
+ '@xmlns': "http://www.w3.org/2005/Atom",
+ '@xmlns:codemeta': "https://doi.org/10.5063/SCHEMA/CODEMETA-2.0",
+ 'codemeta:name': name,
+ 'codemeta:author': [{
+ 'codemeta:name': author_name
+ } for author_name in authors],
+ },
+ }
+
+ logging.debug('Temporary file: %s', tmpfile)
+ logging.debug('Metadata dict to generate as xml: %s', codemetadata)
+ s = xmltodict.unparse(codemetadata, pretty=True)
+ logging.debug('Metadata dict as xml generated: %s', s)
+ with open(tmpfile, 'w') as fp:
+ fp.write(s)
+ return tmpfile
+
+
+def _cleanup_tempfile(config):
+ """Clean up the temporary metadata file generated.
+
+ Args:
+
+ config (Dict): A configuration dict with 2 important keys for
+ that routine, 'cleanup_tempfile' (bool) and 'metadata' (path
+ to eventually clean up)
+
+ """
+ if config['cleanup_tempfile']:
+ path = config['metadata']
+ if os.path.exists(path):
+ os.unlink(path)
+
+
def client_command_parse_input(
username, password, archive, metadata,
archive_deposit, metadata_deposit,
collection, slug, partial, deposit_id, replace,
- url, status):
+ url, status, name, authors):
"""Parse the client subcommand options and make sure the combination
is acceptable*. If not, an InputError exception is raised
explaining the issue.
@@ -74,82 +125,99 @@
'deposit_id': optional deposit identifier
"""
- if status and not deposit_id:
- raise InputError("Deposit id must be provided for status check")
-
- if status and deposit_id: # status is higher priority over deposit
- archive_deposit = False
- metadata_deposit = False
- archive = None
- metadata = None
+ cleanup_tempfile = False
- if archive_deposit and metadata_deposit:
- # too many flags use, remove redundant ones (-> multipart deposit)
- archive_deposit = False
- metadata_deposit = False
-
- if archive and not os.path.exists(archive):
- raise InputError('Software Archive %s must exist!' % archive)
-
- if archive and not metadata:
- metadata = '%s.metadata.xml' % archive
-
- if metadata_deposit:
- archive = None
-
- if archive_deposit:
- metadata = None
-
- if metadata_deposit and not metadata:
- raise InputError(
- "Metadata deposit filepath must be provided for metadata deposit")
-
- if metadata and not os.path.exists(metadata):
- raise InputError('Software Archive metadata %s must exist!' % metadata)
-
- if not status and not archive and not metadata:
- raise InputError(
- 'Please provide an actionable command. See --help for more '
- 'information.')
-
- if replace and not deposit_id:
- raise InputError(
- 'To update an existing deposit, you must provide its id')
-
- client = PublicApiDepositClient({
- 'url': url,
- 'auth': {
+ try:
+ if status and not deposit_id:
+ raise InputError("Deposit id must be provided for status check")
+
+ if status and deposit_id: # status is higher priority over deposit
+ archive_deposit = False
+ metadata_deposit = False
+ archive = None
+ metadata = None
+
+ if archive_deposit and metadata_deposit:
+ # too many flags use, remove redundant ones (-> multipart deposit)
+ archive_deposit = False
+ metadata_deposit = False
+
+ if archive and not os.path.exists(archive):
+ raise InputError('Software Archive %s must exist!' % archive)
+
+ if archive and not metadata: # we need to have the metadata
+ if name and authors:
+ metadata = generate_metadata_file(name, authors)
+ cleanup_tempfile = True
+ else:
+ raise InputError('Either metadata deposit file or (`--name` '
+ ' and `--author`) fields must be provided')
+
+ if metadata_deposit:
+ archive = None
+
+ if archive_deposit:
+ metadata = None
+
+ if metadata_deposit and not metadata:
+ raise InputError(
+ "Metadata deposit filepath must be provided for metadata "
+ "deposit")
+
+ if metadata and not os.path.exists(metadata):
+ raise InputError('Software Archive metadata %s must exist!' % (
+ metadata, ))
+
+ if not status and not archive and not metadata:
+ raise InputError(
+ 'Please provide an actionable command. See --help for more '
+ 'information.')
+
+ if replace and not deposit_id:
+ raise InputError(
+ 'To update an existing deposit, you must provide its id')
+
+ client = PublicApiDepositClient({
+ 'url': url,
+ 'auth': {
+ 'username': username,
+ 'password': password
+ },
+ })
+
+ if not collection:
+ # retrieve user's collection
+ sd_content = client.service_document()
+ if 'error' in sd_content:
+ raise InputError('Service document retrieval: %s' % (
+ sd_content['error'], ))
+ collection = sd_content[
+ 'service']['workspace']['collection']['sword:name']
+
+ if not slug:
+ # generate slug
+ slug = generate_slug()
+
+ return {
+ 'archive': archive,
'username': username,
- 'password': password
- },
- })
-
- if not collection:
- # retrieve user's collection
- sd_content = client.service_document()
- if 'error' in sd_content:
- raise InputError('Service document retrieval: %s' % (
- sd_content['error'], ))
- collection = sd_content[
- 'service']['workspace']['collection']['sword:name']
-
- if not slug:
- # generate slug
- slug = generate_slug()
-
- return {
- 'archive': archive,
- 'username': username,
- 'password': password,
- 'metadata': metadata,
- 'collection': collection,
- 'slug': slug,
- 'in_progress': partial,
- 'client': client,
- 'url': url,
- 'deposit_id': deposit_id,
- 'replace': replace,
- }
+ 'password': password,
+ 'metadata': metadata,
+ 'cleanup_tempfile': cleanup_tempfile,
+ 'collection': collection,
+ 'slug': slug,
+ 'in_progress': partial,
+ 'client': client,
+ 'url': url,
+ 'deposit_id': deposit_id,
+ 'replace': replace,
+ }
+ except Exception: # to be clean, cleanup prior to raise
+ _cleanup_tempfile({
+ 'cleanup_tempfile': cleanup_tempfile,
+ 'metadata': metadata
+ })
+ raise
def _subdict(d, keys):
@@ -219,6 +287,11 @@
help="(Optional) Deposit's status")
@click.option('--verbose/--no-verbose', default=False,
help='Verbose mode')
+@click.option('--name',
+ help='Software name')
+@click.option('--author', multiple=True,
+ help='Software author(s), this can be repeated as many times'
+ ' as there are authors')
@click.pass_context
def deposit(ctx,
username, password, archive=None, metadata=None,
@@ -226,7 +299,7 @@
collection=None, slug=None, partial=False, deposit_id=None,
replace=False, status=False,
url='https://deposit.softwareheritage.org/1',
- verbose=False):
+ verbose=False, name=None, author=None):
"""Software Heritage Public Deposit Client
Create/Update deposit through the command line or access its
@@ -243,8 +316,7 @@
config = client_command_parse_input(
username, password, archive, metadata, archive_deposit,
metadata_deposit, collection, slug, partial, deposit_id,
- replace, url, status)
-
+ replace, url, status, name, author)
except InputError as e:
msg = 'Problem during parsing options: %s' % e
r = {
@@ -253,17 +325,21 @@
logger.info(r)
return 1
- if verbose:
- logger.info("Parsed configuration: %s" % (
- config, ))
+ try:
+ if verbose:
+ logger.info("Parsed configuration: %s" % (
+ config, ))
+
+ deposit_id = config['deposit_id']
- deposit_id = config['deposit_id']
+ if status and deposit_id:
+ r = deposit_status(config, logger)
+ elif not status and deposit_id:
+ r = deposit_update(config, logger)
+ elif not status and not deposit_id:
+ r = deposit_create(config, logger)
- if status and deposit_id:
- r = deposit_status(config, logger)
- elif not status and deposit_id:
- r = deposit_update(config, logger)
- elif not status and not deposit_id:
- r = deposit_create(config, logger)
+ logger.info(r)
- logger.info(r)
+ finally:
+ _cleanup_tempfile(config)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Dec 21 2024, 7:44 PM (11 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3216062
Attached To
D1419: cli.deposit: Add mandatory flags to generate the metadata xml
Event Timeline
Log In to Comment