NGPIris 5.3.1__tar.gz → 5.4.0__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.3.1 → ngpiris-5.4.0}/NGPIris/cli/__init__.py +3 -34
  2. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hcp/hcp.py +41 -28
  3. {ngpiris-5.3.1 → ngpiris-5.4.0/NGPIris.egg-info}/PKG-INFO +1 -1
  4. {ngpiris-5.3.1/NGPIris.egg-info → ngpiris-5.4.0}/PKG-INFO +1 -1
  5. {ngpiris-5.3.1 → ngpiris-5.4.0}/pyproject.toml +1 -1
  6. {ngpiris-5.3.1 → ngpiris-5.4.0}/LICENSE +0 -0
  7. {ngpiris-5.3.1 → ngpiris-5.4.0}/MANIFEST.in +0 -0
  8. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/__init__.py +0 -0
  9. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hci/__init__.py +0 -0
  10. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hci/exceptions.py +0 -0
  11. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hci/hci.py +0 -0
  12. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hci/helpers.py +0 -0
  13. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hcp/__init__.py +0 -0
  14. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hcp/exceptions.py +0 -0
  15. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hcp/helpers.py +0 -0
  16. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/hcp/statistics.py +0 -0
  17. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/parse_credentials/__init__.py +0 -0
  18. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/parse_credentials/parse_credentials.py +0 -0
  19. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/utils/__init__.py +0 -0
  20. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris/utils/utils.py +0 -0
  21. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris.egg-info/SOURCES.txt +0 -0
  22. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris.egg-info/dependency_links.txt +0 -0
  23. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris.egg-info/entry_points.txt +0 -0
  24. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris.egg-info/requires.txt +0 -0
  25. {ngpiris-5.3.1 → ngpiris-5.4.0}/NGPIris.egg-info/top_level.txt +0 -0
  26. {ngpiris-5.3.1 → ngpiris-5.4.0}/README.md +0 -0
  27. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/IRIS_5_changelog.md +0 -0
  28. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/Makefile +0 -0
  29. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.cli.rst +0 -0
  30. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.hci.rst +0 -0
  31. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.hcp.rst +0 -0
  32. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.parse_credentials.rst +0 -0
  33. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.rst +0 -0
  34. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/NGPIris.utils.rst +0 -0
  35. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/Tutorial.md +0 -0
  36. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/conf.py +0 -0
  37. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/index.rst +0 -0
  38. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/make.bat +0 -0
  39. {ngpiris-5.3.1 → ngpiris-5.4.0}/docs/modules.rst +0 -0
  40. {ngpiris-5.3.1 → ngpiris-5.4.0}/setup.cfg +0 -0
  41. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/80MB_test_file +0 -0
  42. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/a folder of data/80MB_test_file_0 +0 -0
  43. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/a folder of data/80MB_test_file_1 +0 -0
  44. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/complete_creds_0.json +0 -0
  45. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/complete_creds_1.json +0 -0
  46. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/complete_creds_2.json +0 -0
  47. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/incomplete_creds_0.json +0 -0
  48. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/incomplete_creds_1.json +0 -0
  49. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/incomplete_creds_2.json +0 -0
  50. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/incomplete_creds_3.json +0 -0
  51. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/data/incomplete_creds_4.json +0 -0
  52. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/test_hci.py +0 -0
  53. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/test_hcp.py +0 -0
  54. {ngpiris-5.3.1 → ngpiris-5.4.0}/tests/test_parse_credentials.py +0 -0
@@ -4,11 +4,7 @@ from click.core import Context
4
4
  from json import dump
5
5
  from pathlib import Path
6
6
  from boto3 import set_stream_logger
7
- from botocore.paginate import PageIterator, Paginator
8
7
  from typing import Any, Generator
9
- from os import get_terminal_size
10
- from math import floor
11
- from tabulate import tabulate
12
8
  from bitmath import Byte, TiB
13
9
 
14
10
  from NGPIris.hcp import HCPHandler
