dcicutils 8.13.3.1b25__py3-none-any.whl → 8.13.3.1b26__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/misc_utils.py +68 -58
- dcicutils/structured_data.py +7 -7
- {dcicutils-8.13.3.1b25.dist-info → dcicutils-8.13.3.1b26.dist-info}/METADATA +1 -1
- {dcicutils-8.13.3.1b25.dist-info → dcicutils-8.13.3.1b26.dist-info}/RECORD +7 -7
- {dcicutils-8.13.3.1b25.dist-info → dcicutils-8.13.3.1b26.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.13.3.1b25.dist-info → dcicutils-8.13.3.1b26.dist-info}/WHEEL +0 -0
- {dcicutils-8.13.3.1b25.dist-info → dcicutils-8.13.3.1b26.dist-info}/entry_points.txt +0 -0
dcicutils/misc_utils.py
CHANGED
@@ -986,53 +986,61 @@ def str_to_bool(x: Optional[str]) -> Optional[bool]:
|
|
986
986
|
raise ValueError(f"An argument to str_or_bool must be a string or None: {x!r}")
|
987
987
|
|
988
988
|
|
989
|
-
def to_integer(value: str,
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
"
|
1014
|
-
"
|
989
|
+
def to_integer(value: str,
|
990
|
+
allow_commas: bool = False,
|
991
|
+
allow_multiplier_suffix: bool = False,
|
992
|
+
fallback: Optional[Union[int, float]] = None) -> Optional[int]:
|
993
|
+
return to_number(value, fallback=fallback, as_float=False,
|
994
|
+
allow_commas=allow_commas,
|
995
|
+
allow_multiplier_suffix=allow_multiplier_suffix)
|
996
|
+
|
997
|
+
|
998
|
+
def to_float(value: str,
|
999
|
+
allow_commas: bool = False,
|
1000
|
+
allow_multiplier_suffix: bool = False,
|
1001
|
+
fallback: Optional[Union[int, float]] = None) -> Optional[int]:
|
1002
|
+
return to_number(value, fallback=fallback, as_float=True,
|
1003
|
+
allow_commas=allow_commas,
|
1004
|
+
allow_multiplier_suffix=allow_multiplier_suffix)
|
1005
|
+
|
1006
|
+
|
1007
|
+
_TO_NUMBER_MULTIPLIER_K = 1000
|
1008
|
+
_TO_NUMBER_MULTIPLIER_M = 1000 * _TO_NUMBER_MULTIPLIER_K
|
1009
|
+
_TO_NUMBER_MULTIPLIER_G = 1000 * _TO_NUMBER_MULTIPLIER_M
|
1010
|
+
_TO_NUMBER_MULTIPLIER_T = 1000 * _TO_NUMBER_MULTIPLIER_G
|
1011
|
+
|
1012
|
+
_TO_NUMBER_MULTIPLIER_SUFFIXES = {
|
1013
|
+
"K": _TO_NUMBER_MULTIPLIER_K,
|
1014
|
+
"KB": _TO_NUMBER_MULTIPLIER_K,
|
1015
|
+
"M": _TO_NUMBER_MULTIPLIER_M,
|
1016
|
+
"MB": _TO_NUMBER_MULTIPLIER_M,
|
1017
|
+
"G": _TO_NUMBER_MULTIPLIER_G,
|
1018
|
+
"GB": _TO_NUMBER_MULTIPLIER_G,
|
1019
|
+
"T": _TO_NUMBER_MULTIPLIER_T,
|
1020
|
+
"TB": _TO_NUMBER_MULTIPLIER_T
|
1015
1021
|
}
|
1016
1022
|
|
1017
1023
|
|
1018
1024
|
def to_number(value: str,
|
1025
|
+
as_float: bool = False,
|
1019
1026
|
allow_commas: bool = False,
|
1020
1027
|
allow_multiplier_suffix: bool = False,
|
1021
|
-
allow_float: bool = False,
|
1022
1028
|
fallback: Optional[Union[int, float]] = None) -> Optional[Union[int, float]]:
|
1023
|
-
|
1024
1029
|
"""
|
1025
|
-
Converts the
|
1026
|
-
If allow_commas is True
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
If the string is not well formated then returns None.
|
1030
|
+
Converts the given string value to an int, or float if as_float is True, or None if malformed.
|
1031
|
+
If allow_commas is True then allow commas (only) every three digits. If allow_multiplier_suffix
|
1032
|
+
is True allow any of K, KB; or M, MB; or G, or GB; or T, TB (case-insensitive), to mean multiply
|
1033
|
+
value by one thousand; one million; one billion; or one trillion; respectively. If as_float is True
|
1034
|
+
then value is parsed and returned as a float rather than int. Note that even if as_float is False,
|
1035
|
+
values that might look like a float, can be an int, for example, "1.5K", returns 1500 as an int;
|
1036
|
+
but "1.5002K" returns None, i.e. since 1.5002K is 1500.2 which is not an int.
|
1033
1037
|
"""
|
1038
|
+
|
1034
1039
|
if not (isinstance(value, str) and (value := value.strip())):
|
1035
|
-
|
1040
|
+
if as_float is True:
|
1041
|
+
return float(value) if isinstance(value, (float, int)) else fallback
|
1042
|
+
else:
|
1043
|
+
return value if isinstance(value, int) else fallback
|
1036
1044
|
|
1037
1045
|
value_multiplier = 1
|
1038
1046
|
value_negative = False
|
@@ -1048,21 +1056,28 @@ def to_number(value: str,
|
|
1048
1056
|
|
1049
1057
|
if allow_multiplier_suffix is True:
|
1050
1058
|
value_upper = value.upper()
|
1051
|
-
for suffix in
|
1059
|
+
for suffix in _TO_NUMBER_MULTIPLIER_SUFFIXES:
|
1052
1060
|
if value_upper.endswith(suffix):
|
1053
|
-
value_multiplier *=
|
1061
|
+
value_multiplier *= _TO_NUMBER_MULTIPLIER_SUFFIXES[suffix]
|
1054
1062
|
if not (value := value[:-len(suffix)].strip()):
|
1055
1063
|
return fallback
|
1056
1064
|
break
|
1057
1065
|
|
1058
|
-
if
|
1066
|
+
if (allow_multiplier_suffix is True) or (as_float is True):
|
1067
|
+
# Allow for example "1.5K" to mean 1500 (integer).
|
1059
1068
|
if (dot_index := value.rfind(".")) >= 0:
|
1060
1069
|
if value_fraction := value[dot_index + 1:].strip():
|
1061
1070
|
try:
|
1062
1071
|
value_fraction = float(f"0.{value_fraction}")
|
1063
1072
|
except Exception:
|
1064
1073
|
return fallback
|
1065
|
-
value
|
1074
|
+
if not (value := value[:dot_index].strip()):
|
1075
|
+
if not value_fraction:
|
1076
|
+
return fallback
|
1077
|
+
value = "0"
|
1078
|
+
elif (as_float is not True) and (value_dot_zero_suffix := re.search(r"\.0*$", value)):
|
1079
|
+
# Allow for example "123.00" to mean 123 (integer).
|
1080
|
+
value = value[:value_dot_zero_suffix.start()]
|
1066
1081
|
|
1067
1082
|
if (allow_commas is True) and ("," in value):
|
1068
1083
|
if not re.fullmatch(r"(-?\d{1,3}(,\d{3})*)", value):
|
@@ -1072,28 +1087,23 @@ def to_number(value: str,
|
|
1072
1087
|
if not value.isdigit():
|
1073
1088
|
return fallback
|
1074
1089
|
|
1075
|
-
|
1090
|
+
value = float(value) if as_float is True else int(value)
|
1076
1091
|
|
1077
1092
|
if value_fraction:
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1093
|
+
value_float = (float(value) + value_fraction) * float(value_multiplier)
|
1094
|
+
if as_float is True:
|
1095
|
+
value = value_float
|
1096
|
+
else:
|
1097
|
+
value = int(value_float)
|
1098
|
+
if value_float != value:
|
1099
|
+
return fallback
|
1100
|
+
else:
|
1101
|
+
value *= value_multiplier
|
1081
1102
|
|
1082
1103
|
if value_negative:
|
1083
|
-
|
1084
|
-
|
1085
|
-
if allow_float is True:
|
1086
|
-
if result == int(result):
|
1087
|
-
result = int(result)
|
1088
|
-
|
1089
|
-
return result
|
1104
|
+
value = -value
|
1090
1105
|
|
1091
|
-
|
1092
|
-
def to_float(value: str, fallback: Optional[Any] = None) -> Optional[Any]:
|
1093
|
-
try:
|
1094
|
-
return float(value)
|
1095
|
-
except Exception:
|
1096
|
-
return fallback
|
1106
|
+
return value
|
1097
1107
|
|
1098
1108
|
|
1099
1109
|
def to_boolean(value: str, fallback: Optional[Any]) -> Optional[Any]:
|
dcicutils/structured_data.py
CHANGED
@@ -13,7 +13,7 @@ from dcicutils.data_readers import CsvReader, Excel, RowReader
|
|
13
13
|
from dcicutils.datetime_utils import normalize_date_string, normalize_datetime_string
|
14
14
|
from dcicutils.misc_utils import (create_dict, create_readonly_object, is_uuid, load_json_if,
|
15
15
|
merge_objects, remove_empty_properties, right_trim, split_string,
|
16
|
-
to_boolean, to_enum,
|
16
|
+
to_boolean, to_enum, to_float, to_integer, VirtualApp)
|
17
17
|
from dcicutils.portal_object_utils import PortalObject
|
18
18
|
from dcicutils.portal_utils import Portal as PortalBase
|
19
19
|
from dcicutils.submitr.progress_constants import PROGRESS_PARSE as PROGRESS
|
@@ -727,9 +727,9 @@ class Schema(SchemaBase):
|
|
727
727
|
allow_multiplier_suffix = typeinfo.get("allow_multiplier_suffix") is True
|
728
728
|
def map_integer(value: str, src: Optional[str]) -> Any: # noqa
|
729
729
|
nonlocal allow_commas, allow_multiplier_suffix
|
730
|
-
return
|
731
|
-
|
732
|
-
|
730
|
+
return to_integer(value, fallback=value,
|
731
|
+
allow_commas=allow_commas,
|
732
|
+
allow_multiplier_suffix=allow_multiplier_suffix)
|
733
733
|
return map_integer
|
734
734
|
|
735
735
|
def _map_function_number(self, typeinfo: dict) -> Callable:
|
@@ -737,9 +737,9 @@ class Schema(SchemaBase):
|
|
737
737
|
allow_multiplier_suffix = typeinfo.get("allow_multiplier_suffix") is True
|
738
738
|
def map_number(value: str, src: Optional[str]) -> Any: # noqa
|
739
739
|
nonlocal allow_commas, allow_multiplier_suffix
|
740
|
-
return
|
741
|
-
|
742
|
-
|
740
|
+
return to_float(value, fallback=value,
|
741
|
+
allow_commas=allow_commas,
|
742
|
+
allow_multiplier_suffix=allow_multiplier_suffix)
|
743
743
|
return map_number
|
744
744
|
|
745
745
|
def _map_function_string(self, typeinfo: dict) -> Callable:
|
@@ -45,7 +45,7 @@ dcicutils/license_policies/park-lab-gpl-pipeline.jsonc,sha256=vLZkwm3Js-kjV44nug
|
|
45
45
|
dcicutils/license_policies/park-lab-pipeline.jsonc,sha256=9qlY0ASy3iUMQlr3gorVcXrSfRHnVGbLhkS427UaRy4,283
|
46
46
|
dcicutils/license_utils.py,sha256=2Yxnh1T1iuMe6wluwbvpFO_zYSGPxB4-STAMc-vz-YM,47202
|
47
47
|
dcicutils/log_utils.py,sha256=7pWMc6vyrorUZQf-V-M3YC6zrPgNhuV_fzm9xqTPph0,10883
|
48
|
-
dcicutils/misc_utils.py,sha256=
|
48
|
+
dcicutils/misc_utils.py,sha256=zkzCwtuqdq90HoOP8kLuJw4ldeE8AdRNBduW2KzEBfQ,114108
|
49
49
|
dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmjw,5963
|
50
50
|
dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
|
51
51
|
dcicutils/portal_object_utils.py,sha256=Az3n1aL-PQkN5gOFE6ZqC2XkYsqiwKlq7-tZggs1QN4,11062
|
@@ -66,7 +66,7 @@ dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19
|
|
66
66
|
dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
|
67
67
|
dcicutils/snapshot_utils.py,sha256=YDeI3vD-MhAtHwKDzfEm2q-n3l-da2yRpRR3xp0Ah1M,23021
|
68
68
|
dcicutils/ssl_certificate_utils.py,sha256=F0ifz_wnRRN9dfrfsz7aCp4UDLgHEY8LaK7PjnNvrAQ,9707
|
69
|
-
dcicutils/structured_data.py,sha256=
|
69
|
+
dcicutils/structured_data.py,sha256=LN-Bn-RUM_jy0T6s-ovZT9QXDsQ8w1_QVtkb8LAHFs4,66119
|
70
70
|
dcicutils/submitr/progress_constants.py,sha256=5bxyX77ql8qEJearfHEvsvXl7D0GuUODW0T65mbRmnE,2895
|
71
71
|
dcicutils/submitr/ref_lookup_strategy.py,sha256=VJN-Oo0LLna6Vo2cu47eC-eU-yUC9NFlQP29xajejVU,4741
|
72
72
|
dcicutils/task_utils.py,sha256=MF8ujmTD6-O2AC2gRGPHyGdUrVKgtr8epT5XU8WtNjk,8082
|
@@ -75,8 +75,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
|
|
75
75
|
dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
|
76
76
|
dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
|
77
77
|
dcicutils/zip_utils.py,sha256=_Y9EmL3D2dUZhxucxHvrtmmlbZmK4FpSsHEb7rGSJLU,3265
|
78
|
-
dcicutils-8.13.3.
|
79
|
-
dcicutils-8.13.3.
|
80
|
-
dcicutils-8.13.3.
|
81
|
-
dcicutils-8.13.3.
|
82
|
-
dcicutils-8.13.3.
|
78
|
+
dcicutils-8.13.3.1b26.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
|
79
|
+
dcicutils-8.13.3.1b26.dist-info/METADATA,sha256=jQjbtF24ujN4fAqJqGPzqMmdDZMI78IAeZlpBs3WAWc,3440
|
80
|
+
dcicutils-8.13.3.1b26.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
81
|
+
dcicutils-8.13.3.1b26.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
|
82
|
+
dcicutils-8.13.3.1b26.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|