dcicutils 8.8.3.1b9__tar.gz → 8.8.3.1b12__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/PKG-INFO +1 -1
  2. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/misc_utils.py +42 -0
  3. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/portal_utils.py +8 -6
  4. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/progress_bar.py +14 -17
  5. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/pyproject.toml +1 -1
  6. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/LICENSE.txt +0 -0
  7. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/README.rst +0 -0
  8. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/__init__.py +0 -0
  9. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/base.py +0 -0
  10. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/beanstalk_utils.py +0 -0
  11. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/bundle_utils.py +0 -0
  12. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/captured_output.py +0 -0
  13. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/cloudformation_utils.py +0 -0
  14. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/codebuild_utils.py +0 -0
  15. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/command_utils.py +0 -0
  16. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/common.py +0 -0
  17. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/contribution_scripts.py +0 -0
  18. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/contribution_utils.py +0 -0
  19. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/creds_utils.py +0 -0
  20. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/data_readers.py +0 -0
  21. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/data_utils.py +0 -0
  22. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/datetime_utils.py +0 -0
  23. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/deployment_utils.py +0 -0
  24. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/diff_utils.py +0 -0
  25. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/docker_utils.py +0 -0
  26. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ecr_scripts.py +0 -0
  27. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ecr_utils.py +0 -0
  28. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ecs_utils.py +0 -0
  29. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/env_base.py +0 -0
  30. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/env_manager.py +0 -0
  31. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/env_scripts.py +0 -0
  32. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/env_utils.py +0 -0
  33. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/env_utils_legacy.py +0 -0
  34. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/es_utils.py +0 -0
  35. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/exceptions.py +0 -0
  36. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ff_mocks.py +0 -0
  37. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ff_utils.py +0 -0
  38. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/file_utils.py +0 -0
  39. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/function_cache_decorator.py +0 -0
  40. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/glacier_utils.py +0 -0
  41. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/jh_utils.py +0 -0
  42. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/kibana/dashboards.json +0 -0
  43. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/kibana/readme.md +0 -0
  44. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/lang_utils.py +0 -0
  45. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/c4-infrastructure.jsonc +0 -0
  46. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/c4-python-infrastructure.jsonc +0 -0
  47. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/park-lab-common-server.jsonc +0 -0
  48. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/park-lab-common.jsonc +0 -0
  49. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/park-lab-gpl-pipeline.jsonc +0 -0
  50. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_policies/park-lab-pipeline.jsonc +0 -0
  51. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/license_utils.py +0 -0
  52. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/log_utils.py +0 -0
  53. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/obfuscation_utils.py +0 -0
  54. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/opensearch_utils.py +0 -0
  55. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/portal_object_utils.py +0 -0
  56. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/project_utils.py +0 -0
  57. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/qa_checkers.py +0 -0
  58. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/qa_utils.py +0 -0
  59. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/redis_tools.py +0 -0
  60. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/redis_utils.py +0 -0
  61. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/s3_utils.py +0 -0
  62. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/schema_utils.py +0 -0
  63. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/scripts/publish_to_pypi.py +0 -0
  64. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/scripts/run_license_checker.py +0 -0
  65. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/scripts/view_portal_object.py +0 -0
  66. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/secrets_utils.py +0 -0
  67. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/sheet_utils.py +0 -0
  68. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/snapshot_utils.py +0 -0
  69. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/ssl_certificate_utils.py +0 -0
  70. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/structured_data.py +0 -0
  71. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/submitr/progress_constants.py +0 -0
  72. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/submitr/ref_lookup_strategy.py +0 -0
  73. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/task_utils.py +0 -0
  74. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/tmpfile_utils.py +0 -0
  75. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/trace_utils.py +0 -0
  76. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/validation_utils.py +0 -0
  77. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/variant_utils.py +0 -0
  78. {dcicutils-8.8.3.1b9 → dcicutils-8.8.3.1b12}/dcicutils/zip_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.8.3.1b9
3
+ Version: 8.8.3.1b12
4
4
  Summary: Utility package for interacting with the 4DN Data Portal and other 4DN resources
5
5
  Home-page: https://github.com/4dn-dcic/utils
6
6
  License: MIT
@@ -2571,6 +2571,48 @@ def set_nth(string: str, nth: int, replacement: str) -> str:
2571
2571
  return string[:nth] + replacement + string[nth + 1:] if 0 <= nth < len(string) else string
