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

EVA-3400 Implement submission ID persistence and retrieval for user sessions #12

Merged
merged 5 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
20 changes: 20 additions & 0 deletions cli/eva_sub_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from argparse import ArgumentParser

from ebi_eva_common_pyutils.logger import logging_config

from cli.submit import StudySubmitter

if __name__ == "__main__":
argparse = ArgumentParser(description='EVA Submission CLI')
argparse.add_argument('--submission-dir', required=True, type=str,
help='Full path to the submission directory where all submission info is/will be stored')
argparse.add_argument('--resume', action='store_true', default=False, help='resume an existing submission')
args = argparse.parse_args()

logging_config.add_stdout_handler()

submitter = StudySubmitter()
if args.resume:
submitter.upload_submission(args.submission_dir)
else:
submitter.submit(args.submission_dir)
51 changes: 40 additions & 11 deletions cli/submit.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#!/usr/bin/env python
import json
import requests
import os

import requests
import yaml
from ebi_eva_common_pyutils.logger import logging_config

from cli.auth import get_auth

logger = logging_config.get_logger(__name__)
SUB_CLI_CONFIG_FILE = ".eva-sub-cli-config.yml"
SUB_CLI_CONFIG_KEY_SUBMISSION_ID = "submission_id"
SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL = "submission_upload_url"
SUBMISSION_INITIATE_URL = "http://www.ebi.ac.uk/eva/v1/submission/initiate"


Expand All @@ -14,21 +19,45 @@ def __init__(self, submission_initiate_url=SUBMISSION_INITIATE_URL):
self.auth = get_auth()
self.submission_initiate_url = submission_initiate_url

def create_submission_config_file(self, submission_dir, submission_id, submission_upload_url):
submission_config_file = os.path.join(submission_dir, SUB_CLI_CONFIG_FILE)
config_data = {
SUB_CLI_CONFIG_KEY_SUBMISSION_ID: submission_id,
SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL: submission_upload_url
}
with open(submission_config_file, 'w') as open_file:
yaml.safe_dump(config_data, open_file)

def get_submission_id_and_upload_url(self, submission_dir):
submission_config_file = os.path.join(submission_dir, SUB_CLI_CONFIG_FILE)
if submission_config_file:
with (open(submission_config_file, 'r') as f):
submission_config_data = yaml.safe_load(f)
return submission_config_data[SUB_CLI_CONFIG_KEY_SUBMISSION_ID], submission_config_data[
SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL]
else:
raise FileNotFoundError(f'Could not upload. No config file found for the submission in {submission_dir}')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise FileNotFoundError(f'Could not upload. No config file found for the submission in {submission_dir}')
raise FileNotFoundError(f'Could not upload. No config file found for the submission in {submission_dir}.')

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


# TODO
def upload_submission(self, submission_id, submission_upload_url):
def upload_submission(self, submission_dir, submission_id=None, submission_upload_url=None):
if not submission_id or not submission_upload_url:
submission_id, submission_upload_url = self.get_submission_id_and_upload_url(submission_dir)
pass

def submit(self):
def verify_submission_dir(self, submission_dir):
if not os.path.exists(submission_dir):
os.makedirs(submission_dir)
if not os.access(submission_dir, os.W_OK):
raise Exception(f"The directory '{submission_dir}' does not have write permissions.")


def submit(self, submission_dir):
self.verify_submission_dir(submission_dir)
response = requests.post(self.submission_initiate_url,
headers={'Accept': 'application/hal+json',
'Authorization': 'Bearer ' + self.auth.token})
response.raise_for_status()
response_json = response.json()
logger.info("Submission ID {} received!!".format(response_json["submissionId"]))
self.upload_submission(response_json["submissionId"], response_json["uploadUrl"])


