Skip to content

Commit

Permalink
Merge pull request #269 from NASA-PDS/action_class_bug_fixes
Browse files Browse the repository at this point in the history
Action Class Bug Fix Roll Up
  • Loading branch information
collinss-jpl authored Oct 11, 2021
2 parents b3b30df + 59303fc commit 8705f8b
Show file tree
Hide file tree
Showing 26 changed files with 554 additions and 202 deletions.
8 changes: 3 additions & 5 deletions src/pds_doi_service/core/actions/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def create_cmd_parser():
"""
parser = argparse.ArgumentParser(
description="PDS core command for DOI management. " "The available subcommands are:\n",
description="PDS core command for DOI management. The available subcommands are:\n",
formatter_class=argparse.RawTextHelpFormatter,
)

Expand Down Expand Up @@ -90,7 +90,7 @@ def add_to_subparser(cls, subparsers):
"""
return NotImplementedError(
f"Subclasses of {cls.__class__.__name__} must provide an " f"implementation for add_to_subparser()"
f"Subclasses of {cls.__class__.__name__} must provide an implementation for add_to_subparser()"
)

def parse_arguments(self, kwargs):
Expand Down Expand Up @@ -134,6 +134,4 @@ def run(self, **kwargs):
representation).
"""
return NotImplementedError(
f"Subclasses of {self.__class__.__name__} must provide an " f"implementation for run()"
)
return NotImplementedError(f"Subclasses of {self.__class__.__name__} must provide an implementation for run()")
19 changes: 12 additions & 7 deletions src/pds_doi_service/core/actions/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@
class DOICoreActionCheck(DOICoreAction):
_name = "check"
_description = (
"Check pending DOI statuses from the service provider and "
"update the local database. May be run regularly, for "
"example in a crontab."
"Check for pending DOI submissions from the service provider and "
"update the local database with any changes in status"
)
_order = 30
_run_arguments = ("submitter", "email", "attachment")
Expand Down Expand Up @@ -82,7 +81,7 @@ def add_to_subparser(cls, subparsers):
"--email",
required=False,
action="store_true",
help="If provided, the check action sends results to the default " "recipients and pending DOI submitters.",
help="If provided, the check action sends results to the default recipients and pending DOI submitters.",
)
action_parser.add_argument(
"-a",
Expand All @@ -96,8 +95,8 @@ def add_to_subparser(cls, subparsers):
"-s",
"--submitter",
required=False,
metavar='"[email protected]"',
help="The email address of the user to register as author of the " "check action.",
metavar="EMAIL",
help="The email address of the user to register as author of the check action.",
)

def _update_transaction_db(self, pending_record):
Expand Down Expand Up @@ -169,7 +168,7 @@ def _update_transaction_db(self, pending_record):
pending_record.pop("is_latest", None)
else:
message = (
f"No record for DOI {pending_record['doi']} " f"(Identifier {identifier}) found at the service provider"
f"No record for DOI {pending_record['doi']} (Identifier {identifier}) found at the service provider"
)
pending_record["message"] = message
logger.error(message)
Expand Down Expand Up @@ -410,6 +409,12 @@ def run(self, **kwargs):
All parameters are optional and may be useful for tests.
"""
logger.warning(
"This action has been deprecated with the transition "
"from OSTI to DataCite as the DOI service provider.\nThis action "
"may be removed or significantly modified in a future release."
)

self.parse_arguments(kwargs)

# Get the list of latest rows in database with status = 'Pending'.
Expand Down
24 changes: 13 additions & 11 deletions src/pds_doi_service/core/actions/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@

class DOICoreActionDraft(DOICoreAction):
_name = "draft"
_description = "Prepare a draft DOI record created from PDS4 labels."
_description = (
"Update a record without submission to the service provider. Metadata "
"updates are pulled from the provided PDS4/DOI label."
)
_order = 10
_run_arguments = ("input", "node", "submitter", "lidvid", "force", "keywords")

Expand All @@ -66,16 +69,16 @@ def __init__(self, db_name=None):
@classmethod
def add_to_subparser(cls, subparsers):
action_parser = subparsers.add_parser(
cls._name, description="Create a draft DOI record from existing PDS4 or DOI " "labels."
cls._name, description="Create a draft DOI record from existing PDS4 or DOI labels."
)

