dcicutils 8.8.6.1b11__py3-none-any.whl → 8.8.6.1b13__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/command_utils.py +69 -1
- dcicutils/structured_data.py +8 -15
- {dcicutils-8.8.6.1b11.dist-info → dcicutils-8.8.6.1b13.dist-info}/METADATA +1 -1
- {dcicutils-8.8.6.1b11.dist-info → dcicutils-8.8.6.1b13.dist-info}/RECORD +7 -7
- {dcicutils-8.8.6.1b11.dist-info → dcicutils-8.8.6.1b13.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.8.6.1b11.dist-info → dcicutils-8.8.6.1b13.dist-info}/WHEEL +0 -0
- {dcicutils-8.8.6.1b11.dist-info → dcicutils-8.8.6.1b13.dist-info}/entry_points.txt +0 -0
dcicutils/command_utils.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import contextlib
|
2
3
|
import functools
|
3
4
|
import glob
|
@@ -7,7 +8,7 @@ import re
|
|
7
8
|
import requests
|
8
9
|
import subprocess
|
9
10
|
|
10
|
-
from typing import Optional
|
11
|
+
from typing import Callable, Optional
|
11
12
|
from .exceptions import InvalidParameterError
|
12
13
|
from .lang_utils import there_are
|
13
14
|
from .misc_utils import INPUT, PRINT, environ_bool, print_error_message, decorator
|
@@ -384,3 +385,70 @@ def script_catch_errors():
|
|
384
385
|
message = str(e) # Note: We ignore the type, which isn't intended to be shown.
|
385
386
|
PRINT(message)
|
386
387
|
exit(1)
|
388
|
+
|
389
|
+
|
390
|
+
class Question:
|
391
|
+
"""
|
392
|
+
Supports asking the user (via stdin) a yes/no question, possibly repeatedly; and after
|
393
|
+
some maximum number times of the same answer in a row (consecutively), then asks them
|
394
|
+
if they want to automatically give that same answer to any/all subsequent questions.
|
395
|
+
Supports static/global list of such Question instances, hashed (only) by the question text.
|
396
|
+
"""
|
397
|
+
_static_instances = {}
|
398
|
+
|
399
|
+
@staticmethod
|
400
|
+
def instance(question: Optional[str] = None,
|
401
|
+
max: Optional[int] = None, printf: Optional[Callable] = None) -> Question:
|
402
|
+
question = question if isinstance(question, str) else ""
|
403
|
+
if not (instance := Question._static_instances.get(question)):
|
404
|
+
Question._static_instances[question] = (instance := Question(question, max=max, printf=printf))
|
405
|
+
return instance
|
406
|
+
|
407
|
+
@staticmethod
|
408
|
+
def yes(question: Optional[str] = None,
|
409
|
+
max: Optional[int] = None, printf: Optional[Callable] = None) -> bool:
|
410
|
+
return Question.instance(question, max=max, printf=printf).ask()
|
411
|
+
|
412
|
+
def __init__(self, question: Optional[str] = None,
|
413
|
+
max: Optional[int] = None, printf: Optional[Callable] = None) -> None:
|
414
|
+
self._question = question if isinstance(question, str) else ""
|
415
|
+
self._max = max if isinstance(max, int) and max > 0 else None
|
416
|
+
self._print = printf if callable(printf) else print
|
417
|
+
self._yes_consecutive_count = 0
|
418
|
+
self._no_consecutive_count = 0
|
419
|
+
self._yes_automatic = False
|
420
|
+
self._no_automatic = False
|
421
|
+
|
422
|
+
def ask(self, question: Optional[str] = None) -> bool:
|
423
|
+
|
424
|
+
def question_automatic(value: str) -> bool:
|
425
|
+
nonlocal self
|
426
|
+
RARROW = "▶"
|
427
|
+
LARROW = "◀"
|
428
|
+
if yes_or_no(f"{RARROW}{RARROW}{RARROW}"
|
429
|
+
f" Do you want to answer {value} to all such questions?"
|
430
|
+
f" {LARROW}{LARROW}{LARROW}"):
|
431
|
+
return True
|
432
|
+
self._yes_consecutive_count = 0
|
433
|
+
self._no_consecutive_count = 0
|
434
|
+
|
435
|
+
if self._yes_automatic:
|
436
|
+
return True
|
437
|
+
elif self._no_automatic:
|
438
|
+
return False
|
439
|
+
elif yes_or_no((question if isinstance(question, str) else "") or self._question or "Undefined question"):
|
440
|
+
self._yes_consecutive_count += 1
|
441
|
+
self._no_consecutive_count = 0
|
442
|
+
if (self._no_consecutive_count == 0) and self._max and (self._yes_consecutive_count >= self._max):
|
443
|
+
# Have reached the maximum number of consecutive YES answers; ask if YES to all subsequent.
|
444
|
+
if question_automatic("YES"):
|
445
|
+
self._yes_automatic = True
|
446
|
+
return True
|
447
|
+
else:
|
448
|
+
self._no_consecutive_count += 1
|
449
|
+
self._yes_consecutive_count = 0
|
450
|
+
if (self._yes_consecutive_count == 0) and self._max and (self._no_consecutive_count >= self._max):
|
451
|
+
# Have reached the maximum number of consecutive NO answers; ask if NO to all subsequent.
|
452
|
+
if question_automatic("NO"):
|
453
|
+
self._no_automatic = True
|
454
|
+
return False
|
dcicutils/structured_data.py
CHANGED
@@ -11,7 +11,6 @@ from webtest.app import TestApp
|
|
11
11
|
from dcicutils.common import OrchestratedApp
|
12
12
|
from dcicutils.data_readers import CsvReader, Excel, RowReader
|
13
13
|
from dcicutils.datetime_utils import normalize_date_string, normalize_datetime_string
|
14
|
-
from dcicutils.file_utils import search_for_file
|
15
14
|
from dcicutils.misc_utils import (create_dict, create_readonly_object, is_uuid, load_json_if,
|
16
15
|
merge_objects, remove_empty_properties, right_trim, split_string,
|
17
16
|
to_boolean, to_enum, to_float, to_integer, VirtualApp)
|
@@ -209,14 +208,6 @@ class StructuredDataSet:
|
|
209
208
|
result.append({"type": type_name, "file": file_name})
|
210
209
|
return result
|
211
210
|
|
212
|
-
def upload_files_located(self,
|
213
|
-
location: Union[str, Optional[List[str]]] = None, recursive: bool = False) -> List[str]:
|
214
|
-
upload_files = copy.deepcopy(self.upload_files)
|
215
|
-
for upload_file in upload_files:
|
216
|
-
if file_path := search_for_file(upload_file["file"], location, recursive=recursive, single=True):
|
217
|
-
upload_file["path"] = file_path
|
218
|
-
return upload_files
|
219
|
-
|
220
211
|
@property
|
221
212
|
def nrows(self) -> int:
|
222
213
|
return self._nrows
|
@@ -351,20 +342,22 @@ class StructuredDataSet:
|
|
351
342
|
|
352
343
|
def _load_json_file(self, file: str) -> None:
|
353
344
|
with open(file) as f:
|
354
|
-
|
345
|
+
data = json.load(f)
|
346
|
+
import pdb ; pdb.set_trace() # noqa
|
347
|
+
pass
|
355
348
|
if ((schema_name_inferred_from_file_name := Schema.type_name(file)) and
|
356
349
|
(self._portal.get_schema(schema_name_inferred_from_file_name) is not None)): # noqa
|
357
350
|
# If the JSON file name looks like a schema name then assume it
|
358
351
|
# contains an object or an array of object of that schema type.
|
359
352
|
if self._merge:
|
360
|
-
|
361
|
-
self._add(Schema.type_name(file),
|
362
|
-
elif isinstance(
|
353
|
+
data = self._merge_with_existing_portal_object(data, schema_name_inferred_from_file_name)
|
354
|
+
self._add(Schema.type_name(file), data)
|
355
|
+
elif isinstance(data, dict):
|
363
356
|
# Otherwise if the JSON file name does not look like a schema name then
|
364
357
|
# assume it a dictionary where each property is the name of a schema, and
|
365
358
|
# which (each property) contains a list of object of that schema type.
|
366
|
-
for schema_name in
|
367
|
-
item =
|
359
|
+
for schema_name in data:
|
360
|
+
item = data[schema_name]
|
368
361
|
if self._merge:
|
369
362
|
item = self._merge_with_existing_portal_object(item, schema_name)
|
370
363
|
self._add(schema_name, item)
|
@@ -5,7 +5,7 @@ dcicutils/bundle_utils.py,sha256=ZVQcqlt7Yly8-YbL3A-5DW859_hMWpTL6dXtknEYZIw,346
|
|
5
5
|
dcicutils/captured_output.py,sha256=0hP7sPwleMaYXQAvCfJOxG8Z8T_JJYy8ADp8A5ZoblE,3295
|
6
6
|
dcicutils/cloudformation_utils.py,sha256=MtWJrSTXyiImgbPHgRvfH9bWso20ZPLTFJAfhDQSVj4,13786
|
7
7
|
dcicutils/codebuild_utils.py,sha256=CKpmhJ-Z8gYbkt1I2zyMlKtFdsg7T8lqrx3V5ieta-U,1155
|
8
|
-
dcicutils/command_utils.py,sha256=
|
8
|
+
dcicutils/command_utils.py,sha256=1_h18LGX86sLAkRkH33HNmBkwMb7v2wAh3jL01hzceU,18487
|
9
9
|
dcicutils/common.py,sha256=YE8Mt5-vaZWWz4uaChSVhqGFbFtW5QKtnIyOr4zG4vM,3955
|
10
10
|
dcicutils/contribution_scripts.py,sha256=0k5Gw1TumcD5SAcXVkDd6-yvuMEw-jUp5Kfb7FJH6XQ,2015
|
11
11
|
dcicutils/contribution_utils.py,sha256=vYLS1JUB3sKd24BUxZ29qUBqYeQBLK9cwo8x3k64uPg,25653
|
@@ -64,7 +64,7 @@ dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19
|
|
64
64
|
dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
|
65
65
|
dcicutils/snapshot_utils.py,sha256=ymP7PXH6-yEiXAt75w0ldQFciGNqWBClNxC5gfX2FnY,22961
|
66
66
|
dcicutils/ssl_certificate_utils.py,sha256=F0ifz_wnRRN9dfrfsz7aCp4UDLgHEY8LaK7PjnNvrAQ,9707
|
67
|
-
dcicutils/structured_data.py,sha256=
|
67
|
+
dcicutils/structured_data.py,sha256=KxwDJ9wwEnT7NCsEw9bKrufGYe2wfP2Zoy8zipTk0Gs,64096
|
68
68
|
dcicutils/submitr/progress_constants.py,sha256=5bxyX77ql8qEJearfHEvsvXl7D0GuUODW0T65mbRmnE,2895
|
69
69
|
dcicutils/submitr/ref_lookup_strategy.py,sha256=VJN-Oo0LLna6Vo2cu47eC-eU-yUC9NFlQP29xajejVU,4741
|
70
70
|
dcicutils/task_utils.py,sha256=MF8ujmTD6-O2AC2gRGPHyGdUrVKgtr8epT5XU8WtNjk,8082
|
@@ -73,8 +73,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
|
|
73
73
|
dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
|
74
74
|
dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
|
75
75
|
dcicutils/zip_utils.py,sha256=_Y9EmL3D2dUZhxucxHvrtmmlbZmK4FpSsHEb7rGSJLU,3265
|
76
|
-
dcicutils-8.8.6.
|
77
|
-
dcicutils-8.8.6.
|
78
|
-
dcicutils-8.8.6.
|
79
|
-
dcicutils-8.8.6.
|
80
|
-
dcicutils-8.8.6.
|
76
|
+
dcicutils-8.8.6.1b13.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
|
77
|
+
dcicutils-8.8.6.1b13.dist-info/METADATA,sha256=u0aE7aX6k854ZrCide1x5MCfmaqMi2dc4JUx6ZnYA5M,3440
|
78
|
+
dcicutils-8.8.6.1b13.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
79
|
+
dcicutils-8.8.6.1b13.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
|
80
|
+
dcicutils-8.8.6.1b13.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|