if __name__ == "__main__":
logging_config.add_stdout_handler()
submitter = StudySubmitter()
submitter.submit()
self.create_submission_config_file(submission_dir, response_json["submissionId"], response_json["uploadUrl"])
self.upload_submission(submission_dir, response_json["submissionId"], response_json["uploadUrl"])
63 changes: 61 additions & 2 deletions tests/test_submit.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import json
import os
import shutil
import unittest
from unittest.mock import MagicMock, patch, Mock, PropertyMock

import yaml

from cli import LSRI_CLIENT_ID
from cli.auth import WebinAuth, LSRIAuth
from cli.submit import StudySubmitter
from cli.submit import StudySubmitter, SUB_CLI_CONFIG_FILE, SUB_CLI_CONFIG_KEY_SUBMISSION_ID, \
SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL


class TestSubmit(unittest.TestCase):
Expand All @@ -13,6 +18,11 @@ def setUp(self) -> None:
self.token = 'a token'
with patch('cli.submit.get_auth', return_value=Mock(token=self.token)):
self.submitter = StudySubmitter()
self.test_sub_dir = os.path.join(os.path.dirname(__file__), 'resources', 'test_sub_dir')
shutil.rmtree(self.test_sub_dir, ignore_errors=True)

def tearDown(self) -> None:
shutil.rmtree(self.test_sub_dir, ignore_errors=True)

def test_submit(self):
# Mock the response for post-authentication response from eva-submission-ws
Expand All @@ -24,8 +34,57 @@ def test_submit(self):

# Set the side_effect attribute to return different responses
with patch('cli.submit.requests.post', return_value=mock_submit_response) as mock_post:
self.submitter.submit()
with patch('cli.submit.StudySubmitter.create_submission_config_file'):
self.submitter.submit('test_submission_directory')
mock_post.assert_called_once_with('http://www.ebi.ac.uk/eva/v1/submission/initiate',
headers={'Accept': 'application/hal+json', 'Authorization': 'Bearer a token'})

# TODO: Check that upload_submission was called with submission id

def test_verify_submission_dir(self):
self.submitter.verify_submission_dir(self.test_sub_dir)
assert os.path.exists(self.test_sub_dir)

def test_verify_submission_dircreate_submission_config_file(self):
self.submitter.verify_submission_dir(self.test_sub_dir)
self.submitter.create_submission_config_file(self.test_sub_dir, 1234, "/sub/upload/url")

sub_config_file = os.path.join(self.test_sub_dir, SUB_CLI_CONFIG_FILE)
assert os.path.exists(sub_config_file)

with (open(sub_config_file, 'r') as f):
sub_config_data = yaml.safe_load(f)
assert sub_config_data[SUB_CLI_CONFIG_KEY_SUBMISSION_ID] == 1234
assert sub_config_data[SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL] == "/sub/upload/url"

def test_get_submission_id_and_upload_url(self):
self.submitter.verify_submission_dir(self.test_sub_dir)
self.submitter.create_submission_config_file(self.test_sub_dir, 1234, "/sub/upload/url")

submission_id, upload_url = self.submitter.get_submission_id_and_upload_url(self.test_sub_dir)

assert submission_id == 1234
assert upload_url == "/sub/upload/url"



def test_submit(self):
mock_submit_response = MagicMock()
mock_submit_response.status_code = 200
mock_submit_response.json.return_value = {
"submissionId": "mock_submission_id",
"uploadUrl": "directory to use for upload",
}
with patch('cli.submit.requests.post', return_value=mock_submit_response) as mock_post:
self.submitter.submit(self.test_sub_dir)

assert os.path.exists(self.test_sub_dir)
sub_config_file = os.path.join(self.test_sub_dir, SUB_CLI_CONFIG_FILE)
assert os.path.exists(sub_config_file)
with (open(sub_config_file, 'r') as f):
sub_config_data = yaml.safe_load(f)
assert sub_config_data[SUB_CLI_CONFIG_KEY_SUBMISSION_ID] == "mock_submission_id"
assert sub_config_data[SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL] == "directory to use for upload"



Loading