Skip to content

Commit 9b97f7c

Browse files
committed
fix(download): use record IDs for all local data paths (#167)
When downloading files using `--doi` or `--title` parameters, the download directory was incorrectly named "None" instead of the actual record ID. This commit fixes the problem by dereferencing DOI/title into record ID and using that for storing downloaded files. Also enhances `--help` output to clarify that `--recid`, `--doi` and `--title` options are triggering exact match with no wildcards. Closes #166
1 parent 7d14b38 commit 9b97f7c

2 files changed

Lines changed: 56 additions & 23 deletions

File tree

cernopendata_client/cli.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
# This file is part of cernopendata-client.
33
#
4-
# Copyright (C) 2019, 2020, 2021, 2023 CERN.
4+
# Copyright (C) 2019, 2020, 2021, 2023, 2025 CERN.
55
#
66
# cernopendata-client is free software; you can redistribute it and/or modify
77
# it under the terms of the GPLv3 license; see LICENSE file for more details.
@@ -70,9 +70,9 @@ def version():
7070

7171

7272
@cernopendata_client.command()
73-
@click.option("--recid", type=click.INT, help="Record ID")
74-
@click.option("--doi", help="Digital Object Identifier")
75-
@click.option("--title", help="Title of the record")
73+
@click.option("--recid", type=click.INT, help="Record ID (exact match)")
74+
@click.option("--doi", help="Digital Object Identifier (exact match)")
75+
@click.option("--title", help="Record title (exact match, no wildcards)")
7676
@click.option(
7777
"--output-value",
7878
is_flag=False,
@@ -147,9 +147,9 @@ def get_metadata(server, recid, doi, title, output_value, filters):
147147

148148

149149
@cernopendata_client.command()
150-
@click.option("--recid", type=click.INT, help="Record ID")
151-
@click.option("--doi", help="Digital Object Identifier")
152-
@click.option("--title", help="Record title")
150+
@click.option("--recid", type=click.INT, help="Record ID (exact match)")
151+
@click.option("--doi", help="Digital Object Identifier (exact match)")
152+
@click.option("--title", help="Record title (exact match, no wildcards)")
153153
@click.option(
154154
"--protocol",
155155
default="http",
@@ -197,9 +197,9 @@ def get_file_locations(server, recid, doi, title, protocol, expand, verbose):
197197

198198

199199
@cernopendata_client.command()
200-
@click.option("--recid", type=click.INT, help="Record ID")
201-
@click.option("--doi", help="Digital Object Identifier")
202-
@click.option("--title", help="Record title")
200+
@click.option("--recid", type=click.INT, help="Record ID (exact match)")
201+
@click.option("--doi", help="Digital Object Identifier (exact match)")
202+
@click.option("--title", help="Record title (exact match, no wildcards)")
203203
@click.option(
204204
"--protocol",
205205
default="http",
@@ -311,7 +311,9 @@ def download_files(
311311
validate_retry_limit(retry_limit=retry_limit)
312312
if retry_sleep:
313313
validate_retry_sleep(retry_sleep=retry_sleep)
314+
# Get record metadata and resolve recid from DOI/title if needed
314315
record_json = get_record_as_json(server, recid, doi, title)
316+
record_recid = record_json["metadata"]["recid"]
315317
file_locations_info = get_files_list(server, record_json, protocol, expand)
316318
file_locations = [file_[0] for file_ in file_locations_info]
317319
download_file_locations = []
@@ -353,7 +355,7 @@ def download_files(
353355
sys.exit(0)
354356

355357
total_files = len(download_file_locations)
356-
path = str(recid)
358+
path = record_recid
357359
if not os.path.isdir(path):
358360
try:
359361
os.mkdir(path)
@@ -390,11 +392,11 @@ def download_files(
390392
if verify:
391393
file_info_remote = get_file_info_remote(
392394
server,
393-
recid,
395+
record_recid,
394396
protocol=protocol,
395397
filtered_files=[file_location],
396398
)
397-
file_info_local = get_file_info_local(recid)
399+
file_info_local = get_file_info_local(record_recid)
398400
verify_file_info(file_info_local, file_info_remote)
399401
display_message(
400402
msg_type="info",
@@ -403,19 +405,21 @@ def download_files(
403405

404406

405407
@cernopendata_client.command()
406-
@click.option("--recid", type=click.INT, help="Record ID")
408+
@click.option("--recid", type=click.INT, help="Record ID (exact match)")
409+
@click.option("--doi", help="Digital Object Identifier (exact match)")
410+
@click.option("--title", help="Record title (exact match, no wildcards)")
407411
@click.option(
408412
"--server",
409413
default=SERVER_HTTP_URI,
410414
type=click.STRING,
411415
help="Which CERN Open Data server to query? [default={}]".format(SERVER_HTTP_URI),
412416
)
413-
def verify_files(server, recid):
417+
def verify_files(server, recid, doi, title):
414418
"""Verify downloaded data file integrity.
415419
416-
Select a CERN Open Data bibliographic record by a record ID and
417-
verify integrity of downloaded data files belonging to this
418-
record.
420+
Select a CERN Open Data bibliographic record by a record ID, a
421+
DOI, or a title and verify integrity of downloaded data files
422+
belonging to this record.
419423
420424
Examples: \n
421425
\t $ cernopendata-client verify-files --recid 5500
@@ -425,24 +429,28 @@ def verify_files(server, recid):
425429
if recid is not None:
426430
validate_recid(recid)
427431

432+
# Get record metadata and resolve recid from DOI/title if needed
433+
record_json = get_record_as_json(server, recid, doi, title)
434+
record_recid = record_json["metadata"]["recid"]
435+
428436
# Get remote file information
429-
file_info_remote = get_file_info_remote(server, recid)
437+
file_info_remote = get_file_info_remote(server, record_recid)
430438

431439
# Get local file information
432-
file_info_local = get_file_info_local(recid)
440+
file_info_local = get_file_info_local(record_recid)
433441
if not file_info_local:
434442
display_message(
435443
msg_type="error",
436444
msg="No local files found for record {}. Perhaps run `download-files` first? Exiting.".format(
437-
recid
445+
record_recid
438446
),
439447
)
440448
sys.exit(1)
441449

442450
# Verify number of files
443451
display_message(
444452
msg_type="info",
445-
msg="Verifying number of files for record {}... ".format(recid),
453+
msg="Verifying number of files for record {}... ".format(record_recid),
446454
)
447455
display_message(
448456
msg_type="note",

tests/test_cli_download_files.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of cernopendata-client.
44
#
5-
# Copyright (C) 2020, 2021 CERN.
5+
# Copyright (C) 2020, 2021, 2025 CERN.
66
#
77
# cernopendata-client is free software; you can redistribute it and/or modify
88
# it under the terms of the GPLv3 license; see LICENSE file for more details.
@@ -55,6 +55,31 @@ def test_dry_run_from_doi_wrong():
5555
assert test_result.exit_code == 2
5656

5757

58+
def test_download_files_from_doi_uses_recid_directory(mocker):
59+
"""Test that download-files --doi stores files in recid directory, not 'None'."""
60+
mocker.patch("cernopendata_client.downloader.pycurl_available", False)
61+
# DOI 10.7483/OPENDATA.CMS.W26R.J96R corresponds to recid 461
62+
test_file = "461/readme.txt"
63+
wrong_file = "None/readme.txt"
64+
if os.path.isfile(test_file):
65+
os.remove(test_file)
66+
if os.path.isfile(wrong_file):
67+
os.remove(wrong_file)
68+
test_download_files = CliRunner()
69+
test_result = test_download_files.invoke(
70+
download_files,
71+
["--doi", "10.7483/OPENDATA.CMS.W26R.J96R", "--filter-name", "readme.txt"],
72+
)
73+
assert test_result.exit_code == 0
74+
# File should be in the recid directory (461), not 'None'
75+
assert os.path.isfile(test_file) is True
76+
assert os.path.isfile(wrong_file) is False
77+
assert os.path.getsize(test_file) == 2971
78+
assert test_result.output.endswith("\n==> Success!\n")
79+
if os.path.isfile(test_file):
80+
os.remove(test_file)
81+
82+
5883
def test_download_files_http_pycurl():
5984
"""Test download_files() command with http protocol using pycurl."""
6085
pycurl = pytest.importorskip("pycurl") # noqa: F841

0 commit comments

Comments
 (0)