From d7b9fc2c79dc3e979e45078efeaa1b167ece50b9 Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Thu, 27 Oct 2016 07:45:16 +0200 Subject: [PATCH 01/13] handle datetime as datetime.datetime instead of string --- graphene_sqlalchemy/converter.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index 05690697..ab17d32f 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -80,7 +80,6 @@ def convert_sqlalchemy_type(type, column, registry=None): @convert_sqlalchemy_type.register(types.Date) -@convert_sqlalchemy_type.register(types.DateTime) @convert_sqlalchemy_type.register(types.Time) @convert_sqlalchemy_type.register(types.String) @convert_sqlalchemy_type.register(types.Text) @@ -93,6 +92,11 @@ def convert_column_to_string(type, column, registry=None): return String(description=getattr(column, 'doc', None), required=not(getattr(column, 'nullable', True))) +@convert_sqlalchemy_type.register(types.DateTime) +def convert_column_to_datetime(type, column, registry=None): + from graphene.types.datetime import DateTime + return DateTime(description=getattr(column, 'doc', None), + required=not(getattr(column, 'nullable', True))) @convert_sqlalchemy_type.register(types.SmallInteger) @convert_sqlalchemy_type.register(types.BigInteger) From 5920243d238b1a8abd54484112b426e786ce4e2d Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Fri, 28 Oct 2016 07:23:46 +0200 Subject: [PATCH 02/13] convert biginteger to float Biginteger can be too big for integer because integer is limited to 32 bit --- graphene_sqlalchemy/converter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index ab17d32f..db35a7cc 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -99,7 +99,7 @@ def convert_column_to_datetime(type, column, registry=None): required=not(getattr(column, 'nullable', True))) @convert_sqlalchemy_type.register(types.SmallInteger) -@convert_sqlalchemy_type.register(types.BigInteger) +#@convert_sqlalchemy_type.register(types.BigInteger) @convert_sqlalchemy_type.register(types.Integer) def convert_column_to_int_or_id(type, column, registry=None): if column.primary_key: @@ -115,6 +115,7 @@ def convert_column_to_boolean(type, column, registry=None): @convert_sqlalchemy_type.register(types.Float) @convert_sqlalchemy_type.register(types.Numeric) +@convert_sqlalchemy_type.register(types.BigInteger) def convert_column_to_float(type, column, registry=None): return Float(description=column.doc, required=not(column.nullable)) From 92f73ec111f6ecba8daf04ff1f006e44e5a95c24 Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Fri, 18 Nov 2016 08:47:46 +0100 Subject: [PATCH 03/13] Removed commeted BigInteger-int-mapping line --- graphene_sqlalchemy/converter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index db35a7cc..d4bccc2a 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -99,7 +99,6 @@ def convert_column_to_datetime(type, column, registry=None): required=not(getattr(column, 'nullable', True))) @convert_sqlalchemy_type.register(types.SmallInteger) -#@convert_sqlalchemy_type.register(types.BigInteger) @convert_sqlalchemy_type.register(types.Integer) def convert_column_to_int_or_id(type, column, registry=None): if column.primary_key: From 5fdaae6500632eb648e70d05ae0c8db9aa17ecd7 Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Fri, 18 Nov 2016 08:50:35 +0100 Subject: [PATCH 04/13] Create Conections through connection-factory This change allows api users to have the hand on the used ConnectionField implementation. (If filtering/sorting is wanted for example) --- graphene_sqlalchemy/converter.py | 4 ++-- graphene_sqlalchemy/fields.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index d4bccc2a..4ec1dd90 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -8,7 +8,7 @@ from graphene.relay import is_node from graphene.types.json import JSONString -from .fields import SQLAlchemyConnectionField +from .fields import createConnectionField try: from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType @@ -36,7 +36,7 @@ def dynamic_type(): elif (direction == interfaces.ONETOMANY or direction == interfaces.MANYTOMANY): if is_node(_type): - return SQLAlchemyConnectionField(_type) + return createConnectionField(_type) return Field(List(_type)) return Dynamic(dynamic_type) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index de1d301f..beb38942 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -41,3 +41,11 @@ def connection_resolver(cls, resolver, connection, model, root, args, context, i def get_resolver(self, parent_resolver): return partial(self.connection_resolver, parent_resolver, self.type, self.model) + +__connectionFactory = SQLAlchemyConnectionField +def createConnectionField(_type): + return __connectionFactory(_type) + +def registerConnectionFieldFactory(factoryMethod): + global __connectionFactory + __connectionFactory = factoryMethod From 26112de9f1aeeb5a0af591204b10a6996516c57a Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Fri, 18 Nov 2016 16:45:29 +0100 Subject: [PATCH 05/13] Add depndency to iso8601 to correctly handle datetime --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 9f86913d..5e25f028 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ 'graphene>=1.0', 'SQLAlchemy', 'singledispatch>=3.4.0.3', + 'iso8601', ], tests_require=[ 'pytest>=2.7.2', From b8a4c8e7edce6c207b9508c12b25d18c52f4c094 Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Fri, 18 Nov 2016 16:46:50 +0100 Subject: [PATCH 06/13] Add dependency to iso8601: required for datetime handling --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 9f86913d..5e25f028 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ 'graphene>=1.0', 'SQLAlchemy', 'singledispatch>=3.4.0.3', + 'iso8601', ], tests_require=[ 'pytest>=2.7.2', From e5bdaecc5fe5a1263958fe6f05b3f50cd3ad0318 Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Mon, 21 Nov 2016 08:27:02 +0100 Subject: [PATCH 07/13] Create SQLAlchemyConnectionField through a factory method. Overriding the contructor-method gives the user the possibility to enhance the standard implementation --- graphene_sqlalchemy/converter.py | 4 ++-- graphene_sqlalchemy/fields.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index 05690697..9b110cfb 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -8,7 +8,7 @@ from graphene.relay import is_node from graphene.types.json import JSONString -from .fields import SQLAlchemyConnectionField +from .fields import createConnectionField try: from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType @@ -36,7 +36,7 @@ def dynamic_type(): elif (direction == interfaces.ONETOMANY or direction == interfaces.MANYTOMANY): if is_node(_type): - return SQLAlchemyConnectionField(_type) + return createConnectionField(_type) return Field(List(_type)) return Dynamic(dynamic_type) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index de1d301f..0702a022 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -41,3 +41,11 @@ def connection_resolver(cls, resolver, connection, model, root, args, context, i def get_resolver(self, parent_resolver): return partial(self.connection_resolver, parent_resolver, self.type, self.model) + +__connectionFactory = SQLAlchemyConnectionField +def createConnectionField(_type): + return __connectionFactory(_type) + +def registerConnectionFieldFactory(factoryMethod): + global __connectionFactory + __connectionFactory = factoryMethod \ No newline at end of file From cbf0a2289fdb8edf51466f42e8600dcbddf9e53f Mon Sep 17 00:00:00 2001 From: Palm Kevin Date: Mon, 21 Nov 2016 08:41:47 +0100 Subject: [PATCH 08/13] Add free lins to match code lint checks --- graphene_sqlalchemy/fields.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index 0702a022..31c73a5f 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -42,10 +42,14 @@ def connection_resolver(cls, resolver, connection, model, root, args, context, i def get_resolver(self, parent_resolver): return partial(self.connection_resolver, parent_resolver, self.type, self.model) + __connectionFactory = SQLAlchemyConnectionField + + def createConnectionField(_type): return __connectionFactory(_type) + def registerConnectionFieldFactory(factoryMethod): global __connectionFactory - __connectionFactory = factoryMethod \ No newline at end of file + __connectionFactory = factoryMethod From ec928df6e85a7f4b0416820d6236af926a6f00b5 Mon Sep 17 00:00:00 2001 From: Denny Weinberg Date: Tue, 2 May 2017 15:38:17 +0200 Subject: [PATCH 09/13] Added test for connection factory --- .../tests/test_connectionfactory.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 graphene_sqlalchemy/tests/test_connectionfactory.py diff --git a/graphene_sqlalchemy/tests/test_connectionfactory.py b/graphene_sqlalchemy/tests/test_connectionfactory.py new file mode 100644 index 00000000..bca03dac --- /dev/null +++ b/graphene_sqlalchemy/tests/test_connectionfactory.py @@ -0,0 +1,29 @@ +from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory +import graphene + +def test_register(): + class LXConnectionField(SQLAlchemyConnectionField): + @classmethod + def _applyQueryArgs(cls, model, q, args): + return q + + @classmethod + def connection_resolver(cls, resolver, connection, model, root, args, context, info): + + def LXResolver(root, args, context, info): + iterable = resolver(root, args, context, info) + if iterable is None: + iterable = cls.get_query(model, context, info, args) + + # We accept always a query here. All LX-queries can be filtered and sorted + iterable = cls._applyQueryArgs(model, iterable, args) + return iterable + + return SQLAlchemyConnectionField.connection_resolver(LXResolver, connection, model, root, args, context, info) + + def createLXConnectionField(table): + return LXConnectionField(table, filter=table.filter(), order_by=graphene.List(of_type=table.order_by)) + + registerConnectionFieldFactory(createLXConnectionField) + + \ No newline at end of file From c943739e81291d4987c8de8dfaf25d44bdbf192a Mon Sep 17 00:00:00 2001 From: Denny Weinberg Date: Tue, 2 May 2017 16:02:14 +0200 Subject: [PATCH 10/13] Added test for connection factory --- graphene_sqlalchemy/tests/test_connectionfactory.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/graphene_sqlalchemy/tests/test_connectionfactory.py b/graphene_sqlalchemy/tests/test_connectionfactory.py index bca03dac..867c5261 100644 --- a/graphene_sqlalchemy/tests/test_connectionfactory.py +++ b/graphene_sqlalchemy/tests/test_connectionfactory.py @@ -1,4 +1,4 @@ -from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory +from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory, unregisterConnectionFieldFactory import graphene def test_register(): @@ -25,5 +25,4 @@ def createLXConnectionField(table): return LXConnectionField(table, filter=table.filter(), order_by=graphene.List(of_type=table.order_by)) registerConnectionFieldFactory(createLXConnectionField) - - \ No newline at end of file + unregisterConnectionFieldFactory() From 02735385e27e8c73495fda9ee2d491a2767019a6 Mon Sep 17 00:00:00 2001 From: Denny Weinberg Date: Tue, 2 May 2017 16:02:14 +0200 Subject: [PATCH 11/13] Added test for connection factory --- graphene_sqlalchemy/tests/test_connectionfactory.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/graphene_sqlalchemy/tests/test_connectionfactory.py b/graphene_sqlalchemy/tests/test_connectionfactory.py index bca03dac..867c5261 100644 --- a/graphene_sqlalchemy/tests/test_connectionfactory.py +++ b/graphene_sqlalchemy/tests/test_connectionfactory.py @@ -1,4 +1,4 @@ -from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory +from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory, unregisterConnectionFieldFactory import graphene def test_register(): @@ -25,5 +25,4 @@ def createLXConnectionField(table): return LXConnectionField(table, filter=table.filter(), order_by=graphene.List(of_type=table.order_by)) registerConnectionFieldFactory(createLXConnectionField) - - \ No newline at end of file + unregisterConnectionFieldFactory() From c0556efebce21920d42662add4447aabd08de6aa Mon Sep 17 00:00:00 2001 From: Denny Weinberg Date: Tue, 2 May 2017 16:10:07 +0200 Subject: [PATCH 12/13] Added test for connection factory --- graphene_sqlalchemy/fields.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index 31c73a5f..8ac27942 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -53,3 +53,8 @@ def createConnectionField(_type): def registerConnectionFieldFactory(factoryMethod): global __connectionFactory __connectionFactory = factoryMethod + + +def unregisterConnectionFieldFactory(): + global __connectionFactory + __connectionFactory = SQLAlchemyConnectionField From 073dc55fe9cd5faa202f91f0f8ae753350b6e557 Mon Sep 17 00:00:00 2001 From: Denny Weinberg Date: Tue, 2 May 2017 16:35:27 +0200 Subject: [PATCH 13/13] Added test for connection factory Description --- graphene_sqlalchemy/fields.py | 5 +++++ graphene_sqlalchemy/tests/test_connectionfactory.py | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index 31c73a5f..8ac27942 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -53,3 +53,8 @@ def createConnectionField(_type): def registerConnectionFieldFactory(factoryMethod): global __connectionFactory __connectionFactory = factoryMethod + + +def unregisterConnectionFieldFactory(): + global __connectionFactory + __connectionFactory = SQLAlchemyConnectionField diff --git a/graphene_sqlalchemy/tests/test_connectionfactory.py b/graphene_sqlalchemy/tests/test_connectionfactory.py index bca03dac..867c5261 100644 --- a/graphene_sqlalchemy/tests/test_connectionfactory.py +++ b/graphene_sqlalchemy/tests/test_connectionfactory.py @@ -1,4 +1,4 @@ -from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory +from graphene_sqlalchemy.fields import SQLAlchemyConnectionField, registerConnectionFieldFactory, unregisterConnectionFieldFactory import graphene def test_register(): @@ -25,5 +25,4 @@ def createLXConnectionField(table): return LXConnectionField(table, filter=table.filter(), order_by=graphene.List(of_type=table.order_by)) registerConnectionFieldFactory(createLXConnectionField) - - \ No newline at end of file + unregisterConnectionFieldFactory()