2572
2572
 
2573
2573
 
2574
+ def format_size(nbytes: Union[int, float], precision: int = 2, nospace: bool = False, terse: bool = False) -> str:
2575
+ if isinstance(nbytes, str) and nbytes.isdigit():
2576
+ nbytes = int(nbytes)
2577
+ elif not isinstance(nbytes, (int, float)):
2578
+ return ""
2579
+ UNITS = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
2580
+ UNITS_TERSE = ['b', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
2581
+ MAX_UNITS_INDEX = len(UNITS) - 1
2582
+ ONE_K = 1024
2583
+ index = 0
2584
+ if (precision := max(precision, 0)) and (nbytes <= ONE_K):
2585
+ precision -= 1
2586
+ while abs(nbytes) >= ONE_K and index < MAX_UNITS_INDEX:
2587
+ nbytes /= ONE_K
2588
+ index += 1
2589
+ if index == 0:
2590
+ nbytes = int(nbytes)
2591
+ return f"{nbytes} byte{'s' if nbytes != 1 else ''}"
2592
+ unit = (UNITS_TERSE if terse else UNITS)[index]
2593
+ return f"{nbytes:.{precision}f}{'' if nospace else ' '}{unit}"
2594
+
2595
+
2596
+ def format_duration(seconds: Union[int, float]) -> str:
2597
+ seconds_actual = seconds
2598
+ seconds = round(max(seconds, 0))
2599
+ durations = [("year", 31536000), ("day", 86400), ("hour", 3600), ("minute", 60), ("second", 1)]
2600
+ parts = []
2601
+ for name, duration in durations:
2602
+ if seconds >= duration:
2603
+ count = seconds // duration
2604
+ seconds %= duration
2605
+ if count != 1:
2606
+ name += "s"
2607
+ parts.append(f"{count} {name}")
2608
+ if len(parts) == 0:
2609
+ return f"{seconds_actual:.1f} seconds"
2610
+ elif len(parts) == 1:
2611
+ return f"{seconds_actual:.1f} seconds"
2612
+ else:
2613
+ return " ".join(parts[:-1]) + " " + parts[-1]
2614
+
2615
+
2574
2616
  class JsonLinesReader:
2575
2617
 
2576
2618
  def __init__(self, fp, padded=False, padding=None):
@@ -282,15 +282,17 @@ class Portal:
282
282
  except Exception:
283
283
  return None
284
284
 
285
- def patch_metadata(self, object_id: str, data: dict) -> Optional[dict]:
285
+ def patch_metadata(self, object_id: str, data: dict, check_only: bool = False) -> Optional[dict]:
286
286
  if self.key:
287
- return patch_metadata(obj_id=object_id, patch_item=data, key=self.key)
288
- return self.patch(f"/{object_id}", data).json()
287
+ return patch_metadata(obj_id=object_id, patch_item=data, key=self.key,
288
+ add_on="check_only=True" if check_only else "")
289
+ return self.patch(f"/{object_id}{'?check_only=True' if check_only else ''}", data).json()
289
290
 
290
- def post_metadata(self, object_type: str, data: dict) -> Optional[dict]:
291
+ def post_metadata(self, object_type: str, data: dict, check_only: bool = False) -> Optional[dict]:
291
292
  if self.key:
292
- return post_metadata(schema_name=object_type, post_item=data, key=self.key)
293
- return self.post(f"/{object_type}", data).json()
293
+ return post_metadata(schema_name=object_type, post_item=data, key=self.key,
294
+ add_on="check_only=True" if check_only else "")
295
+ return self.post(f"/{object_type}{'?check_only=True' if check_only else ''}", data).json()
294
296
 
295
297
  def get_health(self) -> OptionalResponse:
296
298
  return self.get("/health")
@@ -9,7 +9,7 @@ from types import FrameType as frame
9
9
  from typing import Callable, List, Optional, Union
10
10
  from contextlib import contextmanager
11
11
  from dcicutils.command_utils import yes_or_no
12
- from dcicutils.misc_utils import find_nth_from_end, set_nth
12
+ from dcicutils.misc_utils import find_nth_from_end, format_size, set_nth
13
13
 
14
14
 
15
15
  class TQDM(tqdm):
@@ -49,6 +49,7 @@ class ProgressBar:
49
49
 
50
50
  def __init__(self, total: Optional[int] = None,
51
51
  description: Optional[str] = None,
52
+ use_byte_size_for_rate: bool = False,
52
53
  catch_interrupt: bool = True,
53
54
  interrupt: Optional[Callable] = None,
54
55
  interrupt_continue: Optional[Callable] = None,
@@ -59,13 +60,12 @@ class ProgressBar:
59
60
  tidy_output_hack: bool = True,
60
61
  capture_output_for_testing: bool = False) -> None:
61
62
  self._bar = None
63
+ self._started = 0
62
64
  self._disabled = False
63
65
  self._done = False
64
- self._really_done = False
65
- self.foo = time.time()
66
66
  self._tidy_output_hack = (tidy_output_hack is True)
67
- self._started = time.time()
68
67
  self._stop_requested = False
68
+ self._use_byte_size_for_rate = (use_byte_size_for_rate is True and self._tidy_output_hack)
69
69
  # Interrupt handling. We do not do the actual (signal) interrupt setup
70
70
  # in self._initialize as that could be called from a (sub) thread; and in
71
71
  # Python we can only set a signal (SIGINT in our case) on the main thread.
@@ -98,9 +98,13 @@ class ProgressBar:
98
98
  def _initialize(self) -> bool:
99
99
  # Do not actually create the tqdm object unless/until we have a positive total.
100
100
  if (self._bar is None) and (self._total > 0):
101
- bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} | {rate_fmt} | {elapsed}{postfix} | ETA: {remaining} "
101
+ if self._use_byte_size_for_rate:
102
+ bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} | [rate] | {elapsed}{postfix} | ETA: {remaining} "
103
+ else:
104
+ bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} | {rate_fmt} | {elapsed}{postfix} | ETA: {remaining} "
102
105
  self._bar = TQDM(total=self._total, desc=self._description,
103
106
  dynamic_ncols=True, bar_format=bar_format, unit="", file=sys.stdout)
