Skip to content

Commit 1d353f7

Browse files
authored
Merge pull request #57 from graphql-python/features/2.0
Road to 2.0
2 parents c2da407 + ac7b670 commit 1d353f7

File tree

15 files changed

+182
-125
lines changed

15 files changed

+182
-125
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ deploy:
5757
tags: true
5858
password:
5959
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=
60+
distributions: "sdist bdist_wheel"

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Please read [UPGRADE-v1.0.md](https://github.com/graphql-python/graphene/blob/master/UPGRADE-v1.0.md)
2-
to learn how to upgrade to Graphene `1.0`.
1+
Please read [UPGRADE-v2.0.md](https://github.com/graphql-python/graphene/blob/master/UPGRADE-v2.0.md)
2+
to learn how to upgrade to Graphene `2.0`.
33

44
---
55

@@ -13,7 +13,7 @@ A [SQLAlchemy](http://www.sqlalchemy.org/) integration for [Graphene](http://gra
1313
For instaling graphene, just run this command in your shell
1414

1515
```bash
16-
pip install "graphene-sqlalchemy>=1.0"
16+
pip install "graphene-sqlalchemy>=2.0"
1717
```
1818

1919
## Examples
@@ -47,8 +47,8 @@ class User(SQLAlchemyObjectType):
4747
class Query(graphene.ObjectType):
4848
users = graphene.List(User)
4949

50-
def resolve_users(self, args, context, info):
51-
query = User.get_query(context) # SQLAlchemy query
50+
def resolve_users(self, info):
51+
query = User.get_query(info.context) # SQLAlchemy query
5252
return query.all()
5353

5454
schema = graphene.Schema(query=Query)

README.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Please read
2-
`UPGRADE-v1.0.md <https://github.com/graphql-python/graphene/blob/master/UPGRADE-v1.0.md>`__
3-
to learn how to upgrade to Graphene ``1.0``.
2+
`UPGRADE-v2.0.md <https://github.com/graphql-python/graphene/blob/master/UPGRADE-v2.0.md>`__
3+
to learn how to upgrade to Graphene ``2.0``.
44

55
--------------
66

@@ -17,7 +17,7 @@ For instaling graphene, just run this command in your shell
1717

1818
.. code:: bash
1919
20-
pip install "graphene-sqlalchemy>=1.0"
20+
pip install "graphene-sqlalchemy>=2.0"
2121
2222
Examples
2323
--------
@@ -53,8 +53,8 @@ following:
5353
class Query(graphene.ObjectType):
5454
users = graphene.List(User)
5555
56-
def resolve_users(self, args, context, info):
57-
query = User.get_query(context) # SQLAlchemy query
56+
def resolve_users(self, info):
57+
query = User.get_query(info.context) # SQLAlchemy query
5858
return query.all()
5959
6060
schema = graphene.Schema(query=Query)

graphene_sqlalchemy/__init__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
get_session
1010
)
1111

12-
__all__ = ['SQLAlchemyObjectType',
13-
'SQLAlchemyConnectionField',
14-
'get_query',
15-
'get_session']
12+
__version__ = '2.0.dev2017073101'
13+
14+
__all__ = [
15+
'__version__',
16+
'SQLAlchemyObjectType',
17+
'SQLAlchemyConnectionField',
18+
'get_query',
19+
'get_session'
20+
]

graphene_sqlalchemy/converter.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List,
77
String)
8-
from graphene.relay import is_node
98
from graphene.types.json import JSONString
109

1110
from .fields import createConnectionField
@@ -43,15 +42,17 @@ def dynamic_type():
4342
return Field(_type)
4443
elif (direction == interfaces.ONETOMANY or
4544
direction == interfaces.MANYTOMANY):
46-
if is_node(_type):
45+
if _type._meta.connection:
4746
return createConnectionField(_type)
4847
return Field(List(_type))
4948

5049
return Dynamic(dynamic_type)
51-
50+
51+
5252
def convert_sqlalchemy_hybrid_method(hybrid_item):
53-
return String(description=getattr(hybrid_item, '__doc__', None),
54-
required=False)
53+
return String(description=getattr(hybrid_item, '__doc__', None),
54+
required=False)
55+
5556

5657
def convert_sqlalchemy_composite(composite, registry):
5758
converter = registry.get_converter_for_composite(composite.composite_class)

graphene_sqlalchemy/fields.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,24 @@ def model(self):
1616
return self.type._meta.node._meta.model
1717

1818
@classmethod
19-
def get_query(cls, model, context, info, args):
20-
return get_query(model, context)
19+
def get_query(cls, model, info, **args):
20+
return get_query(model, info.context)
21+
22+
@property
23+
def type(self):
24+
from .types import SQLAlchemyObjectType
25+
_type = super(ConnectionField, self).type
26+
assert issubclass(_type, SQLAlchemyObjectType), (
27+
"SQLAlchemyConnectionField only accepts SQLAlchemyObjectType types"
28+
)
29+
assert _type._meta.connection, "The type {} doesn't have a connection".format(_type.__name__)
30+
return _type._meta.connection
2131

2232
@classmethod
23-
def connection_resolver(cls, resolver, connection, model, root, args, context, info):
24-
iterable = resolver(root, args, context, info)
33+
def connection_resolver(cls, resolver, connection, model, root, info, **args):
34+
iterable = resolver(root, info, **args)
2535
if iterable is None:
26-
iterable = cls.get_query(model, context, info, args)
36+
iterable = cls.get_query(model, info, **args)
2737
if isinstance(iterable, Query):
2838
_len = iterable.count()
2939
else:

graphene_sqlalchemy/registry.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ def __init__(self):
66
self._registry_composites = {}
77

88
def register(self, cls):
9-
from .types import SQLAlchemyObjectTypeMeta
10-
assert issubclass(type(cls), SQLAlchemyObjectTypeMeta), (
11-
'Only classes of type SQLAlchemyObjectTypeMeta can be registered, ',
9+
from .types import SQLAlchemyObjectType
10+
assert issubclass(cls, SQLAlchemyObjectType), (
11+
'Only classes of type SQLAlchemyObjectType can be registered, ',
1212
'received "{}"'
1313
).format(cls.__name__)
1414
assert cls._meta.registry == self, 'Registry for a Model have to match.'

graphene_sqlalchemy/tests/models.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ class Reporter(Base):
3434
articles = relationship('Article', backref='reporter')
3535
favorite_article = relationship("Article", uselist=False)
3636

37+
# total = column_property(
38+
# select([
39+
# func.cast(func.count(PersonInfo.id), Float)
40+
# ])
41+
# )
42+
3743

3844
class Article(Base):
3945
__tablename__ = 'articles'
@@ -43,8 +49,11 @@ class Article(Base):
4349
reporter_id = Column(Integer(), ForeignKey('reporters.id'))
4450

4551

46-
class ReflectedEditor:
52+
class ReflectedEditor(type):
4753
"""Same as Editor, but using reflected table."""
54+
@classmethod
55+
def __subclasses__(cls):
56+
return []
4857

4958
editor_table = Table('editors', Base.metadata, autoload=True)
5059

graphene_sqlalchemy/tests/test_converter.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from py.test import raises
2-
from sqlalchemy import Column, Table, case, types
2+
from sqlalchemy import Column, Table, case, types, select, func
33
from sqlalchemy.dialects import postgresql
44
from sqlalchemy.ext.declarative import declarative_base
5-
from sqlalchemy.orm import composite
5+
from sqlalchemy.orm import composite, column_property
66
from sqlalchemy.sql.elements import Label
77
from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType
88

@@ -136,6 +136,23 @@ def test_should_choice_convert_enum():
136136
assert graphene_type._meta.enum.__members__['en'].value == 'English'
137137

138138

139+
def test_should_columproperty_convert():
140+
141+
Base = declarative_base()
142+
143+
class Test(Base):
144+
__tablename__ = 'test'
145+
id = Column(types.Integer, primary_key=True)
146+
column = column_property(
147+
select([func.sum(func.cast(id, types.Integer))]).where(
148+
id==1
149+
)
150+
)
151+
152+
graphene_type = convert_sqlalchemy_column(Test.column)
153+
assert graphene_type.kwargs['required'] == False
154+
155+
139156
def test_should_scalar_list_convert_list():
140157
assert_column_conversion(ScalarListType(), graphene.List)
141158

graphene_sqlalchemy/tests/test_query.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,18 +270,17 @@ class Meta:
270270

271271
class CreateArticle(graphene.Mutation):
272272

273-
class Input:
273+
class Arguments:
274274
headline = graphene.String()
275275
reporter_id = graphene.ID()
276276

277277
ok = graphene.Boolean()
278278
article = graphene.Field(ArticleNode)
279279

280-
@classmethod
281-
def mutate(cls, instance, args, context, info):
280+
def mutate(self, info, headline, reporter_id):
282281
new_article = Article(
283-
headline=args.get('headline'),
284-
reporter_id=args.get('reporter_id'),
282+
headline=headline,
283+
reporter_id=reporter_id,
285284
)
286285

287286
session.add(new_article)

graphene_sqlalchemy/tests/test_types.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import six
55

66
from ..registry import Registry
7-
from ..types import SQLAlchemyObjectType, SQLAlchemyObjectTypeMeta
7+
from ..types import SQLAlchemyObjectType
88
from .models import Article, Reporter
99

1010
registry = Registry()
@@ -72,8 +72,21 @@ def test_node_replacedfield():
7272

7373

7474
def test_object_type():
75+
76+
77+
class Human(SQLAlchemyObjectType):
78+
'''Human description'''
79+
80+
pub_date = Int()
81+
82+
class Meta:
83+
model = Article
84+
# exclude_fields = ('id', )
85+
registry = registry
86+
interfaces = (Node, )
87+
7588
assert issubclass(Human, ObjectType)
76-
assert list(Human._meta.fields.keys()) == ['id', 'headline', 'reporter_id', 'reporter', 'pub_date']
89+
assert list(Human._meta.fields.keys()) == ['id', 'headline', 'pub_date', 'reporter_id', 'reporter']
7790
assert is_node(Human)
7891

7992

graphene_sqlalchemy/tests/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ def test_get_session():
99
class Query(ObjectType):
1010
x = String()
1111

12-
def resolve_x(self, args, context, info):
13-
return get_session(context)
12+
def resolve_x(self, info):
13+
return get_session(info.context)
1414

1515
query = '''
1616
query ReporterQuery {

0 commit comments

Comments
 (0)