From 999b677e30089faf311cf2ae28d9ed09f1df5100 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Tue, 25 Jul 2017 19:56:30 -0700 Subject: [PATCH 1/8] Road to 2.0 --- graphene_sqlalchemy/converter.py | 3 +- graphene_sqlalchemy/fields.py | 10 ++ graphene_sqlalchemy/tests/models.py | 6 ++ graphene_sqlalchemy/tests/test_query.py | 7 +- graphene_sqlalchemy/tests/test_types.py | 15 ++- graphene_sqlalchemy/tests/test_utils.py | 5 +- graphene_sqlalchemy/types.py | 127 ++++++++++++------------ 7 files changed, 98 insertions(+), 75 deletions(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index c8170ba8..34f0f98c 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -5,7 +5,6 @@ from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List, String) -from graphene.relay import is_node from graphene.types.json import JSONString from .fields import SQLAlchemyConnectionField @@ -43,7 +42,7 @@ def dynamic_type(): return Field(_type) elif (direction == interfaces.ONETOMANY or direction == interfaces.MANYTOMANY): - if is_node(_type): + if _type._meta.connection: return SQLAlchemyConnectionField(_type) return Field(List(_type)) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index de1d301f..5b6fc4ca 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -19,6 +19,16 @@ def model(self): def get_query(cls, model, context, info, args): return get_query(model, context) + @property + def type(self): + from .types import SQLAlchemyObjectType + _type = super(ConnectionField, self).type + assert issubclass(_type, SQLAlchemyObjectType), ( + "SQLAlchemyConnectionField only accepts SQLAlchemyObjectType types" + ) + assert _type._meta.connection, "The type {} doesn't have a connection".format(_type.__name__) + return _type._meta.connection + @classmethod def connection_resolver(cls, resolver, connection, model, root, args, context, info): iterable = resolver(root, args, context, info) diff --git a/graphene_sqlalchemy/tests/models.py b/graphene_sqlalchemy/tests/models.py index d4a2c952..3fd6c068 100644 --- a/graphene_sqlalchemy/tests/models.py +++ b/graphene_sqlalchemy/tests/models.py @@ -34,6 +34,12 @@ class Reporter(Base): articles = relationship('Article', backref='reporter') favorite_article = relationship("Article", uselist=False) + # total = column_property( + # select([ + # func.cast(func.count(PersonInfo.id), Float) + # ]) + # ) + class Article(Base): __tablename__ = 'articles' diff --git a/graphene_sqlalchemy/tests/test_query.py b/graphene_sqlalchemy/tests/test_query.py index 042352c8..f2cc78f8 100644 --- a/graphene_sqlalchemy/tests/test_query.py +++ b/graphene_sqlalchemy/tests/test_query.py @@ -277,11 +277,10 @@ class Input: ok = graphene.Boolean() article = graphene.Field(ArticleNode) - @classmethod - def mutate(cls, instance, args, context, info): + def mutate(self, headline, reporter_id): new_article = Article( - headline=args.get('headline'), - reporter_id=args.get('reporter_id'), + headline=headline, + reporter_id=reporter_id, ) session.add(new_article) diff --git a/graphene_sqlalchemy/tests/test_types.py b/graphene_sqlalchemy/tests/test_types.py index 83bdc263..ee4ca283 100644 --- a/graphene_sqlalchemy/tests/test_types.py +++ b/graphene_sqlalchemy/tests/test_types.py @@ -71,6 +71,19 @@ def test_node_replacedfield(): def test_object_type(): + + + class Human(SQLAlchemyObjectType): + '''Human description''' + + pub_date = Int() + + class Meta: + model = Article + # exclude_fields = ('id', ) + registry = registry + interfaces = (Node, ) + assert issubclass(Human, ObjectType) - assert list(Human._meta.fields.keys()) == ['id', 'headline', 'reporter_id', 'reporter', 'pub_date'] + assert list(Human._meta.fields.keys()) == ['id', 'headline', 'pub_date', 'reporter_id', 'reporter'] assert is_node(Human) diff --git a/graphene_sqlalchemy/tests/test_utils.py b/graphene_sqlalchemy/tests/test_utils.py index 484b9f6a..e4b68e6e 100644 --- a/graphene_sqlalchemy/tests/test_utils.py +++ b/graphene_sqlalchemy/tests/test_utils.py @@ -1,4 +1,4 @@ -from graphene import ObjectType, Schema, String +from graphene import ObjectType, Schema, String, annotate, Context from ..utils import get_session @@ -9,7 +9,8 @@ def test_get_session(): class Query(ObjectType): x = String() - def resolve_x(self, args, context, info): + @annotate(context=Context) + def resolve_x(self, context): return get_session(context) query = ''' diff --git a/graphene_sqlalchemy/types.py b/graphene_sqlalchemy/types.py index 70729ed6..955a783b 100644 --- a/graphene_sqlalchemy/types.py +++ b/graphene_sqlalchemy/types.py @@ -1,15 +1,12 @@ from collections import OrderedDict -import six from sqlalchemy.inspection import inspect as sqlalchemyinspect from sqlalchemy.orm.exc import NoResultFound -from graphene import Field, ObjectType -from graphene.relay import is_node -from graphene.types.objecttype import ObjectTypeMeta -from graphene.types.options import Options -from graphene.types.utils import merge, yank_fields_from_attrs -from graphene.utils.is_base_type import is_base_type +from graphene import Field # , annotate, ResolveInfo +from graphene.relay import Connection, Node +from graphene.types.objecttype import ObjectType, ObjectTypeOptions +from graphene.types.utils import yank_fields_from_attrs from .converter import (convert_sqlalchemy_column, convert_sqlalchemy_composite, @@ -18,103 +15,102 @@ from .utils import get_query, is_mapped -def construct_fields(options): - only_fields = options.only_fields - exclude_fields = options.exclude_fields - inspected_model = sqlalchemyinspect(options.model) +def construct_fields(model, registry, only_fields, exclude_fields): + inspected_model = sqlalchemyinspect(model) fields = OrderedDict() for name, column in inspected_model.columns.items(): is_not_in_only = only_fields and name not in only_fields - is_already_created = name in options.fields - is_excluded = name in exclude_fields or is_already_created + # is_already_created = name in options.fields + is_excluded = name in exclude_fields # or is_already_created if is_not_in_only or is_excluded: # We skip this field if we specify only_fields and is not # in there. Or when we excldue this field in exclude_fields continue - converted_column = convert_sqlalchemy_column(column, options.registry) + converted_column = convert_sqlalchemy_column(column, registry) fields[name] = converted_column for name, composite in inspected_model.composites.items(): is_not_in_only = only_fields and name not in only_fields - is_already_created = name in options.fields - is_excluded = name in exclude_fields or is_already_created + # is_already_created = name in options.fields + is_excluded = name in exclude_fields # or is_already_created if is_not_in_only or is_excluded: # We skip this field if we specify only_fields and is not # in there. Or when we excldue this field in exclude_fields continue - converted_composite = convert_sqlalchemy_composite(composite, options.registry) + converted_composite = convert_sqlalchemy_composite(composite, registry) fields[name] = converted_composite # Get all the columns for the relationships on the model for relationship in inspected_model.relationships: is_not_in_only = only_fields and relationship.key not in only_fields - is_already_created = relationship.key in options.fields - is_excluded = relationship.key in exclude_fields or is_already_created + # is_already_created = relationship.key in options.fields + is_excluded = relationship.key in exclude_fields # or is_already_created if is_not_in_only or is_excluded: # We skip this field if we specify only_fields and is not # in there. Or when we excldue this field in exclude_fields continue - converted_relationship = convert_sqlalchemy_relationship(relationship, options.registry) + converted_relationship = convert_sqlalchemy_relationship(relationship, registry) name = relationship.key fields[name] = converted_relationship return fields -class SQLAlchemyObjectTypeMeta(ObjectTypeMeta): - - @staticmethod - def __new__(cls, name, bases, attrs): - # Also ensure initialization is only performed for subclasses of Model - # (excluding Model class itself). - if not is_base_type(bases, SQLAlchemyObjectTypeMeta): - return type.__new__(cls, name, bases, attrs) - - options = Options( - attrs.pop('Meta', None), - name=name, - description=attrs.pop('__doc__', None), - model=None, - local_fields=None, - only_fields=(), - exclude_fields=(), - id='id', - interfaces=(), - registry=None - ) +class SQLAlchemyObjectTypeOptions(ObjectTypeOptions): + model = None # type: Model + registry = None # type: Registry + connection = None # type: Type[Connection] + id = None # type: str + - if not options.registry: - options.registry = get_global_registry() - assert isinstance(options.registry, Registry), ( - 'The attribute registry in {}.Meta needs to be an' - ' instance of Registry, received "{}".' - ).format(name, options.registry) - assert is_mapped(options.model), ( +class SQLAlchemyObjectType(ObjectType): + @classmethod + def __init_subclass_with_meta__(cls, model=None, registry=None, skip_registry=False, + only_fields=(), exclude_fields=(), connection=None, + use_connection=None, interfaces=(), id=None, **options): + assert is_mapped(model), ( 'You need to pass a valid SQLAlchemy Model in ' '{}.Meta, received "{}".' - ).format(name, options.model) + ).format(cls.__name__, model) - cls = ObjectTypeMeta.__new__(cls, name, bases, dict(attrs, _meta=options)) + if not registry: + registry = get_global_registry() - options.registry.register(cls) + assert isinstance(registry, Registry), ( + 'The attribute registry in {} needs to be an instance of ' + 'Registry, received "{}".' + ).format(cls.__name__, registry) - options.sqlalchemy_fields = yank_fields_from_attrs( - construct_fields(options), + sqla_fields = yank_fields_from_attrs( + construct_fields(model, registry, only_fields, exclude_fields), _as=Field, ) - options.fields = merge( - options.interface_fields, - options.sqlalchemy_fields, - options.base_fields, - options.local_fields - ) - return cls + if use_connection is None and interfaces: + use_connection = any((issubclass(interface, Node) for interface in interfaces)) + + if use_connection and not connection: + # We create the connection automatically + connection = Connection.create_type('{}Connection'.format(cls.__name__), node=cls) + + if connection is not None: + assert issubclass(connection, Connection), ( + "The connection must be a Connection. Received {}" + ).format(connection.__name__) + + _meta = SQLAlchemyObjectTypeOptions(cls) + _meta.model = model + _meta.registry = registry + _meta.fields = sqla_fields + _meta.connection = connection + _meta.id = id or 'id' + super(SQLAlchemyObjectType, cls).__init_subclass_with_meta__(_meta=_meta, interfaces=interfaces, **options) -class SQLAlchemyObjectType(six.with_metaclass(SQLAlchemyObjectTypeMeta, ObjectType)): + if not skip_registry: + registry.register(cls) @classmethod def is_type_of(cls, root, context, info): @@ -138,8 +134,7 @@ def get_node(cls, id, context, info): except NoResultFound: return None - def resolve_id(self, args, context, info): - graphene_type = info.parent_type.graphene_type - if is_node(graphene_type): - return self.__mapper__.primary_key_from_instance(self)[0] - return getattr(self, graphene_type._meta.id, None) + # @annotate(info=ResolveInfo) + def resolve_id(self): + # graphene_type = info.parent_type.graphene_type + return self.__mapper__.primary_key_from_instance(self)[0] From 9d1e3c63a9387d75ca1b97201601ea0d8f7d8295 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Tue, 25 Jul 2017 23:38:55 -0700 Subject: [PATCH 2/8] Added extra test for column properties --- graphene_sqlalchemy/tests/test_converter.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/graphene_sqlalchemy/tests/test_converter.py b/graphene_sqlalchemy/tests/test_converter.py index c43b8919..3c732b27 100644 --- a/graphene_sqlalchemy/tests/test_converter.py +++ b/graphene_sqlalchemy/tests/test_converter.py @@ -1,8 +1,8 @@ from py.test import raises -from sqlalchemy import Column, Table, case, types +from sqlalchemy import Column, Table, case, types, select, func from sqlalchemy.dialects import postgresql from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import composite +from sqlalchemy.orm import composite, column_property from sqlalchemy.sql.elements import Label from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType @@ -136,6 +136,23 @@ def test_should_choice_convert_enum(): assert graphene_type._meta.enum.__members__['en'].value == 'English' +def test_should_columproperty_convert(): + + Base = declarative_base() + + class Test(Base): + __tablename__ = 'test' + id = Column(types.Integer, primary_key=True) + column = column_property( + select([func.sum(func.cast(id, types.Integer))]).where( + id==1 + ) + ) + + graphene_type = convert_sqlalchemy_column(Test.column) + assert graphene_type.kwargs['required'] == False + + def test_should_scalar_list_convert_list(): assert_column_conversion(ScalarListType(), graphene.List) From d39871b7c29b854b2e8a5ae98568a999afd957c8 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 26 Jul 2017 19:47:33 -0700 Subject: [PATCH 3/8] Fixed dependency on type Meta --- graphene_sqlalchemy/registry.py | 6 +++--- graphene_sqlalchemy/tests/test_query.py | 2 +- graphene_sqlalchemy/tests/test_types.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/graphene_sqlalchemy/registry.py b/graphene_sqlalchemy/registry.py index 091aaf25..61285cbf 100644 --- a/graphene_sqlalchemy/registry.py +++ b/graphene_sqlalchemy/registry.py @@ -6,9 +6,9 @@ def __init__(self): self._registry_composites = {} def register(self, cls): - from .types import SQLAlchemyObjectTypeMeta - assert issubclass(type(cls), SQLAlchemyObjectTypeMeta), ( - 'Only classes of type SQLAlchemyObjectTypeMeta can be registered, ', + from .types import SQLAlchemyObjectType + assert issubclass(cls, SQLAlchemyObjectType), ( + 'Only classes of type SQLAlchemyObjectType can be registered, ', 'received "{}"' ).format(cls.__name__) assert cls._meta.registry == self, 'Registry for a Model have to match.' diff --git a/graphene_sqlalchemy/tests/test_query.py b/graphene_sqlalchemy/tests/test_query.py index f2cc78f8..707d7b95 100644 --- a/graphene_sqlalchemy/tests/test_query.py +++ b/graphene_sqlalchemy/tests/test_query.py @@ -270,7 +270,7 @@ class Meta: class CreateArticle(graphene.Mutation): - class Input: + class Arguments: headline = graphene.String() reporter_id = graphene.ID() diff --git a/graphene_sqlalchemy/tests/test_types.py b/graphene_sqlalchemy/tests/test_types.py index 16922b2d..3f017aae 100644 --- a/graphene_sqlalchemy/tests/test_types.py +++ b/graphene_sqlalchemy/tests/test_types.py @@ -4,7 +4,7 @@ import six from ..registry import Registry -from ..types import SQLAlchemyObjectType, SQLAlchemyObjectTypeMeta +from ..types import SQLAlchemyObjectType from .models import Article, Reporter registry = Registry() From 76daafbea99e4031466c77f4fbacbcc7003f3339 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 26 Jul 2017 20:04:40 -0700 Subject: [PATCH 4/8] Fixed flake issues --- graphene_sqlalchemy/converter.py | 8 +++++--- graphene_sqlalchemy/types.py | 13 +++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index 78d0207d..17e54b0f 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -47,10 +47,12 @@ def dynamic_type(): return Field(List(_type)) return Dynamic(dynamic_type) - + + def convert_sqlalchemy_hybrid_method(hybrid_item): - return String(description=getattr(hybrid_item, '__doc__', None), - required=False) + return String(description=getattr(hybrid_item, '__doc__', None), + required=False) + def convert_sqlalchemy_composite(composite, registry): converter = registry.get_converter_for_composite(composite.composite_class) diff --git a/graphene_sqlalchemy/types.py b/graphene_sqlalchemy/types.py index 2368cade..d7c98cab 100644 --- a/graphene_sqlalchemy/types.py +++ b/graphene_sqlalchemy/types.py @@ -50,16 +50,17 @@ def construct_fields(model, registry, only_fields, exclude_fields): name = hybrid_item.__name__ is_not_in_only = only_fields and name not in only_fields - is_already_created = name in options.fields - is_excluded = name in exclude_fields or is_already_created + # is_already_created = name in options.fields + is_excluded = name in exclude_fields # or is_already_created if is_not_in_only or is_excluded: - # We skip this field if we specify only_fields and is not - # in there. Or when we excldue this field in exclude_fields - + # We skip this field if we specify only_fields and is not + # in there. Or when we excldue this field in exclude_fields continue + converted_hybrid_property = convert_sqlalchemy_hybrid_method( - hybrid_item) + hybrid_item + ) fields[name] = converted_hybrid_property # Get all the columns for the relationships on the model From fb6fb691f94430c2ee95bb6d25329c55399f34d0 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 26 Jul 2017 23:38:05 -0700 Subject: [PATCH 5/8] Improved resolver consistency --- graphene_sqlalchemy/fields.py | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index 60cb9557..01fd392f 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -2,6 +2,7 @@ from sqlalchemy.orm.query import Query +from graphene import final_resolver from graphene.relay import ConnectionField from graphene.relay.connection import PageInfo from graphql_relay.connection.arrayconnection import connection_from_list_slice @@ -53,7 +54,7 @@ def connection_resolver(cls, resolver, connection, model, root, args, context, i return connection def get_resolver(self, parent_resolver): - return partial(self.connection_resolver, parent_resolver, self.type, self.model) + return final_resolver(partial(self.connection_resolver, parent_resolver, self.type, self.model)) __connectionFactory = SQLAlchemyConnectionField diff --git a/setup.py b/setup.py index 9bfb5882..2494ffad 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='graphene-sqlalchemy', - version='1.1.1', + version='2.0.dev2017072601', description='Graphene SQLAlchemy integration', long_description=open('README.rst').read(), From 41309d08fe8f56bb3a36f88d52e2756a3c420276 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 31 Jul 2017 20:27:25 -0700 Subject: [PATCH 6/8] Adapted code to the new resovlers api --- graphene_sqlalchemy/fields.py | 13 ++++++------- graphene_sqlalchemy/tests/test_query.py | 2 +- graphene_sqlalchemy/tests/test_utils.py | 7 +++---- graphene_sqlalchemy/types.py | 13 ++++++------- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index 01fd392f..bb084b3a 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -2,7 +2,6 @@ from sqlalchemy.orm.query import Query -from graphene import final_resolver from graphene.relay import ConnectionField from graphene.relay.connection import PageInfo from graphql_relay.connection.arrayconnection import connection_from_list_slice @@ -17,8 +16,8 @@ def model(self): return self.type._meta.node._meta.model @classmethod - def get_query(cls, model, context, info, args): - return get_query(model, context) + def get_query(cls, model, info, **args): + return get_query(model, info.context) @property def type(self): @@ -31,10 +30,10 @@ def type(self): return _type._meta.connection @classmethod - def connection_resolver(cls, resolver, connection, model, root, args, context, info): - iterable = resolver(root, args, context, info) + def connection_resolver(cls, resolver, connection, model, root, info, **args): + iterable = resolver(root, info, **args) if iterable is None: - iterable = cls.get_query(model, context, info, args) + iterable = cls.get_query(model, info, **args) if isinstance(iterable, Query): _len = iterable.count() else: @@ -54,7 +53,7 @@ def connection_resolver(cls, resolver, connection, model, root, args, context, i return connection def get_resolver(self, parent_resolver): - return final_resolver(partial(self.connection_resolver, parent_resolver, self.type, self.model)) + return partial(self.connection_resolver, parent_resolver, self.type, self.model) __connectionFactory = SQLAlchemyConnectionField diff --git a/graphene_sqlalchemy/tests/test_query.py b/graphene_sqlalchemy/tests/test_query.py index 707d7b95..e4c3f835 100644 --- a/graphene_sqlalchemy/tests/test_query.py +++ b/graphene_sqlalchemy/tests/test_query.py @@ -277,7 +277,7 @@ class Arguments: ok = graphene.Boolean() article = graphene.Field(ArticleNode) - def mutate(self, headline, reporter_id): + def mutate(self, info, headline, reporter_id): new_article = Article( headline=headline, reporter_id=reporter_id, diff --git a/graphene_sqlalchemy/tests/test_utils.py b/graphene_sqlalchemy/tests/test_utils.py index e4b68e6e..8af3c61e 100644 --- a/graphene_sqlalchemy/tests/test_utils.py +++ b/graphene_sqlalchemy/tests/test_utils.py @@ -1,4 +1,4 @@ -from graphene import ObjectType, Schema, String, annotate, Context +from graphene import ObjectType, Schema, String from ..utils import get_session @@ -9,9 +9,8 @@ def test_get_session(): class Query(ObjectType): x = String() - @annotate(context=Context) - def resolve_x(self, context): - return get_session(context) + def resolve_x(self, info): + return get_session(info.context) query = ''' query ReporterQuery { diff --git a/graphene_sqlalchemy/types.py b/graphene_sqlalchemy/types.py index d7c98cab..44bf9c27 100644 --- a/graphene_sqlalchemy/types.py +++ b/graphene_sqlalchemy/types.py @@ -134,7 +134,7 @@ def __init_subclass_with_meta__(cls, model=None, registry=None, skip_registry=Fa registry.register(cls) @classmethod - def is_type_of(cls, root, context, info): + def is_type_of(cls, root, info): if isinstance(root, cls): return True if not is_mapped_instance(root): @@ -144,19 +144,18 @@ def is_type_of(cls, root, context, info): return isinstance(root, cls._meta.model) @classmethod - def get_query(cls, context): + def get_query(cls, info): model = cls._meta.model - return get_query(model, context) + return get_query(model, info.context) @classmethod - def get_node(cls, id, context, info): + def get_node(cls, info, id): try: - return cls.get_query(context).get(id) + return cls.get_query(info).get(id) except NoResultFound: return None - # @annotate(info=ResolveInfo) - def resolve_id(self): + def resolve_id(self, info): # graphene_type = info.parent_type.graphene_type keys = self.__mapper__.primary_key_from_instance(self) return tuple(keys) if len(keys) > 1 else keys[0] From 514eaae8671ab77bc7b5e2f252ad67c9bd327206 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 31 Jul 2017 22:52:20 -0700 Subject: [PATCH 7/8] Added support for wheel distribution package --- .travis.yml | 1 + README.md | 10 +++++----- README.rst | 10 +++++----- graphene_sqlalchemy/__init__.py | 13 +++++++++---- setup.cfg | 3 +++ setup.py | 12 +++++++++++- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76a4dc6f..713d720e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,3 +57,4 @@ deploy: tags: true password: secure: q0ey31cWljGB30l43aEd1KIPuAHRutzmsd2lBb/2zvD79ReBrzvCdFAkH2xcyo4Volk3aazQQTNUIurnTuvBxmtqja0e+gUaO5LdOcokVdOGyLABXh7qhd2kdvbTDWgSwA4EWneLGXn/SjXSe0f3pCcrwc6WDcLAHxtffMvO9gulpYQtUoOqXfMipMOkRD9iDWTJBsSo3trL70X1FHOVr6Yqi0mfkX2Y/imxn6wlTWRz28Ru94xrj27OmUnCv7qcG0taO8LNlUCquNFAr2sZ+l+U/GkQrrM1y+ehPz3pmI0cCCd7SX/7+EG9ViZ07BZ31nk4pgnqjmj3nFwqnCE/4IApGnduqtrMDF63C9TnB1TU8oJmbbUCu4ODwRpBPZMnwzaHsLnrpdrB89/98NtTfujdrh3U5bVB+t33yxrXVh+FjgLYj9PVeDixpFDn6V/Xcnv4BbRMNOhXIQT7a7/5b99RiXBjCk6KRu+Jdu5DZ+3G4Nbr4oim3kZFPUHa555qbzTlwAfkrQxKv3C3OdVJR7eGc9ADsbHyEJbdPNAh/T+xblXTXLS3hPYDvgM+WEGy3CytBDG3JVcXm25ZP96EDWjweJ7MyfylubhuKj/iR1Y1wiHeIsYq9CqRrFQUWL8gFJBfmgjs96xRXXXnvyLtKUKpKw3wFg5cR/6FnLeYZ8k= + distributions: "sdist bdist_wheel" diff --git a/README.md b/README.md index 7178e99f..876381d5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -Please read [UPGRADE-v1.0.md](https://github.com/graphql-python/graphene/blob/master/UPGRADE-v1.0.md) -to learn how to upgrade to Graphene `1.0`. +Please read [UPGRADE-v2.0.md](https://github.com/graphql-python/graphene/blob/master/UPGRADE-v2.0.md) +to learn how to upgrade to Graphene `2.0`. --- @@ -13,7 +13,7 @@ A [SQLAlchemy](http://www.sqlalchemy.org/) integration for [Graphene](http://gra For instaling graphene, just run this command in your shell ```bash -pip install "graphene-sqlalchemy>=1.0" +pip install "graphene-sqlalchemy>=2.0" ``` ## Examples @@ -47,8 +47,8 @@ class User(SQLAlchemyObjectType): class Query(graphene.ObjectType): users = graphene.List(User) - def resolve_users(self, args, context, info): - query = User.get_query(context) # SQLAlchemy query + def resolve_users(self, info): + query = User.get_query(info.context) # SQLAlchemy query return query.all() schema = graphene.Schema(query=Query) diff --git a/README.rst b/README.rst index e1983a2a..e367d430 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ Please read -`UPGRADE-v1.0.md `__ -to learn how to upgrade to Graphene ``1.0``. +`UPGRADE-v2.0.md `__ +to learn how to upgrade to Graphene ``2.0``. -------------- @@ -17,7 +17,7 @@ For instaling graphene, just run this command in your shell .. code:: bash - pip install "graphene-sqlalchemy>=1.0" + pip install "graphene-sqlalchemy>=2.0" Examples -------- @@ -53,8 +53,8 @@ following: class Query(graphene.ObjectType): users = graphene.List(User) - def resolve_users(self, args, context, info): - query = User.get_query(context) # SQLAlchemy query + def resolve_users(self, info): + query = User.get_query(info.context) # SQLAlchemy query return query.all() schema = graphene.Schema(query=Query) diff --git a/graphene_sqlalchemy/__init__.py b/graphene_sqlalchemy/__init__.py index 5c6c0b38..a6438b9a 100644 --- a/graphene_sqlalchemy/__init__.py +++ b/graphene_sqlalchemy/__init__.py @@ -9,7 +9,12 @@ get_session ) -__all__ = ['SQLAlchemyObjectType', - 'SQLAlchemyConnectionField', - 'get_query', - 'get_session'] +__version__ = '2.0.dev2017072601' + +__all__ = [ + '__version__', + 'SQLAlchemyObjectType', + 'SQLAlchemyConnectionField', + 'get_query', + 'get_session' +] diff --git a/setup.cfg b/setup.cfg index 558f31d7..d8d54e3f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,3 +24,6 @@ norecursedirs = filterwarnings = error ignore::DeprecationWarning + +[bdist_wheel] +universal=1 diff --git a/setup.py b/setup.py index 2494ffad..1853009b 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,18 @@ from setuptools import find_packages, setup +import sys +import ast +import re + +_version_re = re.compile(r'__version__\s+=\s+(.*)') + +with open('graphene_django/__init__.py', 'rb') as f: + version = str(ast.literal_eval(_version_re.search( + f.read().decode('utf-8')).group(1))) + setup( name='graphene-sqlalchemy', - version='2.0.dev2017072601', + version=version, description='Graphene SQLAlchemy integration', long_description=open('README.rst').read(), From ac7b670bcae1a60bc8b2c7f0ebd1a54eb807559e Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 31 Jul 2017 23:13:21 -0700 Subject: [PATCH 8/8] Updated version --- graphene_sqlalchemy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene_sqlalchemy/__init__.py b/graphene_sqlalchemy/__init__.py index a6438b9a..88cbeb43 100644 --- a/graphene_sqlalchemy/__init__.py +++ b/graphene_sqlalchemy/__init__.py @@ -9,7 +9,7 @@ get_session ) -__version__ = '2.0.dev2017072601' +__version__ = '2.0.dev2017073101' __all__ = [ '__version__',