NGPIris 5.4.2.dev4__tar.gz → 5.4.2.dev6__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.
Files changed (54) hide show
  1. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/cli/__init__.py +26 -3
  2. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hcp/hcp.py +49 -11
  3. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6/NGPIris.egg-info}/PKG-INFO +1 -1
  4. {ngpiris-5.4.2.dev4/NGPIris.egg-info → ngpiris-5.4.2.dev6}/PKG-INFO +1 -1
  5. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/pyproject.toml +1 -1
  6. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/test_hcp.py +12 -5
  7. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/LICENSE +0 -0
  8. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/MANIFEST.in +0 -0
  9. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/__init__.py +0 -0
  10. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hci/__init__.py +0 -0
  11. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hci/exceptions.py +0 -0
  12. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hci/hci.py +0 -0
  13. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hci/helpers.py +0 -0
  14. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hcp/__init__.py +0 -0
  15. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hcp/exceptions.py +0 -0
  16. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hcp/helpers.py +0 -0
  17. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/hcp/statistics.py +0 -0
  18. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/parse_credentials/__init__.py +0 -0
  19. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/parse_credentials/parse_credentials.py +0 -0
  20. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/utils/__init__.py +0 -0
  21. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris/utils/utils.py +0 -0
  22. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris.egg-info/SOURCES.txt +0 -0
  23. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris.egg-info/dependency_links.txt +0 -0
  24. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris.egg-info/entry_points.txt +0 -0
  25. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris.egg-info/requires.txt +0 -0
  26. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/NGPIris.egg-info/top_level.txt +0 -0
  27. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/README.md +0 -0
  28. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/IRIS_5_changelog.md +0 -0
  29. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/Makefile +0 -0
  30. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.cli.rst +0 -0
  31. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.hci.rst +0 -0
  32. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.hcp.rst +0 -0
  33. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.parse_credentials.rst +0 -0
  34. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.rst +0 -0
  35. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/NGPIris.utils.rst +0 -0
  36. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/Tutorial.md +0 -0
  37. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/conf.py +0 -0
  38. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/index.rst +0 -0
  39. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/make.bat +0 -0
  40. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/docs/modules.rst +0 -0
  41. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/setup.cfg +0 -0
  42. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/80MB_test_file +0 -0
  43. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/a folder of data/80MB_test_file_0 +0 -0
  44. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/a folder of data/80MB_test_file_1 +0 -0
  45. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/complete_creds_0.json +0 -0
  46. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/complete_creds_1.json +0 -0
  47. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/complete_creds_2.json +0 -0
  48. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/incomplete_creds_0.json +0 -0
  49. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/incomplete_creds_1.json +0 -0
  50. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/incomplete_creds_2.json +0 -0
  51. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/incomplete_creds_3.json +0 -0
  52. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/data/incomplete_creds_4.json +0 -0
  53. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/test_hci.py +0 -0
  54. {ngpiris-5.4.2.dev4 → ngpiris-5.4.2.dev6}/tests/test_parse_credentials.py +0 -0
@@ -78,8 +78,25 @@ def cli(context : Context, credentials : str, debug : bool, transfer_config : st
78
78
  help = "Simulate the command execution without making actual changes. Useful for testing and verification",
79
79
  is_flag = True
80
80
  )
81
+ @click.option(
82
+ "-um",
83
+ "--upload_mode",
84
+ 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",
85
+ type = click.Choice(
86
+ ["STANDARD", "SIMPLE", "EQUAL_PARTS"],
87
+ case_sensitive = False
88
+ ),
89
+ default = "STANDARD"
90
+ )
91
+ @click.option(
92
+ "-ep",
93
+ "--equal_parts",
94
+ help = "Supplementary option when using the EQUAL_PARTS upload mode. Splits each file into a given number of parts. Must be a positive integer",
95
+ type = int,
96
+ default = 5
97
+ )
81
98
  @click.pass_context
82
- def upload(context : Context, bucket : str, source : str, destination : str, dry_run : bool):
99
+ def upload(context : Context, bucket : str, source : str, destination : str, dry_run : bool, upload_mode : str, equal_parts : int):
83
100
  """
84
101
  Upload files to an HCP bucket/namespace.
85
102
 
@@ -89,6 +106,12 @@ def upload(context : Context, bucket : str, source : str, destination : str, dry
89
106
 
90
107
  DESTINATION is the destination path on the HCP.
91
108
  """
