Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ™…πŸ»β€β™‚οΈ add REJECTED choice and cli to reject analyses #58

Merged
merged 3 commits into from
Oct 27, 2023
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 isabl_cli/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ def patch_analysis_status(analysis, status):
analysis["status"] = status # make sure that the analysis status is updated
_set_analysis_permissions(analysis)

if status in {"FAILED", "SUCCEEDED", "IN_PROGRESS"}:
if status in {"FAILED", "SUCCEEDED", "IN_PROGRESS", "REJECTED"}:
data["storage_usage"] = utils.get_tree_size(storage_url)

if status == "STARTED":
Expand Down
4 changes: 2 additions & 2 deletions isabl_cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class AbstractApplication: # pylint: disable=too-many-public-methods
# Analyses in these status won't be prepared for submission. To re-rerun SUCCEEDED
# analyses see unique_analysis_per_individual. To re-rerun failed analyses use
# either --force or --restart.
skip_status = {"FAILED", "FINISHED", "STARTED", "SUBMITTED", "SUCCEEDED"}
skip_status = {"FAILED", "FINISHED", "STARTED", "SUBMITTED", "SUCCEEDED", "REJECTED"}

# If any of these errors is raised during the command generation process, the
# submission will continue. Errors or valdation messages are presented at the end.
Expand Down Expand Up @@ -957,7 +957,7 @@ def run_analyses(self, analyses, commit, force, restart, local):
api.patch_analysis_status(i, "STAGED")

# trash analysis and create outdir again
elif force and i["status"] not in {"SUCCEEDED", "FINISHED"}:
elif force and i["status"] not in {"SUCCEEDED", "FINISHED", "REJECTED"}:
system_settings.TRASH_ANALYSIS_STORAGE(i)
utils.makedirs(i["storage_url"])

Expand Down
10 changes: 10 additions & 0 deletions isabl_cli/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,13 @@ def run_signals(endpoint, filters, signals):

for i in api.get_instances(endpoint, **filters):
api._run_signals(endpoint, i, signals, raise_error=True, create_record=False)


@click.command(hidden=True)
@options.ANALYSIS_PRIMARY_KEY
@click.option("--reason", help="Rejection reason. (Will be stored in Analysis.notes)")
def reject_analysis(key, reason):
"""Patch an analysis status as REJECTED, providing the rejection reason."""
analysis = api.get_instance("analyses", key)
api.patch_analysis_status(analysis, "REJECTED")
api.patch_instance("analyses", key, notes=reason)
1 change: 1 addition & 0 deletions isabl_cli/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ProjectFactory(BaseFactory):
owner = factory.Sequence(lambda n: f"owner-{n}@test.com")
principal_investigator = factory.Sequence(lambda n: f"pi-{n}@test.com")
title = fuzzy.FuzzyText(length=20, chars=string.ascii_lowercase + " ")
sharing = {"can_share": [], "can_read": [], "is_public": True}


class CenterFactory(BaseFactory):
Expand Down
1 change: 1 addition & 0 deletions isabl_cli/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def _get_experiments(filter_tuples):
"STARTED",
"SUBMITTED",
"SUCCEEDED",
"REJECTED",
]
),
)
Expand Down
5 changes: 3 additions & 2 deletions isabl_cli/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@
"isabl_cli.commands.get_reference",
"isabl_cli.commands.get_results",
"isabl_cli.commands.login",
"isabl_cli.commands.merge_project_analyses",
"isabl_cli.commands.merge_individual_analyses",
"isabl_cli.commands.merge_project_analyses",
"isabl_cli.commands.patch_status",
"isabl_cli.commands.reject_analysis",
"isabl_cli.commands.rerun_signals",
"isabl_cli.commands.run_web_signals",
"isabl_cli.commands.run_signals",
"isabl_cli.commands.run_web_signals",
],
"EXTRA_RAW_DATA_FORMATS": [],
}
Expand Down
25 changes: 20 additions & 5 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from click.testing import CliRunner
import pytest
import click

from isabl_cli import api
from isabl_cli import commands
Expand Down Expand Up @@ -180,7 +178,7 @@ def test_get_bams():
assert "/hello/mars" in result.output


def test_get_data(tmpdir):
def test_get_data():
runner = CliRunner()
experiment = api.create_instance("experiments", **factories.ExperimentFactory())
experiment = data.update_storage_url("experiments", experiment.pk)
Expand Down Expand Up @@ -287,7 +285,7 @@ def test_run_web_signals():


def test_process_finished_tags(tmpdir):
# check that a tagged analysis does NOT get processed to FINISHED
"""Check that a tagged analysis does NOT get processed to FINISHED."""
analysis = api.create_instance(
"analyses",
project_level_analysis=factories.ProjectFactory(),
Expand All @@ -310,7 +308,7 @@ def test_process_finished_tags(tmpdir):


def test_force_process_finished_tags(tmpdir):
# check that a tagged analysis does get processed to FINISHED when forced
"""Check that a tagged analysis does get processed to FINISHED when forced."""
analysis = api.create_instance(
"analyses",
project_level_analysis=factories.ProjectFactory(),
Expand All @@ -324,3 +322,20 @@ def test_force_process_finished_tags(tmpdir):
print(result.output)
analysis = api.get_instance("analyses", analysis["pk"])
assert analysis["status"] == "SUCCEEDED"


def test_rejected_analysis(tmpdir):
"""Check an analysis can be rejected using the command cli."""
analysis = api.create_instance(
"analyses",
status="FINISHED",
storage_url=tmpdir.strpath,
**factories.AnalysisFactory(ran_by=None),
)
runner = CliRunner()
rejection_reason = "This analysis is FAKE."
args = ["--key", analysis["pk"], "--reason", rejection_reason]
runner.invoke(commands.reject_analysis, args, catch_exceptions=False)
analysis = api.get_instance("analyses", analysis["pk"])
assert analysis["status"] == "REJECTED"
assert analysis["notes"] == rejection_reason