gramineproject / graphene

Graphene / Graphene-SGX - a library OS for Linux multi-process applications, with Intel SGX support
https://grapheneproject.io
GNU Lesser General Public License v3.0
771 stars 260 forks source link

Decimal type prone to float rounding error. #2699

Closed drozdowsky closed 2 years ago

drozdowsky commented 2 years ago

Description of the problem

We use graphene with django_graphene but the issue is related with this package. v 2.1.9:

class Decimal(Scalar):
    """
    The `Decimal` scalar type represents a python Decimal.
    """

    @staticmethod
    def serialize(dec):
        if isinstance(dec, str):
            dec = _Decimal(dec)
        assert isinstance(dec, _Decimal), 'Received not compatible Decimal "{}"'.format(
            repr(dec)
        )
        return str(dec)

    @classmethod
    def parse_literal(cls, node):
        if isinstance(node, ast.StringValue):
            return cls.parse_value(node.value)

    @staticmethod
    def parse_value(value):
        try:
            return _Decimal(str(value))
        except ValueError:
            return None

Decimal.parse_value(value) gets value of type float, it converts it to Decimal which results in rounding error.

Workaround (it probably should be fixed in upper frames):

def parse_decimal_value(value):
    try:
        # print(
        #     value, type(value), decimal.Decimal(value), decimal.Decimal(str(value))
        # )
        # results in:
        # 2639.14 <class 'float'> 2639.13999999999987267074175179004669189453125 2639.14
        return decimal.Decimal(str(value))
    except ValueError:
        return None

graphene.types.Decimal.parse_value = parse_decimal_value

I think this happens because client can send the decimal as float, it probably works fine with strings.

mkow commented 2 years ago

Hi, please check the main readme of this repo. The project was moved to https://github.com/gramineproject/gramine and this repository is kept only for historical reasons (we'll archive it soon).