mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-31 07:57:26 +03:00 
			
		
		
		
	Added scalars
This commit is contained in:
		
							parent
							
								
									55a1450dd3
								
							
						
					
					
						commit
						453d6d6ab7
					
				
							
								
								
									
										148
									
								
								graphene/new_types/scalars.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								graphene/new_types/scalars.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,148 @@ | |||
| import six | ||||
| 
 | ||||
| from graphql.language.ast import BooleanValue, FloatValue, IntValue, StringValue | ||||
| 
 | ||||
| from ..utils.is_base_type import is_base_type | ||||
| from .options import Options | ||||
| from .unmountedtype import UnmountedType | ||||
| 
 | ||||
| 
 | ||||
| class ScalarTypeMeta(type): | ||||
| 
 | ||||
|     def __new__(cls, name, bases, attrs): | ||||
|         super_new = super(ScalarTypeMeta, cls).__new__ | ||||
| 
 | ||||
|         # Also ensure initialization is only performed for subclasses of Model | ||||
|         # (excluding Model class itself). | ||||
|         if not is_base_type(bases, ScalarTypeMeta): | ||||
|             return super_new(cls, name, bases, attrs) | ||||
| 
 | ||||
|         options = Options( | ||||
|             attrs.pop('Meta', None), | ||||
|             name=None, | ||||
|             description=None, | ||||
|         ) | ||||
| 
 | ||||
|         return super_new(cls, name, bases, dict(attrs, _meta=options)) | ||||
| 
 | ||||
| 
 | ||||
| class Scalar(six.with_metaclass(ScalarTypeMeta, UnmountedType)): | ||||
|     serialize = None | ||||
|     parse_value = None | ||||
|     parse_literal = None | ||||
| 
 | ||||
| # As per the GraphQL Spec, Integers are only treated as valid when a valid | ||||
| # 32-bit signed integer, providing the broadest support across platforms. | ||||
| # | ||||
| # n.b. JavaScript's integers are safe between -(2^53 - 1) and 2^53 - 1 because | ||||
| # they are internally represented as IEEE 754 doubles. | ||||
| MAX_INT = 2147483647 | ||||
| MIN_INT = -2147483648 | ||||
| 
 | ||||
| 
 | ||||
| class Int(Scalar): | ||||
|     ''' | ||||
|     The `Int` scalar type represents non-fractional signed whole numeric | ||||
|     values. Int can represent values between -(2^53 - 1) and 2^53 - 1 since | ||||
|     represented in JSON as double-precision floating point numbers specified | ||||
|     by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). | ||||
|     ''' | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def coerce_int(value): | ||||
|         try: | ||||
|             num = int(value) | ||||
|         except ValueError: | ||||
|             try: | ||||
|                 num = int(float(value)) | ||||
|             except ValueError: | ||||
|                 return None | ||||
|         if MIN_INT <= num <= MAX_INT: | ||||
|             return num | ||||
| 
 | ||||
|     serialize = coerce_int | ||||
|     parse_value = coerce_int | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def parse_literal(ast): | ||||
|         if isinstance(ast, IntValue): | ||||
|             num = int(ast.value) | ||||
|             if MIN_INT <= num <= MAX_INT: | ||||
|                 return num | ||||
| 
 | ||||
| 
 | ||||
| class Float(Scalar): | ||||
|     ''' | ||||
|     The `Float` scalar type represents signed double-precision fractional | ||||
|     values as specified by | ||||
|     [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). | ||||
|     ''' | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def coerce_float(value): | ||||
|         try: | ||||
|             return float(value) | ||||
|         except ValueError: | ||||
|             return None | ||||
| 
 | ||||
|     serialize = coerce_float | ||||
|     parse_value = coerce_float | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def parse_literal(ast): | ||||
|         if isinstance(ast, (FloatValue, IntValue)): | ||||
|             return float(ast.value) | ||||
| 
 | ||||
| 
 | ||||
| class String(Scalar): | ||||
|     ''' | ||||
|     The `String` scalar type represents textual data, represented as UTF-8 | ||||
|     character sequences. The String type is most often used by GraphQL to | ||||
|     represent free-form human-readable text. | ||||
|     ''' | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def coerce_string(value): | ||||
|         if isinstance(value, bool): | ||||
|             return u'true' if value else u'false' | ||||
|         return six.text_type(value) | ||||
| 
 | ||||