node_values = NodeUtil.get_permissible_values()
action_parser.add_argument(
"-i",
"--input",
required=False,
metavar="input/bundle_in_with_contributors.xml",
help="An input PDS4/DOI label. May be a local path or an HTTP address "
metavar="INPUT[,INPUT]...",
help="Path to an input PDS4/DOI label. May be a local path or an HTTP address "
"resolving to a label file. Multiple inputs may be provided "
"via comma-delimited list. Must be provided if --lidvid is not "
"specified.",
Expand All @@ -84,21 +87,20 @@ def add_to_subparser(cls, subparsers):
"-n",
"--node",
required=True,
metavar='"img"',
help="The PDS Discipline Node in charge of the DOI. Authorized " "values are: " + ",".join(node_values),
metavar="NODE_ID",
help="The PDS Discipline Node in charge of the DOI. Authorized values are: " + ",".join(node_values),
)
action_parser.add_argument(
"-s",
"--submitter",
required=True,
metavar='"[email protected]"',
metavar="EMAIL",
help="The email address to associate with the Draft record.",
)
action_parser.add_argument(
"-l",
"--lidvid",
required=False,
metavar="urn:nasa:pds:lab_shocked_feldspars::1.0",
help="A LIDVID for an existing DOI record to move back to draft "
"status. Must be provided if --input is not specified.",
)
Expand All @@ -116,7 +118,7 @@ def add_to_subparser(cls, subparsers):
"-k",
"--keywords",
required=False,
metavar='"Image"',
metavar="KEYWORD[,KEYWORD]...",
default="",
help="Extra keywords to associate with the Draft record. Multiple "
'keywords must be separated by ",". Ignored when used with the '
Expand Down Expand Up @@ -316,7 +318,7 @@ def _draft_input_files(self, inputs):
# Make sure were returning a valid label
self._validator_service.validate(o_doi_label)
else:
logger.warning("No DOI objects could be parsed from the provided " "list of inputs: %s", list_of_inputs)
logger.warning("No DOI objects could be parsed from the provided list of inputs: %s", list_of_inputs)
o_doi_label = ""

return o_doi_label
Expand Down Expand Up @@ -414,7 +416,7 @@ def run(self, **kwargs):

# Make sure we've been given something to work with
if self._input is None and self._lidvid is None:
raise ValueError("A value must be provided for either --input or " "--lidvid when using the Draft action.")
raise ValueError("A value must be provided for either --input or --lidvid when using the Draft action.")

if self._lidvid:
return self._set_lidvid_to_draft(self._lidvid)
Expand Down
35 changes: 18 additions & 17 deletions src/pds_doi_service/core/actions/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

class DOICoreActionList(DOICoreAction):
_name = "list"
_description = "List DOI entries within the transaction database that match " "the provided search criteria"
_description = "List DOI entries within the transaction database that match the provided search criteria"
_order = 40
_run_arguments = ("doi", "ids", "node", "status", "start_update", "end_update", "submitter")

Expand All @@ -46,10 +46,8 @@ def __init__(self, db_name=None):
def add_to_subparser(cls, subparsers):
action_parser = subparsers.add_parser(
cls._name,
description="Extracts the submitted DOI from the local "
"transaction database using the following "
"selection criteria. Output is returned in "
"JSON format.",
description="Extracts the submitted DOI from the local transaction database using "
"the following selection criteria. Output is returned in JSON format.",
)

