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 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, fallback: Optional[Any] = None, strict: bool = False) -> Optional[Any]:
990
- try:
991
- return int(value)
992
- except Exception:
993
- if strict is not True:
994
- try:
995
- return int(float(value))
996
- except Exception:
997
- pass
998
- return fallback
999
-
1000
-
1001
- _MULTIPLIER_K = 1000
1002
- _MULTIPLIER_M = 1000 * _MULTIPLIER_K
1003
- _MULTIPLIER_G = 1000 * _MULTIPLIER_M
1004
- _MULTIPLIER_T = 1000 * _MULTIPLIER_G
1005
-
1006
- _MULTIPLIER_SUFFIXES = {
1007
- "K": _MULTIPLIER_K,
1008
- "KB": _MULTIPLIER_K,
1009
- "M": _MULTIPLIER_M,
1010
- "MB": _MULTIPLIER_M,
1011
- "G": _MULTIPLIER_G,
1012
- "GB": _MULTIPLIER_G,
1013
- "T": _MULTIPLIER_T,
1014
- "TB": _MULTIPLIER_T
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 give string value to an int, or possibly float if allow_float is True.
1026
- If allow_commas is True (default: False) then allow commas (only) every three digits.
1027
- If allow_multiplier_suffix is True (default: False) allow any of K, Kb, KB; or M, Mb, MB;
1028
- or G, Gb, or GB; or T, Tb, TB, to mean multiply value by one thousand; one million;
1029
- one billion; or one trillion; respectively. If allow_float is True (default: False)
1030
- allow the value to be floating point (i.e. with a decimal point and a fractional part),
1031
- in which case the returned value will be of type float, if it needs to be, and not int.
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
- return value if isinstance(value, (int, float)) else fallback
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 _MULTIPLIER_SUFFIXES:
1059
+ for suffix in _TO_NUMBER_MULTIPLIER_SUFFIXES:
1052
1060
  if value_upper.endswith(suffix):
1053
- value_multiplier *= _MULTIPLIER_SUFFIXES[suffix]
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 allow_float is True:
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 = value[:dot_index].strip()
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
- result = int(value)
1090
+ value = float(value) if as_float is True else int(value)
1076
1091
 
1077
1092
  if value_fraction:
1078
- result += value_fraction
1079
-
1080
- result *= value_multiplier
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
- result = -result
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]:
@@ -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, to_integer, to_number, VirtualApp)
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 to_number(value, fallback=value, allow_float=False,
731
- allow_commas=allow_commas,
732
- allow_multiplier_suffix=allow_multiplier_suffix)
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 to_number(value, fallback=value, allow_float=True,
741
- allow_commas=allow_commas,
742
- allow_multiplier_suffix=allow_multiplier_suffix)
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.13.3.1b25
3
+ Version: 8.13.3.1b26
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
@@ -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=4Kj_0llvUabA1O-n4cGkFdDq_shq_b8iDFDpL9AAIkQ,112934
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=OfGV92SxUosCuh3hwvRJGwreGx1Q43q73mryIZurrxk,66157
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.1b25.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
79
- dcicutils-8.13.3.1b25.dist-info/METADATA,sha256=SUAgwGUivRxlaR7vnZQEmmCaCcjBWeU7M2KySPMDmwo,3440
80
- dcicutils-8.13.3.1b25.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
81
- dcicutils-8.13.3.1b25.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
82
- dcicutils-8.13.3.1b25.dist-info/RECORD,,
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,,