107
+ self._started = time.time()
104
108
  if self._disabled:
105
109
  self._bar.disable = True
106
110
  return True
@@ -155,6 +159,7 @@ class ProgressBar:
155
159
  self.set_total(total, _norefresh=True)
156
160
  self.set_progress(progress, _norefresh=True)
157
161
  self.set_description(description)
162
+ self._started = time.time()
158
163
 
159
164
  def done(self, description: Optional[str] = None) -> None:
160
165
  if self._done or self._bar is None:
@@ -200,14 +205,6 @@ class ProgressBar:
200
205
  def stop_requested(self) -> bool:
201
206
  return self._stop_requested
202
207
 
203
- @property
204
- def started(self) -> None:
205
- return self._started
206
-
207
- @property
208
- def duration(self) -> None:
209
- return time.time() - self._started
210
-
211
208
  @property
212
209
  def captured_output_for_testing(self) -> Optional[List[str]]:
213
210
  return self._captured_output_for_testing
@@ -287,7 +284,7 @@ class ProgressBar:
287
284
  while text.endswith(" "):
288
285
  text = text[:-1]
289
286
  return text
290
- if (not text) or (last_text == text) or self._really_done:
287
+ if (not text) or (last_text == text):
291
288
  return
292
289
  last_text = text
293
290
  if (self._disabled or self._done) and sentinel_internal in text:
@@ -304,11 +301,11 @@ class ProgressBar:
304
301
  # something like "1.54s/" rather than "1.54/s"; something to do with
305
302
  # the unit we gave, which is empty; idunno; just replace it here.
306
303
  text = replace_first(text, "s/ ", "/s ")
304
+ if self._use_byte_size_for_rate and self._bar:
305
+ rate = self._bar.n / (time.time() - self._started)
306
+ text = text.replace("[rate]", f"{format_size(rate)}/s")
307
307
  sys_stdout_write(text)
308
308
  sys.stdout.flush()
309
- if self._done:
310
- self._really_done = True
311
- return
312
309
  if self._captured_output_for_testing is not None:
313
310
  # For testing only we replace vacilliting values in the out like rate,
314
311
  # time elapsed, and ETA with static values; so that something like this:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "dcicutils"
3
- version = "8.8.3.1b9" # TODO: To become 8.8.4
3
+ version = "8.8.3.1b12" # TODO: To become 8.8.4
4
4
  description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
5
5
  authors = ["4DN-DCIC Team <support@4dnucleome.org>"]
6
6
  license = "MIT"
File without changes