|     serialize = coerce_string | ||||
|     parse_value = coerce_string | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def parse_literal(ast): | ||||
|         if isinstance(ast, StringValue): | ||||
|             return ast.value | ||||
| 
 | ||||
| 
 | ||||
| class Boolean(Scalar): | ||||
|     ''' | ||||
|     The `Boolean` scalar type represents `true` or `false`. | ||||
|     ''' | ||||
| 
 | ||||
|     serialize = bool | ||||
|     parse_value = bool | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def parse_literal(ast): | ||||
|         if isinstance(ast, BooleanValue): | ||||
|             return ast.value | ||||
| 
 | ||||
| 
 | ||||
| class ID(Scalar): | ||||
|     ''' | ||||
|     The `ID` scalar type represents a unique identifier, often used to | ||||
|     refetch an object or as key for a cache. The ID type appears in a JSON | ||||
|     response as a String; however, it is not intended to be human-readable. | ||||
|     When expected as an input type, any string (such as `"4"`) or integer | ||||
|     (such as `4`) input value will be accepted as an ID. | ||||
|     ''' | ||||
| 
 | ||||
|     serialize = str | ||||
|     parse_value = str | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def parse_literal(ast): | ||||
|         if isinstance(ast, (StringValue, IntValue)): | ||||
|             return ast.value | ||||
|  | @ -70,6 +70,7 @@ def test_generate_objecttype_inherit_abstracttype(): | |||
|     assert MyObjectType._meta.fields.keys() == ['field1', 'field2'] | ||||
|     assert [type(x) for x in MyObjectType._meta.fields.values()] == [Field, Field] | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_objecttype_inherit_abstracttype_reversed(): | ||||
|     class MyAbstractType(AbstractType): | ||||
|         field1 = MyScalar(MyType) | ||||
|  |  | |||
							
								
								
									
										50
									
								
								graphene/new_types/tests/test_scalars_serialization.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								graphene/new_types/tests/test_scalars_serialization.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| from ..scalars import (Boolean, Float, Int, String) | ||||
| 
 | ||||
| 
 | ||||
| def test_serializes_output_int(): | ||||
|     assert Int.serialize(1) == 1 | ||||
|     assert Int.serialize(0) == 0 | ||||
|     assert Int.serialize(-1) == -1 | ||||
|     assert Int.serialize(0.1) == 0 | ||||
|     assert Int.serialize(1.1) == 1 | ||||
|     assert Int.serialize(-1.1) == -1 | ||||
|     assert Int.serialize(1e5) == 100000 | ||||
|     assert Int.serialize(9876504321) is None | ||||
|     assert Int.serialize(-9876504321) is None | ||||
|     assert Int.serialize(1e100) is None | ||||
|     assert Int.serialize(-1e100) is None | ||||
|     assert Int.serialize('-1.1') == -1 | ||||
|     assert Int.serialize('one') is None | ||||
|     assert Int.serialize(False) == 0 | ||||
|     assert Int.serialize(True) == 1 | ||||
| 
 | ||||
| 
 | ||||
| def test_serializes_output_float(): | ||||
|     assert Float.serialize(1) == 1.0 | ||||
|     assert Float.serialize(0) == 0.0 | ||||
|     assert Float.serialize(-1) == -1.0 | ||||
|     assert Float.serialize(0.1) == 0.1 | ||||
|     assert Float.serialize(1.1) == 1.1 | ||||
|     assert Float.serialize(-1.1) == -1.1 | ||||
|     assert Float.serialize('-1.1') == -1.1 | ||||
|     assert Float.serialize('one') is None | ||||
|     assert Float.serialize(False) == 0 | ||||
|     assert Float.serialize(True) == 1 | ||||
| 
 | ||||
| 
 | ||||
| def test_serializes_output_string(): | ||||
|     assert String.serialize('string') == 'string' | ||||
|     assert String.serialize(1) == '1' | ||||
|     assert String.serialize(-1.1) == '-1.1' | ||||
|     assert String.serialize(True) == 'true' | ||||
|     assert String.serialize(False) == 'false' | ||||
|     assert String.serialize(u'\U0001F601') == u'\U0001F601' | ||||
| 
 | ||||
| 
 | ||||
| def test_serializes_output_boolean(): | ||||
|     assert Boolean.serialize('string') is True | ||||
|     assert Boolean.serialize('') is False | ||||
|     assert Boolean.serialize(1) is True | ||||
|     assert Boolean.serialize(0) is False | ||||
|     assert Boolean.serialize(True) is True | ||||
|     assert Boolean.serialize(False) is False | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user