Skip to content

Commit a8cb000

Browse files
committed
add support for sqlalchemy 1.1
1 parent d7ff41f commit a8cb000

File tree

4 files changed

+28
-27
lines changed

4 files changed

+28
-27
lines changed

graphene_sqlalchemy/converter.py

+15-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from sqlalchemy.dialects import postgresql
66
from sqlalchemy.ext.hybrid import hybrid_property
77
from sqlalchemy.orm import (ColumnProperty, CompositeProperty,
8-
RelationshipProperty, interfaces, strategies)
8+
RelationshipProperty, class_mapper, interfaces,
9+
strategies)
910
from sqlalchemy.orm.attributes import InstrumentedAttribute
1011

1112
from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List,
@@ -36,39 +37,36 @@ def is_column_nullable(column):
3637
return bool(getattr(column, "nullable", True))
3738

3839

39-
def convert_sqlalchemy_association_proxy(association_prop, obj_type, registry, connection_field_factory, batching, resolver, **field_kwargs):
40-
model = association_prop.target_class
41-
42-
attr = getattr(model, association_prop.value_attr)
43-
if isinstance(attr, InstrumentedAttribute):
44-
attr = inspect(attr).property
45-
40+
def convert_sqlalchemy_association_proxy(parent, assoc_prop, obj_type, registry, connection_field_factory, batching, resolver, **field_kwargs):
4641
def dynamic_type():
42+
prop = class_mapper(parent).attrs[assoc_prop.target_collection]
43+
scalar = not prop.uselist
44+
model = prop.mapper.class_
45+
attr = class_mapper(model).attrs[assoc_prop.value_attr]
46+
4747
if isinstance(attr, ColumnProperty):
4848
field = convert_sqlalchemy_column(
4949
attr,
5050
registry,
5151
resolver,
5252
**field_kwargs
5353
)
54-
if not association_prop.scalar:
54+
if not scalar:
5555
# repackage as List
5656
field.__dict__['_type'] = List(field.type)
57-
58-
return field
5957
elif isinstance(attr, RelationshipProperty):
60-
batching_ = field_kwargs.pop('batching', batching)
61-
return convert_sqlalchemy_relationship(
58+
field = convert_sqlalchemy_relationship(
6259
attr,
6360
obj_type,
6461
connection_field_factory,
65-
batching_,
66-
association_prop.value_attr,
62+
field_kwargs.pop('batching', batching),
63+
assoc_prop.value_attr,
6764
**field_kwargs
68-
# resolve Dynamic type
6965
).get_type()
66+
else:
67+
raise NotImplementedError(attr)
7068

71-
raise NotImplementedError(attr)
69+
return field
7270

7371
return Dynamic(dynamic_type)
7472

graphene_sqlalchemy/tests/test_converter.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -291,28 +291,29 @@ class P(SQLAlchemyObjectType):
291291
class Meta:
292292
model = Pet
293293

294-
dynamic_field = convert_sqlalchemy_association_proxy(
294+
field = convert_sqlalchemy_association_proxy(
295+
Reporter,
295296
Reporter.pet_names,
296297
P,
297298
get_global_registry(),
298299
default_connection_field_factory,
299300
True,
300301
mock_resolver,
301302
)
302-
assert isinstance(dynamic_field, graphene.Dynamic)
303-
graphene_type = dynamic_field.get_type()
304-
assert isinstance(graphene_type, graphene.Field)
305-
assert isinstance(graphene_type.type, graphene.List)
306-
assert graphene_type.type.of_type == graphene.String
303+
assert isinstance(field, graphene.Dynamic)
304+
assert isinstance(field.get_type().type, graphene.List)
305+
assert field.get_type().type.of_type == graphene.String
307306

308307
dynamic_field = convert_sqlalchemy_association_proxy(
308+
Article,
309309
Article.reporter_pets,
310310
P,
311311
get_global_registry(),
312312
default_connection_field_factory,
313313
True,
314314
mock_resolver,
315315
)
316+
assert isinstance(dynamic_field, graphene.Dynamic)
316317
assert dynamic_field.get_type().type.of_type == P
317318

318319

graphene_sqlalchemy/tests/test_types.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ class Meta:
121121
assert favorite_article_field.type().description is None
122122

123123
# assocation proxy
124-
assoc_prop = ReporterType._meta.fields['pet_names']
125-
assert isinstance(assoc_prop, Dynamic)
126-
assert assoc_prop.type().type == List(String)
124+
assoc_field = ReporterType._meta.fields['pet_names']
125+
assert isinstance(assoc_field, Dynamic)
126+
assert isinstance(assoc_field.type().type, List)
127+
assert assoc_field.type().type.of_type == String
127128

128129

129130
def test_sqlalchemy_override_fields():

graphene_sqlalchemy/types.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ def construct_fields(
179179
field = convert_sqlalchemy_hybrid_method(attr, resolver, **orm_field.kwargs)
180180
elif isinstance(attr, AssociationProxy):
181181
field = convert_sqlalchemy_association_proxy(
182-
attr.for_class(model),
182+
model,
183+
attr,
183184
obj_type,
184185
registry,
185186
connection_field_factory,

0 commit comments

Comments
 (0)