Source code for task_script_utils.parse

"""A collection of useful functions to parse raw values into a more useable form."""
from collections import defaultdict
from decimal import Decimal, InvalidOperation
from typing import DefaultDict, Optional, Set


[docs] def to_int(value: str) -> Optional[int]: """ Converts given value to its equivalent integer. :param value: A string to convert :return: The int value of the input string or None if the string could not be parsed to int """ if "_" in value: return None if "e" in value.lower() or "." in value: try: float_val = float(value) int_val = int(float_val) if int_val == float_val: return int_val return None except ValueError: return None try: return int(value) except ValueError: return None
[docs] def to_float(value: str) -> Optional[float]: """ Converts given value to its equivalent float. :param value: A string to convert :return: The float value of the input string. None if the string could not be parsed to float """ if "_" in value: return None try: return float(value) except ValueError: return None
[docs] def to_decimal(value: str) -> Optional[Decimal]: """ Converts the given value to its equivalent python Decimal type :param value: The value to convert :return: The decimal value of the input string. None if the string could not be converted to Decimal """ if "_" in value: return None if value.lower() in ("infinity", "-infinity"): return None try: return Decimal(value) except InvalidOperation: return None
[docs] def to_boolean( value: str, true_set: Set[str], false_set: Set[str], case_sensitive: bool = False ) -> Optional[bool]: """ Convert given string to a boolean value based on whether it is in either of the sets provided :param value: A string to convert :param true_set: A set of strings which represent True values :param false_set: A set of strings which represent False values :return: The boolean value of the input string or None if the string could not be parsed to boolean :raises ValueError: If the sets overlap or if either set is empty """ if not true_set or not false_set: raise ValueError( f"The set of 'true' values and 'false' values cannot be empty. " f"true_set: ({', '.join(true_set)}). " f"false_set: ({', '.join(true_set)})" ) if not case_sensitive: def to_lowercase(string): return string.casefold() else: def to_lowercase(string): return string # Map original values to the lowercase'd version. If there are values in common # between true_set and false_set, we can recover the original values and display # them in an error message. true_set_compare: DefaultDict[str, Set[str]] = defaultdict(set) for original_value in true_set: lowercase_value = to_lowercase(original_value) true_set_compare[lowercase_value].add(original_value) false_set_compare: DefaultDict[str, Set[str]] = defaultdict(set) for original_value in false_set: lowercase_value = to_lowercase(original_value) false_set_compare[lowercase_value].add(lowercase_value) true_and_false_intersection = set(true_set_compare) & set(false_set_compare) if true_and_false_intersection: true_intersection: Set[str] = set() for value_ in true_and_false_intersection: true_intersection.update(true_set_compare[value_]) false_intersection: Set[str] = set() for value_ in true_and_false_intersection: false_intersection.update(false_set_compare[value_]) raise ValueError( f"'true_set' and 'false_set' have values in common. " f"true_set: ({', '.join(true_intersection)}). " f"false_set: ({', '.join(false_intersection)})." ) value_compare = to_lowercase(value.strip()) if value_compare in true_set_compare: return True if value_compare in false_set_compare: return False return None