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.
- dcicutils/captured_output.py +18 -2
- dcicutils/progress_bar.py +19 -7
- dcicutils/structured_data.py +4 -1
- {dcicutils-8.8.3.dist-info → dcicutils-8.8.3.1b2.dist-info}/METADATA +1 -1
- {dcicutils-8.8.3.dist-info → dcicutils-8.8.3.1b2.dist-info}/RECORD +8 -8
- {dcicutils-8.8.3.dist-info → dcicutils-8.8.3.1b2.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.8.3.dist-info → dcicutils-8.8.3.1b2.dist-info}/WHEEL +0 -0
- {dcicutils-8.8.3.dist-info → dcicutils-8.8.3.1b2.dist-info}/entry_points.txt +0 -0
dcicutils/captured_output.py
CHANGED
@@ -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
|
-
|
58
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
dcicutils/structured_data.py
CHANGED
@@ -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
|
-
|
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", []):
|
@@ -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=
|
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=
|
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=
|
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=
|
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,,
|
File without changes
|
File without changes
|
File without changes
|