Skip to content

Commit ee9335d

Browse files
fix: convert large integers to strings (#5314)
1 parent d4b5d6a commit ee9335d

4 files changed

Lines changed: 25 additions & 13 deletions

File tree

api/features/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010
# Tag filtering strategy
1111
UNION = "UNION"
1212
INTERSECTION = "INTERSECTION"
13+
14+
MAX_32_BIT_INTEGER = 2_147_483_647

api/features/models.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,22 +720,22 @@ def get_feature_state_value(self, identity: "Identity" = None) -> typing.Any: #
720720
)
721721
return self.get_feature_state_value_by_hash_key(identity_hash_key) # type: ignore[arg-type]
722722

723-
def get_feature_state_value_defaults(self) -> dict: # type: ignore[type-arg]
723+
def get_feature_state_value_defaults(self) -> dict[str, typing.Any]:
724724
if (
725725
self.feature.initial_value is None
726726
or self.feature.project.prevent_flag_defaults
727727
):
728728
return {}
729729

730730
value = self.feature.initial_value
731-
type = get_value_type(value)
731+
type_ = get_value_type(value)
732732
parse_func = {
733733
BOOLEAN: get_boolean_from_string,
734734
INTEGER: get_integer_from_string,
735-
}.get(type, lambda v: v)
736-
key_name = self.get_feature_state_key_name(type)
735+
}.get(type_, lambda v: v)
736+
key_name = self.get_feature_state_key_name(type_)
737737

738-
return {"type": type, key_name: parse_func(value)} # type: ignore[no-untyped-call]
738+
return {"type": type_, key_name: parse_func(value)}
739739

740740
def get_multivariate_feature_state_value(
741741
self, identity_hash_key: str

api/features/utils.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Feature State Value Types
2+
import sys
3+
4+
from features.constants import MAX_32_BIT_INTEGER
25
from features.value_types import BOOLEAN, INTEGER, STRING
36

47

@@ -8,34 +11,38 @@ def get_value_type(value: str) -> str:
811
912
e.g. "12" -> "int", "12.34" -> "float", etc.
1013
"""
11-
if is_integer(value): # type: ignore[no-untyped-call]
14+
if is_32_bit_integer(value):
1215
return INTEGER
13-
elif is_boolean(value): # type: ignore[no-untyped-call]
16+
elif is_boolean(value):
1417
return BOOLEAN
1518
else:
1619
return STRING
1720

1821

19-
def is_integer(value): # type: ignore[no-untyped-def]
22+
def is_32_bit_integer(value: str) -> bool:
23+
return is_integer(value, max_abs_value=MAX_32_BIT_INTEGER)
24+
25+
26+
def is_integer(value: str, max_abs_value: int = sys.maxsize) -> bool:
2027
try:
21-
int(value)
22-
return True
28+
int_value = int(value)
29+
return abs(int_value) < max_abs_value
2330
except ValueError:
2431
return False
2532

2633

27-
def is_boolean(value): # type: ignore[no-untyped-def]
34+
def is_boolean(value: str) -> bool:
2835
return value in ("true", "True", "false", "False")
2936

3037

31-
def get_integer_from_string(value): # type: ignore[no-untyped-def]
38+
def get_integer_from_string(value: str) -> int:
3239
try:
3340
return int(value)
3441
except ValueError:
3542
return 0
3643

3744

38-
def get_boolean_from_string(value): # type: ignore[no-untyped-def]
45+
def get_boolean_from_string(value: str) -> bool:
3946
if value in ("false", "False"):
4047
return False
4148
else:

api/tests/unit/features/test_unit_features_utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22

3+
from features.constants import MAX_32_BIT_INTEGER
34
from features.utils import get_value_type
45
from features.value_types import BOOLEAN, INTEGER, STRING
56

@@ -8,6 +9,8 @@
89
"value, expected_type",
910
(
1011
("1", INTEGER),
12+
(f"{MAX_32_BIT_INTEGER + 1}", STRING),
13+
(f"{-MAX_32_BIT_INTEGER - 1}", STRING),
1114
("a string", STRING),
1215
("True", BOOLEAN),
1316
("true", BOOLEAN),

0 commit comments

Comments
 (0)