diff --git a/superset/utils/core.py b/superset/utils/core.py index 14ec121de4c20..3f998ca1585e6 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -211,7 +211,7 @@ def parse_js_uri_path_item( return unquote_plus(item) if unquote and item else item -def cast_to_num(value: Union[float, int, str]) -> Optional[Union[float, int]]: +def cast_to_num(value: Optional[Union[float, int, str]]) -> Optional[Union[float, int]]: """Casts a value to an int/float >>> cast_to_num('5') @@ -222,6 +222,8 @@ def cast_to_num(value: Union[float, int, str]) -> Optional[Union[float, int]]: 10 >>> cast_to_num(10.1) 10.1 + >>> cast_to_num(None) is None + True >>> cast_to_num('this is not a string') is None True @@ -229,6 +231,8 @@ def cast_to_num(value: Union[float, int, str]) -> Optional[Union[float, int]]: :returns: value cast to `int` if value is all digits, `float` if `value` is decimal value and `None`` if it can't be converted """ + if value is None: + return None if isinstance(value, (int, float)): return value if value.isdigit(): diff --git a/tests/utils_tests.py b/tests/utils_tests.py index 7cb32b729b1a9..4d7806448af16 100644 --- a/tests/utils_tests.py +++ b/tests/utils_tests.py @@ -38,6 +38,7 @@ from superset.utils.cache_manager import CacheManager from superset.utils.core import ( base_json_conv, + cast_to_num, convert_legacy_filters_into_adhoc, create_ssl_cert_file, format_timedelta, @@ -1368,6 +1369,14 @@ def test_schema_one_of_case_insensitive(self): self.assertRaises(marshmallow.ValidationError, validator, "qwerty") self.assertRaises(marshmallow.ValidationError, validator, 4) + def test_cast_to_num(self) -> None: + assert cast_to_num("5") == 5 + assert cast_to_num("5.2") == 5.2 + assert cast_to_num(10) == 10 + assert cast_to_num(10.1) == 10.1 + assert cast_to_num(None) is None + assert cast_to_num("this is not a string") is None + def test_get_form_data_token(self): assert get_form_data_token({"token": "token_abcdefg1"}) == "token_abcdefg1" generated_token = get_form_data_token({})