NGPIris 5.4.1__tar.gz → 5.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/cli/__init__.py +45 -7
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hcp/hcp.py +47 -7
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/PKG-INFO +1 -1
- {ngpiris-5.4.1 → ngpiris-5.4.2}/PKG-INFO +1 -1
- {ngpiris-5.4.1 → ngpiris-5.4.2}/pyproject.toml +1 -1
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/test_hcp.py +12 -5
- {ngpiris-5.4.1 → ngpiris-5.4.2}/LICENSE +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/MANIFEST.in +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/__init__.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hci/__init__.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hci/exceptions.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hci/hci.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hci/helpers.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hcp/__init__.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hcp/exceptions.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hcp/helpers.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/hcp/statistics.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/parse_credentials/__init__.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/parse_credentials/parse_credentials.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/utils/__init__.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris/utils/utils.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/SOURCES.txt +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/dependency_links.txt +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/entry_points.txt +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/requires.txt +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/NGPIris.egg-info/top_level.txt +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/README.md +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/IRIS_5_changelog.md +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/Makefile +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.cli.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.hci.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.hcp.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.parse_credentials.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/NGPIris.utils.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/Tutorial.md +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/conf.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/index.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/make.bat +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/docs/modules.rst +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/setup.cfg +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/80MB_test_file +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/a folder of data/80MB_test_file_0 +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/a folder of data/80MB_test_file_1 +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/complete_creds_0.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/complete_creds_1.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/complete_creds_2.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/incomplete_creds_0.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/incomplete_creds_1.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/incomplete_creds_2.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/incomplete_creds_3.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/data/incomplete_creds_4.json +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/test_hci.py +0 -0
- {ngpiris-5.4.1 → ngpiris-5.4.2}/tests/test_parse_credentials.py +0 -0
|
@@ -6,6 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
from boto3 import set_stream_logger
|
|
7
7
|
from typing import Any, Generator
|
|
8
8
|
from bitmath import Byte, TiB
|
|
9
|
+
import sys
|
|
9
10
|
|
|
10
11
|
from NGPIris.hcp import HCPHandler
|
|
11
12
|
|
|
@@ -41,19 +42,32 @@ def add_trailing_slash(path : str) -> str:
|
|
|
41
42
|
help = "Get the debug log for running a command",
|
|
42
43
|
is_flag = True
|
|
43
44
|
)
|
|
45
|
+
@click.option(
|
|
46
|
+
"-tc",
|
|
47
|
+
"--transfer_config",
|
|
48
|
+
help = "Use a custom transfer config for uploads or downloads",
|
|
49
|
+
)
|
|
44
50
|
@click.version_option(package_name = "NGPIris")
|
|
45
51
|
@click.pass_context
|
|
46
|
-
def cli(context : Context, credentials : str, debug : bool):
|
|
52
|
+
def cli(context : Context, credentials : str, debug : bool, transfer_config : str):
|
|
47
53
|
"""
|
|
48
54
|
NGP Intelligence and Repository Interface Software, IRIS.
|
|
49
55
|
|
|
50
56
|
CREDENTIALS refers to the path to the JSON credentials file.
|
|
51
57
|
"""
|
|
58
|
+
|
|
59
|
+
if transfer_config:
|
|
60
|
+
context.ensure_object(dict)
|
|
61
|
+
context.obj["hcph"] = HCPHandler(credentials, custom_config_path = transfer_config)
|
|
62
|
+
else:
|
|
63
|
+
context.ensure_object(dict)
|
|
64
|
+
context.obj["hcph"] = HCPHandler(credentials)
|
|
65
|
+
|
|
52
66
|
if debug:
|
|
53
67
|
set_stream_logger(name="")
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
click.echo(
|
|
69
|
+
context.obj["hcph"].transfer_config.__dict__
|
|
70
|
+
)
|
|
57
71
|
|
|
58
72
|
@cli.command()
|
|
59
73
|
@click.argument("bucket")
|
|
@@ -65,8 +79,25 @@ def cli(context : Context, credentials : str, debug : bool):
|
|
|
65
79
|
help = "Simulate the command execution without making actual changes. Useful for testing and verification",
|
|
66
80
|
is_flag = True
|
|
67
81
|
)
|
|
82
|
+
@click.option(
|
|
83
|
+
"-um",
|
|
84
|
+
"--upload_mode",
|
|
85
|
+
help = "Choose an upload method. Default upload mode is STANDARD which uses a basic multipart upload. Use another mode than STANDARD if that mode misbehaves",
|
|
86
|
+
type = click.Choice(
|
|
87
|
+
["STANDARD", "SIMPLE", "EQUAL_PARTS"],
|
|
88
|
+
case_sensitive = False
|
|
89
|
+
),
|
|
90
|
+
default = "STANDARD"
|
|
91
|
+
)
|
|
92
|
+
@click.option(
|
|
93
|
+
"-ep",
|
|
94
|
+
"--equal_parts",
|
|
95
|
+
help = "Supplementary option when using the EQUAL_PARTS upload mode. Splits each file into a given number of parts. Must be a positive integer",
|
|
96
|
+
type = int,
|
|
97
|
+
default = 5
|
|
98
|
+
)
|
|
68
99
|
@click.pass_context
|
|
69
|
-
def upload(context : Context, bucket : str, source : str, destination : str, dry_run : bool):
|
|
100
|
+
def upload(context : Context, bucket : str, source : str, destination : str, dry_run : bool, upload_mode : str, equal_parts : int):
|
|
70
101
|
"""
|
|
71
102
|
Upload files to an HCP bucket/namespace.
|
|
72
103
|
|
|
@@ -76,6 +107,13 @@ def upload(context : Context, bucket : str, source : str, destination : str, dry
|
|
|
76
107
|
|
|
77
108
|
DESTINATION is the destination path on the HCP.
|
|
78
109
|
"""
|
|
110
|
+
|
|
111
|
+
if equal_parts <= 0:
|
|
112
|
+
click.echo("Error: --equal_parts value must be a positive integer", err=True)
|
|
113
|
+
sys.exit(1)
|
|
114
|
+
|
|
115
|
+
upload_mode_choice = HCPHandler.UploadMode(upload_mode.lower())
|
|
116
|
+
|
|
79
117
|
hcph : HCPHandler = get_HCPHandler(context)
|
|
80
118
|
hcph.mount_bucket(bucket)
|
|
81
119
|
destination = add_trailing_slash(destination)
|
|
@@ -84,14 +122,14 @@ def upload(context : Context, bucket : str, source : str, destination : str, dry
|
|
|
84
122
|
if dry_run:
|
|
85
123
|
click.echo("This command would have uploaded the folder \"" + source + "\" to \"" + destination + "\"")
|
|
86
124
|
else:
|
|
87
|
-
hcph.upload_folder(source, destination)
|
|
125
|
+
hcph.upload_folder(source, destination, upload_mode = upload_mode_choice, equal_parts = equal_parts)
|
|
88
126
|
else:
|
|
89
127
|
file_name = Path(source).name
|
|
90
128
|
destination += file_name
|
|
91
129
|
if dry_run:
|
|
92
130
|
click.echo("This command would have uploaded the file \"" + source + "\" to \"" + destination + "\"")
|
|
93
131
|
else:
|
|
94
|
-
hcph.upload_file(source, destination)
|
|
132
|
+
hcph.upload_file(source, destination, upload_mode = upload_mode_choice, equal_parts = equal_parts)
|
|
95
133
|
|
|
96
134
|
@cli.command()
|
|
97
135
|
@click.argument("bucket")
|
|
@@ -42,6 +42,7 @@ from urllib3 import disable_warnings
|
|
|
42
42
|
from tqdm import tqdm
|
|
43
43
|
from bitmath import TiB, Byte
|
|
44
44
|
|
|
45
|
+
from enum import Enum
|
|
45
46
|
from typing import Generator
|
|
46
47
|
|
|
47
48
|
_KB = 1024
|
|
@@ -468,9 +469,14 @@ class HCPHandler:
|
|
|
468
469
|
self.download_file(object["Key"], p.as_posix(), show_progress_bar = show_progress_bar)
|
|
469
470
|
else:
|
|
470
471
|
raise NotADirectory(local_folder_path + " is not a directory")
|
|
472
|
+
|
|
473
|
+
class UploadMode(Enum):
|
|
474
|
+
STANDARD = "standard"
|
|
475
|
+
SIMPLE = "simple"
|
|
476
|
+
EQUAL_PARTS = "equal_parts"
|
|
471
477
|
|
|
472
478
|
@check_mounted
|
|
473
|
-
def upload_file(self, local_file_path : str, key : str = "", show_progress_bar : bool = True) -> None:
|
|
479
|
+
def upload_file(self, local_file_path : str, key : str = "", show_progress_bar : bool = True, upload_mode : UploadMode = UploadMode.STANDARD, equal_parts : int = 5) -> None:
|
|
474
480
|
"""
|
|
475
481
|
Upload one file to the mounted bucket
|
|
476
482
|
|
|
@@ -483,6 +489,16 @@ class HCPHandler:
|
|
|
483
489
|
:param show_progress_bar: Boolean choice of displaying a progress bar. Defaults to True
|
|
484
490
|
:type show_progress_bar: bool, optional
|
|
485
491
|
|
|
492
|
+
:param upload_mode:
|
|
493
|
+
The upload mode of the transfer is any of the following:
|
|
494
|
+
HCPHandler.UploadMode.STANDARD,
|
|
495
|
+
HCPHandler.UploadMode.SIMPLE,
|
|
496
|
+
HCPHandler.UploadMode.EQUAL_PARTS\n
|
|
497
|
+
:type upload_mode: UploadMode, optional
|
|
498
|
+
|
|
499
|
+
:param equal_parts: The number of equal parts that each file should be divided into when using the HCPHandler.UploadMode.EQUAL_PARTS mode. Default is 5
|
|
500
|
+
:type equal_parts: int, optional
|
|
501
|
+
|
|
486
502
|
:raises RuntimeError: If the \"\\\" is used in the file path
|
|
487
503
|
|
|
488
504
|
:raises ObjectAlreadyExist: If the object already exist on the mounted bucket
|
|
@@ -499,8 +515,17 @@ class HCPHandler:
|
|
|
499
515
|
if self.object_exists(key):
|
|
500
516
|
raise ObjectAlreadyExist("The object \"" + key + "\" already exist in the mounted bucket")
|
|
501
517
|
else:
|
|
518
|
+
file_size : int = stat(local_file_path).st_size
|
|
519
|
+
|
|
520
|
+
match upload_mode:
|
|
521
|
+
case HCPHandler.UploadMode.STANDARD:
|
|
522
|
+
config = self.transfer_config
|
|
523
|
+
case HCPHandler.UploadMode.SIMPLE:
|
|
524
|
+
config = TransferConfig(multipart_chunksize = file_size)
|
|
525
|
+
case HCPHandler.UploadMode.EQUAL_PARTS:
|
|
526
|
+
config = TransferConfig(multipart_chunksize = round(file_size / equal_parts))
|
|
527
|
+
|
|
502
528
|
if show_progress_bar:
|
|
503
|
-
file_size : int = stat(local_file_path).st_size
|
|
504
529
|
with tqdm(
|
|
505
530
|
total = file_size,
|
|
506
531
|
unit = "B",
|
|
@@ -511,7 +536,7 @@ class HCPHandler:
|
|
|
511
536
|
Filename = local_file_path,
|
|
512
537
|
Bucket = self.bucket_name,
|
|
513
538
|
Key = key,
|
|
514
|
-
Config =
|
|
539
|
+
Config = config,
|
|
515
540
|
Callback = lambda bytes_transferred : pbar.update(bytes_transferred)
|
|
516
541
|
)
|
|
517
542
|
else:
|
|
@@ -519,12 +544,11 @@ class HCPHandler:
|
|
|
519
544
|
Filename = local_file_path,
|
|
520
545
|
Bucket = self.bucket_name,
|
|
521
546
|
Key = key,
|
|
522
|
-
Config =
|
|
547
|
+
Config = config,
|
|
523
548
|
)
|
|
524
549
|
|
|
525
|
-
|
|
526
550
|
@check_mounted
|
|
527
|
-
def upload_folder(self, local_folder_path : str, key : str = "", show_progress_bar : bool = True) -> None:
|
|
551
|
+
def upload_folder(self, local_folder_path : str, key : str = "", show_progress_bar : bool = True, upload_mode : UploadMode = UploadMode.STANDARD, equal_parts : int = 5) -> None:
|
|
528
552
|
"""
|
|
529
553
|
Upload the contents of a folder to the mounted bucket
|
|
530
554
|
|
|
@@ -536,6 +560,16 @@ class HCPHandler:
|
|
|
536
560
|
|
|
537
561
|
:param show_progress_bar: Boolean choice of displaying a progress bar. Defaults to True
|
|
538
562
|
:type show_progress_bar: bool, optional
|
|
563
|
+
|
|
564
|
+
:param upload_mode:
|
|
565
|
+
The upload mode of the transfer is any of the following:
|
|
566
|
+
HCPHandler.UploadMode.STANDARD,
|
|
567
|
+
HCPHandler.UploadMode.SIMPLE,
|
|
568
|
+
HCPHandler.UploadMode.EQUAL_PARTS\n
|
|
569
|
+
:type upload_mode: UploadMode, optional
|
|
570
|
+
|
|
571
|
+
:param equal_parts: The number of equal parts that each file should be divided into when using the HCPHandler.UploadMode.EQUAL_PARTS mode. Default is 5
|
|
572
|
+
:type equal_parts: int, optional
|
|
539
573
|
"""
|
|
540
574
|
raise_path_error(local_folder_path)
|
|
541
575
|
|
|
@@ -544,7 +578,13 @@ class HCPHandler:
|
|
|
544
578
|
filenames = listdir(local_folder_path)
|
|
545
579
|
|
|
546
580
|
for filename in filenames:
|
|
547
|
-
self.upload_file(
|
|
581
|
+
self.upload_file(
|
|
582
|
+
local_folder_path + filename,
|
|
583
|
+
key + filename,
|
|
584
|
+
show_progress_bar = show_progress_bar,
|
|
585
|
+
upload_mode = upload_mode,
|
|
586
|
+
equal_parts = equal_parts
|
|
587
|
+
)
|
|
548
588
|
|
|
549
589
|
@check_mounted
|
|
550
590
|
def delete_objects(self, keys : list[str], verbose : bool = True) -> None:
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from filecmp import cmp
|
|
5
4
|
from typing import Any, Callable
|
|
6
|
-
|
|
7
5
|
from conftest import CustomConfig
|
|
8
|
-
|
|
9
6
|
from NGPIris.hcp import HCPHandler
|
|
7
|
+
from icecream import ic
|
|
10
8
|
|
|
11
9
|
# --------------------------- Helper fucntions ---------------------------------
|
|
12
10
|
|
|
@@ -70,6 +68,15 @@ def test_upload_file(custom_config : CustomConfig) -> None:
|
|
|
70
68
|
show_progress_bar = False
|
|
71
69
|
)
|
|
72
70
|
|
|
71
|
+
# Test every upload mode
|
|
72
|
+
for mode in HCPHandler.UploadMode:
|
|
73
|
+
ic(mode, custom_config.test_file_path + "_" + str(mode).replace(".", "_"))
|
|
74
|
+
custom_config.hcp_h.upload_file(
|
|
75
|
+
custom_config.test_file_path,
|
|
76
|
+
custom_config.test_file_path + "_" + str(mode).replace(".", "_"),
|
|
77
|
+
upload_mode = mode
|
|
78
|
+
)
|
|
79
|
+
|
|
73
80
|
def test_upload_file_without_mounting(custom_config : CustomConfig) -> None:
|
|
74
81
|
_hcp_h = custom_config.hcp_h
|
|
75
82
|
_without_mounting(_hcp_h, HCPHandler.upload_file)
|
|
@@ -119,8 +126,6 @@ def test_get_file_in_sub_directory(custom_config : CustomConfig) -> None:
|
|
|
119
126
|
assert custom_config.hcp_h.object_exists(custom_config.test_file_path)
|
|
120
127
|
assert custom_config.hcp_h.get_object(custom_config.test_file_path)
|
|
121
128
|
|
|
122
|
-
from icecream import ic
|
|
123
|
-
|
|
124
129
|
def test_download_file(custom_config : CustomConfig) -> None:
|
|
125
130
|
test_mount_bucket(custom_config)
|
|
126
131
|
Path(custom_config.result_path).mkdir()
|
|
@@ -215,6 +220,8 @@ def test_delete_file(custom_config : CustomConfig) -> None:
|
|
|
215
220
|
test_mount_bucket(custom_config)
|
|
216
221
|
custom_config.hcp_h.delete_object(custom_config.test_file_path)
|
|
217
222
|
custom_config.hcp_h.delete_object(custom_config.test_file_path + "_no_progress_bar")
|
|
223
|
+
for mode in HCPHandler.UploadMode:
|
|
224
|
+
custom_config.hcp_h.delete_object(custom_config.test_file_path + "_" + str(mode).replace(".", "_"))
|
|
218
225
|
custom_config.hcp_h.delete_object("a_sub_directory/a_file")
|
|
219
226
|
custom_config.hcp_h.delete_object("a_sub_directory")
|
|
220
227
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|