diff --git a/cap_client/cap_api.py b/cap_client/cap_api.py index 8d15a0b..448e394 100644 --- a/cap_client/cap_api.py +++ b/cap_client/cap_api.py @@ -268,7 +268,9 @@ def get_field(self, pid, field=None): })['metadata'] fields = field.split('.') if field else [] for x in fields: - dct = dct[x or int(x)] + if x.isdigit(): + x = int(x) + dct = dct[x] return dct def set_field(self, field_name, field_val, pid, filepath=None, diff --git a/cap_client/cli/files_cli.py b/cap_client/cli/files_cli.py index 7f83aed..1241088 100644 --- a/cap_client/cli/files_cli.py +++ b/cap_client/cli/files_cli.py @@ -45,7 +45,7 @@ def files(): default=None, required=True ) -@click.argument('file', type=click.Path(exists=False)) +@click.argument('files', type=click.Path(exists=False), nargs=-1) @click.option( '--output-file', '-o', @@ -63,17 +63,26 @@ def files(): help="Uploads docker image." ) @click.pass_context -def upload(ctx, pid, file, yes, output_file=None, docker=False): +def upload(ctx, pid, files, yes, output_file=None, docker=False): """Upload file to deposit with given pid.""" + # disable file naming when uploading multiple files + if output_file and len(files) > 1: + click.echo("Output file name parameter is ignored when uploading " + "multiple files. The files will be saved with their " + "original file names, i.e. " + ', '.join(files) + ".") try: if docker: - ctx.obj.cap_api.upload_docker_img(pid=pid, img_name=file, - output_img_name=output_file) + for _file in files: + ctx.obj.cap_api.upload_docker_img( + pid=pid, img_name=_file, + output_img_name=output_file) + click.echo("Docker image " + _file + " uploaded successfully.") else: - ctx.obj.cap_api.upload_file( - pid=pid, filepath=file, - output_filename=output_file, yes=yes) - click.echo("File uploaded successfully.") + for _file in files: + ctx.obj.cap_api.upload_file( + pid=pid, filepath=_file, + output_filename=output_file, yes=yes) + click.echo(_file + " uploaded successfully.") except BadStatusCode as e: logging.error(str(e)) diff --git a/cap_client/cli/metadata_cli.py b/cap_client/cli/metadata_cli.py index b59382c..9a46f5f 100644 --- a/cap_client/cli/metadata_cli.py +++ b/cap_client/cli/metadata_cli.py @@ -150,7 +150,7 @@ def get(ctx, field, pid): click.echo(json.dumps(response, indent=4)) - except KeyError: + except (KeyError, TypeError): logging.error('Field {} doesn\'t exist' .format(field)) diff --git a/docs/index.rst b/docs/index.rst index be5052f..1f74e9b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -335,6 +335,10 @@ You need to specify "Very Interesting Description" + cap-client metadata get basic_info.analysis_proponents.2 -p bf6b8501822c4d2ba46028611354df7e + + "John Doe" + Edit Metadata ------------- @@ -373,6 +377,17 @@ You need to specify } } + $ cap-client metadata set stripping_turbo_selection.0.stripping_turbo_line D2XMuMu_PiOSLine -p bf6b8501822c4d2ba46028611354df7e + + { + "$ana_type": "lhcb", + "$schema": "https://analysispreservation.cern.ch/schemas/deposits/records/lhcb-v0.0.1.json", + "stripping_turbo_selection": [ + { + "dataset_type": "mc_data", + "stripping_turbo_line": "D2XMuMu_PiOSLine", + "name": "MC-set",... + Remove Metadata ------------- @@ -554,7 +569,7 @@ You need to specify Upload file ----------- -You can upload a file to an analysis only if you have at least read access to it. +You can upload a file (or multiple files) to an analysis only if you have at least read access to it. You need to specify @@ -566,13 +581,21 @@ You need to specify $ cap-client files upload file.json -p 89b593c498874ec8bcafc88944c458a7 - File uploaded successfully. + file.json uploaded successfully. + + $ cap-client files upload config.txt history.txt dict.json -p bf6b8501822c4d2ba46028611354df7e + + config.txt uploaded successfully. + + history.txt uploaded successfully. + + dict.json uploaded successfully. Upload Docker image ----------- -With the client, you can upload a Docker image that is associated to the analysis. Make sure that the image is present in the system by running the command `docker images` in the command line. The image name should be in the list. In the examples below we use an image called `hello-world`. +With the client, you can upload Docker images that are associated to the analysis. Make sure that the image is present in the system by running the command `docker images` in the command line. The image name should be in the list. In the examples below we use an image called `hello-world`. You need to specify @@ -585,9 +608,17 @@ To upload the image use the command: $ cap-client files upload hello-world --docker --pid 1ed645539e08435ea1bd4aad1360e87b + Docker image hello-world uploaded successfully. + + $ cap-client files upload hello-world centos --docker -p bf6b8501822c4d2ba46028611354df7e + + Docker image hello-world uploaded successfully. + + Docker image centos uploaded successfully. + Optionally you can specify - --output-file the output file name of the image; by default it is the same as the original image name + --output-file the output file name of an image; by default it is the same as the original image name To upload the image with an output file name use the command: diff --git a/tests/test_cap_api.py b/tests/test_cap_api.py index f9c5555..346badf 100644 --- a/tests/test_cap_api.py +++ b/tests/test_cap_api.py @@ -140,6 +140,44 @@ def test_get_field_when_field_unspecified(mock_requests, cap_api, assert resp == record_data['metadata'] +@patch('requests.get') +def test_get_field_when_field_is_number(mock_requests, cap_api, + record_data): + mock_requests.return_value.status_code = 200 + mock_requests.return_value.json.return_value = record_data + + resp = cap_api.get_field('some_pid', '_access.deposit-read.user.0') + + assert resp == \ + record_data["metadata"]["_access"]["deposit-read"]["user"][0] + + +@patch('requests.get') +def test_get_field_when_field_is_number_in_middle(mock_requests, cap_api, + record_data): + mock_requests.return_value.status_code = 200 + mock_requests.return_value.json.return_value = record_data + + resp = cap_api.get_field('some_pid', + 'basic_info.people_info.0.name') + + assert resp == \ + record_data["metadata"]["basic_info"]["people_info"][0]["name"] + + +@patch('requests.get') +def test_get_field_when_field_is_negative_number(mock_requests, cap_api, + record_data): + mock_requests.return_value.status_code = 200 + mock_requests.return_value.json.return_value = record_data + + resp = cap_api.get_field('some_pid', + 'basic_info.people_info.1.name') + + assert resp == \ + record_data["metadata"]["basic_info"]["people_info"][1]["name"] + + @patch('requests.get') def test_get_field_when_field_specified(mock_requests, cap_api, record_data): @@ -172,7 +210,7 @@ def test_ping_method(mock_requests, cap_api): @patch('requests.delete') -def test_delete_method_with_given_pid(mock_requests, cap_api, record_data): +def test_delete_method_with_given_pid(mock_requests, cap_api): mock_requests.return_value.status_code = 204 mock_requests.return_value.json.return_value = '' @@ -206,8 +244,7 @@ def test_get_available_types_returns_all_available_types(mock_requests, @patch('requests.get') -def test_get_permissions(mock_requests, cap_api, - record_data): +def test_get_permissions(mock_requests, cap_api, record_data): mock_requests.return_value.status_code = 200 mock_requests.return_value.json.return_value = record_data