node_values = NodeUtil.get_permissible_values()
Expand All @@ -59,31 +57,30 @@ def add_to_subparser(cls, subparsers):
"-n",
"--node",
required=False,
metavar='"img,eng"',
metavar="NODE_ID[,NODE_ID]...",
help="A list of comma-separated node names to filter the available "
"DOI entries by. Valid values are: " + ",".join(node_values),
)
action_parser.add_argument(
"-status",
"--status",
required=False,
metavar="draft,review",
metavar="STATUS[,STATUS]...",
help="A list of comma-separated submission status values to filter "
"the database query results by. Valid status values are: "
"{}".format(", ".join(status_values)),
"the database query results by. Valid status values are: {}".format(", ".join(status_values)),
)
action_parser.add_argument(
"-doi",
"--doi",
required=False,
metavar="10.17189/21734",
help="A list of comma-delimited DOI values to use as filters with the " "database query.",
metavar="DOI[,DOI]...",
help="A list of comma-delimited DOI values to use as filters with the database query.",
)
action_parser.add_argument(
"-i",
"--ids",
required=False,
metavar="urn:nasa:pds:lab_shocked_feldspars",
metavar="ID[,ID]...",
help="A list of comma-delimited PDS identifiers to use as filters with "
"the database query. Each ID may contain one or more wildcards "
"(*) to pattern match against.",
Expand All @@ -92,23 +89,27 @@ def add_to_subparser(cls, subparsers):
"-start",
"--start-update",
required=False,
metavar="2020-01-01T19:02:15.000000",
metavar="YYYY-MM-DD[THH:mm:ss.ssssss[Z]]",
help="The start time of the record update to use as a filter with the "
"database query. Should conform to a valid isoformat date string.",
"database query. Should conform to a valid isoformat date string. By "
"default, the local time zone is assumed. To provide a time in UTC, "
"append a 'Z' to the time portion of the provided date-time.",
)
action_parser.add_argument(
"-end",
"--end-update",
required=False,
metavar="2020-12-311T23:59:00.000000",
metavar="YYYY-MM-DD[THH:mm:ss.ssssss[Z]]",
help="The end time for record update time to use as a filter with the "
"database query. Should conform to a valid isoformat date string.",
"database query. Should conform to a valid isoformat date string. By "
"default, the local time zone is assumed. To provide a time in UTC, "
"append a 'Z' to the time portion of the provided date-time.",
)
action_parser.add_argument(
"-s",
"--submitter",
required=False,
metavar='"[email protected]"',
metavar="EMAIL",
help="A list of comma-separated email addresses to use as a filter "
"with the database query. Only entries containing the one of "
"the provided addresses as the submitter will be returned.",
Expand Down
42 changes: 16 additions & 26 deletions src/pds_doi_service/core/actions/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,15 @@
from pds_doi_service.core.outputs.doi_record import CONTENT_TYPE_JSON
from pds_doi_service.core.outputs.doi_validator import DOIValidator
from pds_doi_service.core.outputs.service import DOIServiceFactory
from pds_doi_service.core.outputs.service import SERVICE_TYPE_DATACITE
from pds_doi_service.core.outputs.web_client import WEB_METHOD_POST
from pds_doi_service.core.outputs.web_client import WEB_METHOD_PUT
from pds_doi_service.core.util.general_util import create_landing_page_url
from pds_doi_service.core.util.general_util import get_logger

logger = get_logger(__name__)


class DOICoreActionRelease(DOICoreAction):
_name = "release"
_description = "Move a reserved DOI to review, or submit a DOI for " "release to the service provider."
_description = "Move a reserved DOI to review, or submit a DOI for release to the service provider"
_order = 20
_run_arguments = ("input", "node", "submitter", "force", "no_review")

Expand All @@ -61,14 +59,13 @@ def add_to_subparser(cls, subparsers):
action_parser = subparsers.add_parser(
cls._name,
description="Release a DOI, in draft or reserve status, for review. "
"A DOI may also be released to the DOI service provider "
"directly.",
"A DOI may also be released to the DOI service provider directly.",
)
action_parser.add_argument(
"-n",
"--node",
required=True,
metavar='"img"',
metavar="NODE_ID",
help="The PDS Discipline Node in charge of the released DOI. "
"Authorized values are: {}".format(",".join(NodeUtil.get_permissible_values())),
)
Expand All @@ -86,17 +83,16 @@ def add_to_subparser(cls, subparsers):
"-i",
"--input",
required=True,
metavar="input/DOI_Update_GEO_200318.xml",
help="A file containing a list of DOI metadata to update/release "
"in OSTI JSON/XML format (see https://www.osti.gov/iad2/docs#record-model)."
"The input is produced by the Reserve and Draft actions, and "
"can be retrieved for a DOI with the List action.",
help="Path to a file containing the record to release. The format may be "
"either a PDS4 label, or a DataCite JSON label. "
"DataCite JSON labels are produced by the Reserve and "
"Draft actions, and can be retrieved for a DOI with the List action.",
)
action_parser.add_argument(
"-s",
"--submitter",
required=True,
metavar='"[email protected]"',
metavar="EMAIL",
help="The email address to associate with the Release request.",
)
action_parser.add_argument(
Expand Down Expand Up @@ -149,6 +145,11 @@ def _complete_dois(self, dois):
# Add 'status' field so the ranking in the workflow can be determined.
doi.status = DoiStatus.Pending if self._no_review else DoiStatus.Review

# If a site url was not created for the DOI at parse time, try
# to create one now
if not doi.site_url:
doi.site_url = create_landing_page_url(doi.related_identifier, doi.product_type)

if self._no_review:
# Add the event field to instruct DataCite to publish DOI to
# findable state (should have no effect for other providers)
Expand Down Expand Up @@ -257,19 +258,8 @@ def run(self, **kwargs):
# If the next step is to release, submit to the service provider and
# use the response label for the local transaction database entry
if self._no_review:
service_type = DOIServiceFactory.get_service_type()

# For OSTI, all submissions use the POST method
# for DataCite, releasing a reserved DOI requires the PUT method
method = WEB_METHOD_PUT if service_type == SERVICE_TYPE_DATACITE else WEB_METHOD_POST

# For DataCite, need to append the assigned DOI to the url
# for the PUT request. For OSTI, can just default to the
# url within the INI.
if service_type == SERVICE_TYPE_DATACITE:
url = "{url}/{doi}".format(url=self._config.get("DATACITE", "url"), doi=doi.doi)
else:
url = self._config.get("OSTI", "url")
# Determine the correct HTTP verb and URL for submission of this DOI
method, url = self._web_client.endpoint_for_doi(doi)

doi, o_doi_label = self._web_client.submit_content(
url=url, method=method, payload=io_doi_label, content_type=CONTENT_TYPE_JSON
Expand Down
Loading

0 comments on commit 8705f8b

Please sign in to comment.