From 71fe34360d08c7e1ebd4ac7b2eb56807e355e322 Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 09:19:03 +0000 Subject: [PATCH 1/7] Fix utf-8 error on py 2.7 --- graphql_relay/node/tests/test_global.py | 5 ----- graphql_relay/node/tests/test_node.py | 4 ---- graphql_relay/tests/__init__.py | 0 graphql_relay/tests/test_utils.py | 30 +++++++++++++++++++++++++ graphql_relay/utils.py | 22 ++++++++---------- setup.py | 1 + tox.ini | 1 + 7 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 graphql_relay/tests/__init__.py create mode 100644 graphql_relay/tests/test_utils.py diff --git a/graphql_relay/node/tests/test_global.py b/graphql_relay/node/tests/test_global.py index 417c2c7..da99e5a 100644 --- a/graphql_relay/node/tests/test_global.py +++ b/graphql_relay/node/tests/test_global.py @@ -1,17 +1,12 @@ from collections import namedtuple -from pytest import raises from graphql import graphql from graphql.type import ( GraphQLSchema, GraphQLObjectType, GraphQLField, - GraphQLArgument, GraphQLList, - GraphQLNonNull, GraphQLInt, GraphQLString, - GraphQLBoolean, - GraphQLID, ) from graphql_relay.node.node import ( diff --git a/graphql_relay/node/tests/test_node.py b/graphql_relay/node/tests/test_node.py index 4d6f252..cef14de 100644 --- a/graphql_relay/node/tests/test_node.py +++ b/graphql_relay/node/tests/test_node.py @@ -1,16 +1,12 @@ from collections import namedtuple -from pytest import raises from graphql import graphql from graphql.type import ( GraphQLSchema, GraphQLObjectType, GraphQLField, - GraphQLArgument, - GraphQLList, GraphQLNonNull, GraphQLInt, GraphQLString, - GraphQLBoolean, GraphQLID, ) diff --git a/graphql_relay/tests/__init__.py b/graphql_relay/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphql_relay/tests/test_utils.py b/graphql_relay/tests/test_utils.py new file mode 100644 index 0000000..7b1db2d --- /dev/null +++ b/graphql_relay/tests/test_utils.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import base64 + +from .. import utils + + +def test_base64_encode_unicode_strings_correctly(): + my_unicode = u'ûñö' + my_base64 = utils.base64(my_unicode) + assert my_base64 == base64.b64encode(my_unicode.encode('utf-8')).decode('utf-8') + + +def test_base64_encode_strings_correctly(): + my_string = 'abc' + my_base64 = utils.base64(my_string) + assert my_base64 == base64.b64encode(my_string.encode('utf-8')).decode('utf-8') + + +def test_unbase64_decodes_unicode_strings_correctly(): + my_unicode = u'ûñö' + my_converted_unicode = utils.unbase64(utils.base64(my_unicode)) + assert my_unicode == my_converted_unicode + + +def test_unbase64_decodes_strings_correctly(): + my_string = 'abc' + my_converted_string = utils.unbase64(utils.base64(my_string)) + assert my_string == my_converted_string diff --git a/graphql_relay/utils.py b/graphql_relay/utils.py index dc9800f..1cba2c9 100644 --- a/graphql_relay/utils.py +++ b/graphql_relay/utils.py @@ -1,22 +1,18 @@ from base64 import b64encode as _base64, b64decode as _unbase64 -try: - str_type = basestring - base64 = _base64 - unbase64 = _unbase64 +from six import string_types - def is_str(s): - return isinstance(s, basestring) -except NameError: - def base64(s): - return _base64(bytes(s, 'utf-8')).decode('utf-8') +def base64(s): + return _base64(s.encode('utf-8')).decode('utf-8') - def unbase64(s): - return _unbase64(s).decode('utf-8') - def is_str(s): - return isinstance(s, str) +def unbase64(s): + return _unbase64(s).decode('utf-8') + + +def is_str(s): + return isinstance(s, string_types) def resolve_maybe_thunk(f): diff --git a/setup.py b/setup.py index e15a88b..db40bd9 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ def run_tests(self): packages=find_packages(exclude=['tests']), install_requires=[ + 'six>=1.10.0', 'graphql-core>=0.5.0', 'promise>=0.4.0' ], diff --git a/tox.ini b/tox.ini index 2fd3c4e..babbf4f 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ envlist = py27,py33,py34,py35,pypy deps= pytest>=2.7.2 django>=1.8.0,<1.9 + six flake8 singledispatch commands= From 3b4de4f428863b8d9346bafc2a1d4538ff8f6798 Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 09:43:36 +0000 Subject: [PATCH 2/7] Fix tests. --- graphql_relay/mutation/tests/test_mutation.py | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/graphql_relay/mutation/tests/test_mutation.py b/graphql_relay/mutation/tests/test_mutation.py index ee14eb7..72651ec 100644 --- a/graphql_relay/mutation/tests/test_mutation.py +++ b/graphql_relay/mutation/tests/test_mutation.py @@ -1,6 +1,6 @@ +from collections import OrderedDict + from promise import Promise -from collections import namedtuple -from pytest import raises from graphql import graphql from graphql.type import ( GraphQLSchema, @@ -83,22 +83,6 @@ def test_requires_an_argument(): } } ''' - expected = { - 'allObjects': [ - { - 'id': 'VXNlcjox' - }, - { - 'id': 'VXNlcjoy' - }, - { - 'id': 'UGhvdG86MQ==' - }, - { - 'id': 'UGhvdG86Mg==' - }, - ] - } result = graphql(schema, query) assert len(result.errors) == 1 @@ -333,7 +317,6 @@ def test_contains_correct_field(): } } ''' - expected = { '__schema': { 'mutationType': { @@ -421,8 +404,14 @@ def test_contains_correct_field(): ] } } - } result = graphql(schema, query) assert not result.errors + # ensure the ordering is correct for the assertion + expected['__schema']['mutationType']['fields'] = sorted( + expected['__schema']['mutationType']['fields'] + ) + result.data['__schema']['mutationType']['fields'] = sorted( + result.data['__schema']['mutationType']['fields'] + ) assert result.data == expected From 7a5ded46182abc4e98889c68f1345d2bb2370556 Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 09:56:12 +0000 Subject: [PATCH 3/7] Fixed ordering for test. --- graphql_relay/mutation/tests/test_mutation.py | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/graphql_relay/mutation/tests/test_mutation.py b/graphql_relay/mutation/tests/test_mutation.py index 72651ec..8653aee 100644 --- a/graphql_relay/mutation/tests/test_mutation.py +++ b/graphql_relay/mutation/tests/test_mutation.py @@ -1,5 +1,3 @@ -from collections import OrderedDict - from promise import Promise from graphql import graphql from graphql.type import ( @@ -322,7 +320,7 @@ def test_contains_correct_field(): 'mutationType': { 'fields': [ { - 'name': 'simpleMutation', + 'name': 'simplePromiseMutation', 'args': [ { 'name': 'input', @@ -330,19 +328,19 @@ def test_contains_correct_field(): 'name': None, 'kind': 'NON_NULL', 'ofType': { - 'name': 'SimpleMutationInput', + 'name': 'SimplePromiseMutationInput', 'kind': 'INPUT_OBJECT' } }, } ], 'type': { - 'name': 'SimpleMutationPayload', + 'name': 'SimplePromiseMutationPayload', 'kind': 'OBJECT', } }, { - 'name': 'simpleMutationWithThunkFields', + 'name': 'simpleRootValueMutation', 'args': [ { 'name': 'input', @@ -350,19 +348,19 @@ def test_contains_correct_field(): 'name': None, 'kind': 'NON_NULL', 'ofType': { - 'name': 'SimpleMutationWithThunkFieldsInput', + 'name': 'SimpleRootValueMutationInput', 'kind': 'INPUT_OBJECT' } }, } ], 'type': { - 'name': 'SimpleMutationWithThunkFieldsPayload', + 'name': 'SimpleRootValueMutationPayload', 'kind': 'OBJECT', } }, { - 'name': 'simplePromiseMutation', + 'name': 'simpleMutation', 'args': [ { 'name': 'input', @@ -370,19 +368,19 @@ def test_contains_correct_field(): 'name': None, 'kind': 'NON_NULL', 'ofType': { - 'name': 'SimplePromiseMutationInput', + 'name': 'SimpleMutationInput', 'kind': 'INPUT_OBJECT' } }, } ], 'type': { - 'name': 'SimplePromiseMutationPayload', + 'name': 'SimpleMutationPayload', 'kind': 'OBJECT', } }, { - 'name': 'simpleRootValueMutation', + 'name': 'simpleMutationWithThunkFields', 'args': [ { 'name': 'input', @@ -390,14 +388,14 @@ def test_contains_correct_field(): 'name': None, 'kind': 'NON_NULL', 'ofType': { - 'name': 'SimpleRootValueMutationInput', + 'name': 'SimpleMutationWithThunkFieldsInput', 'kind': 'INPUT_OBJECT' } }, } ], 'type': { - 'name': 'SimpleRootValueMutationPayload', + 'name': 'SimpleMutationWithThunkFieldsPayload', 'kind': 'OBJECT', } }, @@ -407,11 +405,4 @@ def test_contains_correct_field(): } result = graphql(schema, query) assert not result.errors - # ensure the ordering is correct for the assertion - expected['__schema']['mutationType']['fields'] = sorted( - expected['__schema']['mutationType']['fields'] - ) - result.data['__schema']['mutationType']['fields'] = sorted( - result.data['__schema']['mutationType']['fields'] - ) assert result.data == expected From a67d78e7b8a36e35b1276b42ca0290bc462f5bf6 Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 09:58:42 +0000 Subject: [PATCH 4/7] Try with ordered dict. --- graphql_relay/mutation/tests/test_mutation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/graphql_relay/mutation/tests/test_mutation.py b/graphql_relay/mutation/tests/test_mutation.py index 8653aee..c1f7d97 100644 --- a/graphql_relay/mutation/tests/test_mutation.py +++ b/graphql_relay/mutation/tests/test_mutation.py @@ -1,3 +1,5 @@ +from collections import OrderedDict + from promise import Promise from graphql import graphql from graphql.type import ( @@ -315,7 +317,7 @@ def test_contains_correct_field(): } } ''' - expected = { + expected = OrderedDict({ '__schema': { 'mutationType': { 'fields': [ @@ -402,7 +404,7 @@ def test_contains_correct_field(): ] } } - } + }) result = graphql(schema, query) assert not result.errors assert result.data == expected From d852e75d65560318242fb920439b648c862095a9 Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 10:14:20 +0000 Subject: [PATCH 5/7] Fixed test for py3. --- graphql_relay/mutation/tests/test_mutation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_relay/mutation/tests/test_mutation.py b/graphql_relay/mutation/tests/test_mutation.py index c1f7d97..420b2db 100644 --- a/graphql_relay/mutation/tests/test_mutation.py +++ b/graphql_relay/mutation/tests/test_mutation.py @@ -407,4 +407,4 @@ def test_contains_correct_field(): }) result = graphql(schema, query) assert not result.errors - assert result.data == expected + assert dict(result.data) == expected From c348879155b36c5da67d4032135a487509e70b6c Mon Sep 17 00:00:00 2001 From: markus Date: Fri, 18 Nov 2016 10:21:54 +0000 Subject: [PATCH 6/7] Sort dict entries to be consistent in py2 and 3. --- graphql_relay/mutation/tests/test_mutation.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/graphql_relay/mutation/tests/test_mutation.py b/graphql_relay/mutation/tests/test_mutation.py index 420b2db..f2517be 100644 --- a/graphql_relay/mutation/tests/test_mutation.py +++ b/graphql_relay/mutation/tests/test_mutation.py @@ -317,7 +317,7 @@ def test_contains_correct_field(): } } ''' - expected = OrderedDict({ + expected = { '__schema': { 'mutationType': { 'fields': [ @@ -404,7 +404,16 @@ def test_contains_correct_field(): ] } } - }) + } result = graphql(schema, query) assert not result.errors - assert dict(result.data) == expected + # ensure the ordering is correct for the assertion + expected['__schema']['mutationType']['fields'] = sorted( + expected['__schema']['mutationType']['fields'], + key=lambda k: k['name'] + ) + result.data['__schema']['mutationType']['fields'] = sorted( + result.data['__schema']['mutationType']['fields'], + key=lambda k: k['name'] + ) + assert result.data == expected From 148575e1edd21505367a2f0060d689e5df97fe9b Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 23 Nov 2016 16:00:49 +0000 Subject: [PATCH 7/7] Fix unicode issue for global id conversion. --- graphql_relay/node/node.py | 4 +++- graphql_relay/node/tests/__init__.py | 0 graphql_relay/node/tests/test_node.py | 27 ++++++++++++++++++++++++++- graphql_relay/tests/test_utils.py | 4 ++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 graphql_relay/node/tests/__init__.py diff --git a/graphql_relay/node/node.py b/graphql_relay/node/node.py index 0002cba..01ed462 100644 --- a/graphql_relay/node/node.py +++ b/graphql_relay/node/node.py @@ -1,6 +1,8 @@ from collections import OrderedDict from graphql_relay.utils import base64, unbase64 +from six import text_type + from graphql.type import ( GraphQLArgument, GraphQLNonNull, @@ -52,7 +54,7 @@ def to_global_id(type, id): Takes a type name and an ID specific to that type name, and returns a "global ID" that is unique among all types. ''' - return base64(':'.join([type, str(id)])) + return base64(':'.join([type, text_type(id)])) def from_global_id(global_id): diff --git a/graphql_relay/node/tests/__init__.py b/graphql_relay/node/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphql_relay/node/tests/test_node.py b/graphql_relay/node/tests/test_node.py index cef14de..2c6db8e 100644 --- a/graphql_relay/node/tests/test_node.py +++ b/graphql_relay/node/tests/test_node.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + from collections import namedtuple from graphql import graphql from graphql.type import ( @@ -10,7 +13,7 @@ GraphQLID, ) -from graphql_relay.node.node import node_definitions +from ..node import node_definitions, to_global_id, from_global_id User = namedtuple('User', ['id', 'name']) Photo = namedtuple('Photo', ['id', 'width']) @@ -328,3 +331,25 @@ def test_has_correct_node_root_field(): result = graphql(schema, query) assert not result.errors assert result.data == expected + + +def test_to_global_id_converts_unicode_strings_correctly(): + my_unicode_id = u'ûñö' + g_id = to_global_id('MyType', my_unicode_id) + assert g_id == 'TXlUeXBlOsO7w7HDtg==' + + my_unicode_id = u'\u06ED' + g_id = to_global_id('MyType', my_unicode_id) + assert g_id == 'TXlUeXBlOtut' + + +def test_from_global_id_converts_unicode_strings_correctly(): + my_unicode_id = u'ûñö' + my_type, my_id = from_global_id('TXlUeXBlOsO7w7HDtg==') + assert my_type == 'MyType' + assert my_id == my_unicode_id + + my_unicode_id = u'\u06ED' + my_type, my_id = from_global_id('TXlUeXBlOtut') + assert my_type == 'MyType' + assert my_id == my_unicode_id diff --git a/graphql_relay/tests/test_utils.py b/graphql_relay/tests/test_utils.py index 7b1db2d..67e365b 100644 --- a/graphql_relay/tests/test_utils.py +++ b/graphql_relay/tests/test_utils.py @@ -11,6 +11,10 @@ def test_base64_encode_unicode_strings_correctly(): my_base64 = utils.base64(my_unicode) assert my_base64 == base64.b64encode(my_unicode.encode('utf-8')).decode('utf-8') + my_unicode = u'\u06ED' + my_base64 = utils.base64(my_unicode) + assert my_base64 == base64.b64encode(my_unicode.encode('utf-8')).decode('utf-8') + def test_base64_encode_strings_correctly(): my_string = 'abc'