mirror of https://github.com/nucypher/nucypher.git
Properly handle bigint strings that are strings of large numbers that end with 'n'.
parent
1b13c50b02
commit
a4df4662aa
|
@ -36,7 +36,11 @@ from nucypher.policy.conditions.exceptions import (
|
|||
ReturnValueEvaluationError,
|
||||
)
|
||||
from nucypher.policy.conditions.types import ConditionDict, Lingo
|
||||
from nucypher.policy.conditions.utils import CamelCaseSchema, ConditionProviderManager
|
||||
from nucypher.policy.conditions.utils import (
|
||||
CamelCaseSchema,
|
||||
ConditionProviderManager,
|
||||
check_and_convert_big_int_string_to_int,
|
||||
)
|
||||
|
||||
|
||||
class AnyField(fields.Field):
|
||||
|
@ -46,23 +50,15 @@ class AnyField(fields.Field):
|
|||
numbers as integers, so those need converting to integers.
|
||||
"""
|
||||
|
||||
def _convert_any_large_integers_from_string(self, value):
|
||||
def _convert_any_big_ints_from_string(self, value):
|
||||
if isinstance(value, list):
|
||||
return [
|
||||
self._convert_any_large_integers_from_string(item) for item in value
|
||||
]
|
||||
return [self._convert_any_big_ints_from_string(item) for item in value]
|
||||
elif isinstance(value, dict):
|
||||
return {
|
||||
k: self._convert_any_large_integers_from_string(v)
|
||||
for k, v in value.items()
|
||||
k: self._convert_any_big_ints_from_string(v) for k, v in value.items()
|
||||
}
|
||||
elif isinstance(value, str):
|
||||
try:
|
||||
result = int(value)
|
||||
return result
|
||||
except ValueError:
|
||||
# ignore
|
||||
pass
|
||||
return check_and_convert_big_int_string_to_int(value)
|
||||
|
||||
return value
|
||||
|
||||
|
@ -70,7 +66,23 @@ class AnyField(fields.Field):
|
|||
return value
|
||||
|
||||
def _deserialize(self, value, attr, data, **kwargs):
|
||||
return self._convert_any_large_integers_from_string(value)
|
||||
return self._convert_any_big_ints_from_string(value)
|
||||
|
||||
|
||||
class IntegerField(fields.Int):
|
||||
"""
|
||||
Integer field that also converts big int strings to integers.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _deserialize(self, value, attr, data, **kwargs):
|
||||
if isinstance(value, str):
|
||||
value = check_and_convert_big_int_string_to_int(value)
|
||||
|
||||
return super()._deserialize(value, attr, data, **kwargs)
|
||||
|
||||
|
||||
class _ConditionField(fields.Dict):
|
||||
"""Serializes/Deserializes Conditions to/from dictionaries"""
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import re
|
||||
from http import HTTPStatus
|
||||
from typing import Dict, Iterator, List, Optional, Tuple
|
||||
from typing import Dict, Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from marshmallow import Schema, post_dump
|
||||
from marshmallow.exceptions import SCHEMA
|
||||
|
@ -223,3 +223,18 @@ def extract_single_error_message_from_schema_errors(
|
|||
else ""
|
||||
)
|
||||
return f"{message_prefix}{message}"
|
||||
|
||||
|
||||
def check_and_convert_big_int_string_to_int(value: str) -> Union[str, int]:
|
||||
"""
|
||||
Check if a string is a big int string and convert it to an integer, otherwise return the string.
|
||||
"""
|
||||
if value.endswith("n"):
|
||||
try:
|
||||
result = int(value[:-1])
|
||||
return result
|
||||
except ValueError:
|
||||
# ignore
|
||||
pass
|
||||
|
||||
return value
|
||||
|
|
|
@ -426,16 +426,16 @@ def test_any_field_integer_str_and_no_str_conversion(integer_value):
|
|||
deserialized_raw_integer = field._deserialize(
|
||||
value=integer_value, attr=None, data=None
|
||||
)
|
||||
deserialized_string_integer = field._deserialize(
|
||||
value=str(integer_value), attr=None, data=None
|
||||
deserialized_big_int_string = field._deserialize(
|
||||
value=f"{integer_value}n", attr=None, data=None
|
||||
)
|
||||
assert deserialized_raw_integer == deserialized_string_integer
|
||||
assert deserialized_raw_integer == deserialized_big_int_string
|
||||
|
||||
assert (
|
||||
field._serialize(deserialized_raw_integer, attr=None, obj=None) == integer_value
|
||||
)
|
||||
assert (
|
||||
field._serialize(deserialized_string_integer, attr=None, obj=None)
|
||||
field._serialize(deserialized_big_int_string, attr=None, obj=None)
|
||||
== integer_value
|
||||
)
|
||||
|
||||
|
@ -448,8 +448,8 @@ def test_any_field_nested_integer():
|
|||
regular_number = 12341231
|
||||
|
||||
parameters = [
|
||||
f"{uint256_max}",
|
||||
{"a": [f"{int256_min}", "my_string_value", "0xdeadbeef"], "b": regular_number},
|
||||
f"{uint256_max}n",
|
||||
{"a": [f"{int256_min}n", "my_string_value", "0xdeadbeef"], "b": regular_number},
|
||||
]
|
||||
# quoted numbers get unquoted after deserialization
|
||||
expected_parameters = [
|
||||
|
|
Loading…
Reference in New Issue