dcicutils 8.8.3__py3-none-any.whl → 8.8.3.1b2__py3-none-any.whl

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.
@@ -9,7 +9,7 @@ _real_stderr = sys.stderr
9
9
 
10
10
 
11
11
  @contextmanager
12
- def captured_output(capture: bool = True):
12
+ def captured_output(capture: bool = True, encoding: Optional[str] = None):
13
13
  """
14
14
  Context manager to capture any/all output to stdout or stderr, and not actually output it to stdout
15
15
  or stderr. Yields and object with a get_captured_output() method to get the output captured thus far,
@@ -24,7 +24,7 @@ def captured_output(capture: bool = True):
24
24
 
25
25
  original_stdout = _real_stdout
26
26
  original_stderr = _real_stderr
27
- captured_output = io.StringIO()
27
+ captured_output = io.StringIO() if not encoding else _EncodedStringIO(encoding)
28
28
 
29
29
  def set_original_output() -> None:
30
30
  sys.stdout = original_stdout
@@ -68,3 +68,19 @@ def uncaptured_output():
68
68
  finally:
69
69
  sys.stdout = original_stdout
70
70
  sys.stderr = original_stderr
71
+
72
+
73
+ class _EncodedStringIO:
74
+ def __init__(self, encoding: str = "utf-8"):
75
+ self.encoding = encoding
76
+ self.buffer = io.BytesIO()
77
+ def write(self, s): # noqa
78
+ self.buffer.write(s.encode(self.encoding))
79
+ def flush(self): # noqa
80
+ self.buffer.flush()
81
+ def getvalue(self): # noqa
82
+ return self.buffer.getvalue().decode(self.encoding)
83
+ def __str__(self): # noqa
84
+ return self.getvalue()
85
+ def __repr__(self): # noqa
86
+ return repr(self.getvalue())
dcicutils/progress_bar.py CHANGED
@@ -5,7 +5,7 @@ import threading
5
5
  import time
6
6
  from tqdm import tqdm
7
7
  from types import FrameType as frame
8
- from typing import Callable, Optional, Union
8
+ from typing import Callable, List, Optional, Union
9
9
  from contextlib import contextmanager
10
10
  from dcicutils.command_utils import yes_or_no
11
11
 
@@ -54,12 +54,11 @@ class ProgressBar:
54
54
  interrupt_exit: bool = False,
55
55
  interrupt_exit_message: Optional[Union[Callable, str]] = None,
56
56
  interrupt_message: Optional[str] = None,
57
- printf: Optional[Callable] = None,
58
- tidy_output_hack: bool = True) -> None:
57
+ tidy_output_hack: bool = True,
58
+ capture_output_for_testing: bool = False) -> None:
59
59
  self._bar = None
60
60
  self._disabled = False
61
61
  self._done = False
62
- self._printf = printf if callable(printf) else print
63
62
  self._tidy_output_hack = (tidy_output_hack is True)
64
63
  self._started = time.time()
65
64
  self._stop_requested = False
@@ -90,7 +89,7 @@ class ProgressBar:
90
89
  self._tidy_output_hack = self._define_tidy_output_hack()
91
90
  self._total = total if isinstance(total, int) and total >= 0 else 0
92
91
  self._description = self._format_description(description)
93
- # self._initialize()
92
+ self._captured_output_for_testing = [] if capture_output_for_testing else None
94
93
 
95
94
  def _initialize(self) -> bool:
96
95
  # Do not actually create the tqdm object unless/until we have a positive total.
@@ -197,6 +196,10 @@ class ProgressBar:
197
196
  def duration(self) -> None:
198
197
  return time.time() - self._started
199
198
 
199
+ @property
200
+ def captured_output_for_testing(self) -> Optional[List[str]]:
201
+ return self._captured_output_for_testing
202
+
200
203
  def _format_description(self, value: str) -> str:
201
204
  if not isinstance(value, str):
202
205
  value = ""
@@ -209,7 +212,7 @@ class ProgressBar:
209
212
  nonlocal self
210
213
  def handle_secondary_interrupt(signum: int, frame: frame) -> None: # noqa
211
214
  nonlocal self
212
- self._printf("\nEnter 'yes' or 'no' or CTRL-\\ to completely abort ...")
215
+ print("\nEnter 'yes' or 'no' or CTRL-\\ to completely abort ...")
213
216
  self.disable()
214
217
  self._interrupt(self) if self._interrupt else None
215
218
  set_interrupt_handler(handle_secondary_interrupt)
@@ -226,7 +229,7 @@ class ProgressBar:
226
229
  restore_interrupt_handler()
227
230
  if self._interrupt_exit_message:
228
231
  if isinstance(interrupt_exit_message := self._interrupt_exit_message(self), str):
229
- self._printf(interrupt_exit_message)
232
+ print(interrupt_exit_message)
230
233
  exit(1)
231
234
  elif interrupt_stop is False or ((interrupt_stop is None) and (self._interrupt_exit is False)):
232
235
  set_interrupt_handler(handle_interrupt)
@@ -261,6 +264,12 @@ class ProgressBar:
261
264
  nonlocal self, sys_stdout_write, sentinel_internal, spina, spini, spinn
262
265
  def replace_first(value: str, match: str, replacement: str) -> str: # noqa
263
266
  return value[:i] + replacement + value[i + len(match):] if (i := value.find(match)) >= 0 else value
267
+ def remove_extra_trailing_spaces(text: str) -> str: # noqa
268
+ while text.endswith(" "):
269
+ text = text[:-1]
270
+ return text
271
+ if not text:
272
+ return
264
273
  if (self._disabled or self._done) and sentinel_internal in text:
265
274
  # Another hack to really disable output on interrupt; in this case we set
266
275
  # tqdm.disable to True, but output can still dribble out, so if the output
@@ -270,11 +279,14 @@ class ProgressBar:
270
279
  spinc = spina[spini % spinn] if not ("100%|" in text) else "| ✓" ; spini += 1 # noqa
271
280
  text = replace_first(text, sentinel_internal, f" {spinc}")
272
281
  text = replace_first(text, "%|", "% ◀|")
282
+ text = remove_extra_trailing_spaces(text)
273
283
  # Another oddity: for the rate sometimes tqdm intermittently prints
274
284
  # something like "1.54s/" rather than "1.54/s"; something to do with
275
285
  # the unit we gave, which is empty; idunno; just replace it here.
276
286
  text = replace_first(text, "s/ ", "/s ")
277
287
  sys_stdout_write(text)
288
+ if self._captured_output_for_testing is not None:
289
+ self._captured_output_for_testing.append(text)
278
290
  sys.stdout.flush()
279
291
  def restore_stdout_write() -> None: # noqa
280
292
  nonlocal sys_stdout_write
@@ -653,7 +653,10 @@ class Schema(SchemaBase):
653
653
  def map_ref(value: str, link_to: str, portal: Optional[Portal], src: Optional[str]) -> Any:
654
654
  nonlocal self, typeinfo
655
655
  if self._norefs:
656
- self._resolved_refs.add((f"/{link_to}/{value}", None))
656
+ if value:
657
+ # Dump the src because this cannot add dictionary to a set; note that
658
+ # this is ONLY used for smaht-submitr/submit-metadata-bundle --info --refs.
659
+ self._resolved_refs.add((f"/{link_to}/{value}", json.dumps(src) if isinstance(src, dict) else None))
657
660
  return value
658
661
  if not value:
659
662
  if (column := typeinfo.get("column")) and column in self.data.get("required", []):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.8.3
3
+ Version: 8.8.3.1b2
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
@@ -2,7 +2,7 @@ dcicutils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  dcicutils/base.py,sha256=gxNEv3DSVUfoX3NToWw7pcCdguxsJ75NDqsPi3wdFG4,5115
3
3
  dcicutils/beanstalk_utils.py,sha256=nHMWfFnZAXFiJh60oVouwbAPMKsQfHnDtkwz_PDE6S4,51434
4
4
  dcicutils/bundle_utils.py,sha256=ZVQcqlt7Yly8-YbL3A-5DW859_hMWpTL6dXtknEYZIw,34669
5
- dcicutils/captured_output.py,sha256=9UorUoA-RSGf7fUILHy73JiZ-mJ1IV-or_JGMyncaMs,2522
5
+ dcicutils/captured_output.py,sha256=2pzkq7vtC47zwsSeXS6cJNxC_LXpUbw6ArudKlJHdb0,3108
6
6
  dcicutils/cloudformation_utils.py,sha256=MtWJrSTXyiImgbPHgRvfH9bWso20ZPLTFJAfhDQSVj4,13786
7
7
  dcicutils/codebuild_utils.py,sha256=CKpmhJ-Z8gYbkt1I2zyMlKtFdsg7T8lqrx3V5ieta-U,1155
8
8
  dcicutils/command_utils.py,sha256=JExll5TMqIcmuiGvuS8q4XDUvoEfi2oSH0E2FVF6suU,15285
@@ -48,7 +48,7 @@ dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmj
48
48
  dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
49
49
  dcicutils/portal_object_utils.py,sha256=gDXRgPsRvqCFwbC8WatsuflAxNiigOnqr0Hi93k3AgE,15422
50
50
  dcicutils/portal_utils.py,sha256=Xm0IqL2dA9C2gx98cPEbvlo81V76bEmpUpxb_8S3VqM,30480
51
- dcicutils/progress_bar.py,sha256=tGhqjONjDIjniqKUb8ATQuZmnJjG61XEu-EiY4uKMK4,13554
51
+ dcicutils/progress_bar.py,sha256=sLX0_L1JRrtGSABOkNS-Y5prcWvZqsyxis_oTYbaLk0,14091
52
52
  dcicutils/project_utils.py,sha256=qPdCaFmWUVBJw4rw342iUytwdQC0P-XKpK4mhyIulMM,31250
53
53
  dcicutils/qa_checkers.py,sha256=cdXjeL0jCDFDLT8VR8Px78aS10hwNISOO5G_Zv2TZ6M,20534
54
54
  dcicutils/qa_utils.py,sha256=TT0SiJWiuxYvbsIyhK9VO4uV_suxhB6CpuC4qPacCzQ,160208
@@ -63,7 +63,7 @@ dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19
63
63
  dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
64
64
  dcicutils/snapshot_utils.py,sha256=ymP7PXH6-yEiXAt75w0ldQFciGNqWBClNxC5gfX2FnY,22961
65
65
  dcicutils/ssl_certificate_utils.py,sha256=F0ifz_wnRRN9dfrfsz7aCp4UDLgHEY8LaK7PjnNvrAQ,9707
66
- dcicutils/structured_data.py,sha256=_Rqc_T6iO36lD3B1WqJeDSiNVFfkzpC1inkbH4B1XtA,58188
66
+ dcicutils/structured_data.py,sha256=YCLGtjsCMXCm5ZM96aiTRQ9OPUuj0lK8O9vSkLx1gv8,58450
67
67
  dcicutils/submitr/progress_constants.py,sha256=5bxyX77ql8qEJearfHEvsvXl7D0GuUODW0T65mbRmnE,2895
68
68
  dcicutils/submitr/ref_lookup_strategy.py,sha256=Js2cVznTmgjciLWBPLCvMiwLIHXjDn3jww-gJPjYuFw,3467
69
69
  dcicutils/task_utils.py,sha256=MF8ujmTD6-O2AC2gRGPHyGdUrVKgtr8epT5XU8WtNjk,8082
@@ -72,8 +72,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
72
72
  dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
73
73
  dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
74
74
  dcicutils/zip_utils.py,sha256=rnjNv_k6L9jT2SjDSgVXp4BEJYLtz9XN6Cl2Fy-tqnM,2027
75
- dcicutils-8.8.3.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
76
- dcicutils-8.8.3.dist-info/METADATA,sha256=aG6CCpyI525cQXOiUXz0PMEAGDdcHwtr7Wl9bekTNfc,3352
77
- dcicutils-8.8.3.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
78
- dcicutils-8.8.3.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
79
- dcicutils-8.8.3.dist-info/RECORD,,
75
+ dcicutils-8.8.3.1b2.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
76
+ dcicutils-8.8.3.1b2.dist-info/METADATA,sha256=nOF-Y3McrAK89qI09YdZEMAlJ_IsoquS9KBZAj_YXr4,3356
77
+ dcicutils-8.8.3.1b2.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
78
+ dcicutils-8.8.3.1b2.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
79
+ dcicutils-8.8.3.1b2.dist-info/RECORD,,