@@ -26,36 +22,9 @@ def _list_objects_generator(hcph : HCPHandler, path : str, name_only : bool, fil
26
22
  different from `list_objects` in `hcp.py` in order to make the output
27
23
  printable in a terminal
28
24
  """
29
- paginator : Paginator = hcph.s3_client.get_paginator("list_objects_v2")
30
- pages : PageIterator = paginator.paginate(Bucket = hcph.bucket_name, Prefix = path)
31
- (nb_of_cols, _) = get_terminal_size()
32
- max_width = floor(nb_of_cols / 5)
33
- if (not name_only):
34
- yield tabulate(
35
- [],
36
- headers = ["Key", "LastModified", "ETag", "Size", "StorageClass"],
37
- tablefmt = "plain",
38
- stralign = "center"
39
- ) + "\n" + "-"*nb_of_cols + "\n"
40
- if files_only:
41
- filter_string = "Contents[?!ends_with(Key, '/')][]" # filter objects that does not end with "/"
42
- else:
43
- filter_string = "Contents[*][]"
44
- for object in pages.search(filter_string):
45
- if name_only:
46
- yield str(object["Key"]) + "\n"
47
- else:
48
- yield tabulate(
49
- [
50
- [str(object["Key"]),
51
- str(object["LastModified"]),
52
- str(object["ETag"]),
53
- str(object["Size"]),
54
- str(object["StorageClass"])]
55
- ],
56
- maxcolwidths = max_width,
57
- tablefmt = "plain"
58
- ) + "\n" + "-"*nb_of_cols + "\n"
25
+ objects = hcph.list_objects(path, name_only, files_only)
26
+ for obj in objects:
27
+ yield str(obj) + "\n"
59
28
 
60
29
  def object_is_folder(object_path : str, hcph : HCPHandler) -> bool:
61
30
  return (object_path[-1] == "/") and (hcph.get_object(object_path)["ContentLength"] == 0)
@@ -256,51 +256,64 @@ class HCPHandler:
256
256
  response = self.get_response("/namespaces")
257
257
  list_of_buckets : list[str] = response["name"]
258
258
  return list_of_buckets
259
-
259
+
260
260
  @check_mounted
261
261
  def list_objects(self, path_key : str = "", name_only : bool = False, files_only : bool = False) -> Generator:
262
262
  """
263
263
  List all objects in the mounted bucket as a generator. If one wishes to
264
264
  get the result as a list, use :py:function:`list` to type cast the generator
265
265
 
266
- :param path_key: Filter string for which keys to list, specifically for finding objects in certain folders.
266
+ :param path_key: Filter string for which keys to list, specifically for finding objects in certain folders. Defaults to \"the root\" of the bucket
267
267
  :type path_key: str, optional
268
268
  :param name_only: If True, yield only a the object names. If False, yield the full metadata about each object. Defaults to False.
269
269
  :type name_only: bool, optional
270
270
  :param files_only: If true, only yield file objects. Defaults to False
271
271
  :type files_only: bool, optional
272
- :yield: A generator of all objects in a bucket
272
+ :yield: A generator of all objects in specified folder in a bucket
273
273
  :rtype: Generator
274
274
  """
275
275
  paginator : Paginator = self.s3_client.get_paginator("list_objects_v2")
276
- pages : PageIterator = paginator.paginate(Bucket = self.bucket_name, Prefix = path_key)
277
-
278
- if files_only:
279
- filter_string = "Contents[?!ends_with(Key, '/')][]"
280
- else:
281
- filter_string = "Contents[*][]"
282
-
283
- split_path_key = len(path_key.split("/")) + 1
276
+ pages : PageIterator = paginator.paginate(Bucket = self.bucket_name, Prefix = path_key, Delimiter = "/")
284
277
 
285
- pages_filtered = pages.search(filter_string)
286
- for object in pages_filtered:
287
- # If there are no objects in the bucket, then `object` will be None,
288
- # which means that we should break out of the for loop
289
- if not object:
278
+ for page in pages:
279
+ page : dict | None
280
+ # Check if `page` is None
281
+ if not page:
290
282
  break
291
283
 
292
- # Split the object key by "/"
293
- split_object = object["Key"].split("/")
294
- # Check if the object is within the specified path_key depth
295
- if len(split_object) <= split_path_key:
296
- # Skip objects that are not at the desired depth
297
- if (len(split_object) == split_path_key) and split_object[-1]:
298
- continue
299
-
300
- if name_only:
301
- yield str(object["Key"])
302
- else:
303
- yield object
284
+ if files_only:
285
+ for file_object in page.get("Contents", []):
286
+ file_object : dict
287
+ if file_object["Key"] != path_key:
288
+ file_object["IsFile"] = True
289
+ if name_only:
290
+ yield file_object["Key"]
291
+ else:
292
+ yield file_object
293
+ else:
294
+ for folder_object in page.get("CommonPrefixes", []):
295
+ folder_object : dict
296
+ folder_object_metadata = self.get_object(folder_object["Prefix"])
297
+
298
+ if name_only:
299
+ yield folder_object["Prefix"]
300
+ else:
301
+ yield {
302
+ "Key" : folder_object["Prefix"],
303
+ "LastModified" : folder_object_metadata["LastModified"],
304
+ "ETag" : folder_object_metadata["ETag"],
305
+ "IsFile" : False,
306
+ }
307
+
308
+ for file_object in page.get("Contents", []):
309
+ file_object : dict
310
+ if file_object["Key"] != path_key:
311
+ file_object["IsFile"] = True
312
+ if name_only:
313
+ yield file_object["Key"]
314
+ else:
315
+ yield file_object
316
+
304
317
 
305
318
  @check_mounted
306
319
  def get_object(self, key : str) -> dict:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: NGPIris
3
- Version: 5.3.1
3
+ Version: 5.4.0
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.2
2
2
  Name: NGPIris
3
- Version: 5.3.1
3
+ Version: 5.4.0
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.3.1"
3
+ version = "5.4.0"
4
4
  readme = "README.md"
5
5
  dependencies = [
6
6
  "requests >= 2.31.0",
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