109
+
110
+ if equal_parts <= 0:
111
+ exit("Error: --equal_parts value must be a positive integer")
112
+
113
+ upload_mode_choice = HCPHandler.UploadMode(upload_mode.lower())
114
+
92
115
  hcph : HCPHandler = get_HCPHandler(context)
93
116
  hcph.mount_bucket(bucket)
94
117
  destination = add_trailing_slash(destination)
@@ -97,14 +120,14 @@ def upload(context : Context, bucket : str, source : str, destination : str, dry
97
120
  if dry_run:
98
121
  click.echo("This command would have uploaded the folder \"" + source + "\" to \"" + destination + "\"")
99
122
  else:
100
- hcph.upload_folder(source, destination)
123
+ hcph.upload_folder(source, destination, upload_mode = upload_mode_choice, equal_parts = equal_parts)
101
124
  else:
102
125
  file_name = Path(source).name
103
126
  destination += file_name
104
127
  if dry_run:
105
128
  click.echo("This command would have uploaded the file \"" + source + "\" to \"" + destination + "\"")
106
129
  else:
107
- hcph.upload_file(source, destination)
130
+ hcph.upload_file(source, destination, upload_mode = upload_mode_choice, equal_parts = equal_parts)
108
131
 
109
132
  @cli.command()
110
133
  @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
@@ -496,13 +512,20 @@ class HCPHandler:
496
512
  if "\\" in local_file_path:
497
513
  raise RuntimeError("The \"\\\" character is not allowed in the file path")
498
514
 
499
- #if self.object_exists(key):
500
- # raise ObjectAlreadyExist("The object \"" + key + "\" already exist in the mounted bucket")
501
- if False:
502
- pass
515
+ if self.object_exists(key):
516
+ raise ObjectAlreadyExist("The object \"" + key + "\" already exist in the mounted bucket")
503
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
+
504
528
  if show_progress_bar:
505
- file_size : int = stat(local_file_path).st_size
506
529
  with tqdm(
507
530
  total = file_size,
508
531
  unit = "B",
@@ -513,7 +536,7 @@ class HCPHandler:
513
536
  Filename = local_file_path,
514
537
  Bucket = self.bucket_name,
515
538
  Key = key,
516
- Config = self.transfer_config,
539
+ Config = config,
517
540
  Callback = lambda bytes_transferred : pbar.update(bytes_transferred)
518
541
  )
519
542
  else:
@@ -521,12 +544,11 @@ class HCPHandler:
521
544
  Filename = local_file_path,
522
545
  Bucket = self.bucket_name,
523
546
  Key = key,
524
- Config = self.transfer_config,
547
+ Config = config,
525
548
  )
526
549
 
527
-
528
550
  @check_mounted
529
- 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:
530
552
  """
531
553
  Upload the contents of a folder to the mounted bucket
532
554
 
@@ -538,6 +560,16 @@ class HCPHandler:
538
560
 
539
561
  :param show_progress_bar: Boolean choice of displaying a progress bar. Defaults to True
540
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
541
573
  """
542
574
  raise_path_error(local_folder_path)
543
575
 
@@ -546,7 +578,13 @@ class HCPHandler:
546
578
  filenames = listdir(local_folder_path)
547
579
 
548
580
  for filename in filenames:
549
- self.upload_file(local_folder_path + filename, key + filename, show_progress_bar = show_progress_bar)
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
+ )
550
588
 
551
589
  @check_mounted
552
590
  def delete_objects(self, keys : list[str], verbose : bool = True) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: NGPIris
3
- Version: 5.4.2.dev4
3
+ Version: 5.4.2.dev6
4
4
  Author-email: Erik Brink <erik.brink@gu.se>, Isak Sylvin <isak.sylvin@gu.se>
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: NGPIris
3
- Version: 5.4.2.dev4
3
+ Version: 5.4.2.dev6
4
4
  Author-email: Erik Brink <erik.brink@gu.se>, Isak Sylvin <isak.sylvin@gu.se>
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "NGPIris"
3
- version = "5.4.2.dev4"
3
+ version = "5.4.2.dev6"
4
4
  readme = "README.md"
5
5
  dependencies = [
6
6
  "requests >= 2.31.0",
@@ -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