Skip to content

Issue 703 -- support for Decimal type #726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions graphene/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Date,
DateTime,
Time,
Decimal,
JSONString,
UUID,
List,
Expand Down Expand Up @@ -65,6 +66,7 @@
"Date",
"DateTime",
"Time",
"Decimal",
"JSONString",
"UUID",
"List",
Expand Down
2 changes: 2 additions & 0 deletions graphene/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .mutation import Mutation
from .scalars import Scalar, String, ID, Int, Float, Boolean
from .datetime import Date, DateTime, Time
from .decimal import Decimal
from .json import JSONString
from .uuid import UUID
from .schema import Schema
Expand Down Expand Up @@ -40,6 +41,7 @@
"Date",
"DateTime",
"Time",
"Decimal",
"JSONString",
"UUID",
"Boolean",
Expand Down
34 changes: 34 additions & 0 deletions graphene/types/decimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from __future__ import absolute_import

from decimal import Decimal as _Decimal

from graphql.language import ast

from .scalars import Scalar


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(value)
except ValueError:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it check for decimal.DecimalException here, as for example Django does? I've copied your changes to my repo (as it hasn't been released yet) and I'm trying to use it in my mutations, but when providing invalid values like an empty string I'm getting:

{
  "errors": [
    {
      "message": "[<class 'decimal.ConversionSyntax'>]"
    }
  ]
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maarcingebala can you submit a pull request with this change so it can be reviewed?

return None
43 changes: 43 additions & 0 deletions graphene/types/tests/test_decimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import decimal

from ..decimal import Decimal
from ..objecttype import ObjectType
from ..schema import Schema


class Query(ObjectType):
decimal = Decimal(input=Decimal())

def resolve_decimal(self, info, input):
return input


schema = Schema(query=Query)


def test_decimal_string_query():
decimal_value = decimal.Decimal("1969.1974")
result = schema.execute("""{ decimal(input: "%s") }""" % decimal_value)
assert not result.errors
assert result.data == {"decimal": str(decimal_value)}
assert decimal.Decimal(result.data["decimal"]) == decimal_value


def test_decimal_string_query_variable():
decimal_value = decimal.Decimal("1969.1974")

result = schema.execute(
"""query Test($decimal: Decimal){ decimal(input: $decimal) }""",
variable_values={"decimal": decimal_value},
)
assert not result.errors
assert result.data == {"decimal": str(decimal_value)}
assert decimal.Decimal(result.data["decimal"]) == decimal_value


def test_bad_decimal_query():
not_a_decimal = "Nobody expects the Spanish Inquisition!"

result = schema.execute("""{ decimal(input: "%s") }""" % not_a_decimal)
assert len(result.errors) == 1
assert result.data is None