Skip to content
This repository was archived by the owner on Sep 6, 2022. It is now read-only.

Adapt code to Graphene 2.0 #30

Merged
merged 8 commits into from
Aug 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ A Google AppEngine integration library for `Graphene <http://graphene-python.org

Upgrade Notes
-------------
If you're upgrading from an older version (pre 1.0 version) please check out the `Graphene Upgrade Guide <https://github.com/graphql-python/graphene/blob/master/UPGRADE-v1.0.md>`
If you're upgrading from an older version (pre 2.0 version)
please check out the `Graphene Upgrade Guide <https://github.com/graphql-python/graphene/blob/master/UPGRADE-v2.0.md>`__.


Installation
Expand Down
17 changes: 6 additions & 11 deletions examples/starwars/schema.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from google.appengine.ext import ndb

import graphene
from graphene import relay, resolve_only_args
from graphene import relay
from graphene_gae import NdbObjectType, NdbConnectionField

from .data import create_ship
Expand Down Expand Up @@ -30,7 +30,7 @@ class Meta:

ships = NdbConnectionField(Ship)

def resolve_ships(self, *_):
def resolve_ships(self, info, **args):
return ShipModel.query().filter(ShipModel.faction_key == self.key)


Expand All @@ -43,9 +43,7 @@ class Input:
faction = graphene.Field(Faction)

@classmethod
def mutate_and_get_payload(cls, input, context, info):
ship_name = input.get('ship_name')
faction_id = input.get('faction_id')
def mutate_and_get_payload(cls, root, info, ship_name, faction_id, client_mutation_id=None):
faction_key = ndb.Key(FactionModel, faction_id)
ship = create_ship(ship_name, faction_key)
faction = faction_key.get()
Expand All @@ -58,16 +56,13 @@ class Query(graphene.ObjectType):
node = relay.Node.Field()
ships = NdbConnectionField(Ship)

@resolve_only_args
def resolve_ships(self):
def resolve_ships(self, info, **args):
return ShipModel.query()

@resolve_only_args
def resolve_rebels(self):
def resolve_rebels(self, info):
return FactionModel.get_by_id("rebels")

@resolve_only_args
def resolve_empire(self):
def resolve_empire(self, info):
return FactionModel.get_by_id("empire")


Expand Down
2 changes: 1 addition & 1 deletion graphene_gae/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)

__author__ = 'Eran Kampf'
__version__ = '1.0.7'
__version__ = '2.0.dev2017073101'

__all__ = [
NdbObjectType,
Expand Down
31 changes: 15 additions & 16 deletions graphene_gae/ndb/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def rreplace(s, old, new, occurrence):
return new.join(li)


def convert_ndb_scalar_property(graphene_type, ndb_prop, **kwargs):
def convert_ndb_scalar_property(graphene_type, ndb_prop, registry=None, **kwargs):
kwargs['description'] = "%s %s property" % (ndb_prop._name, graphene_type)
_type = graphene_type

Expand All @@ -36,31 +36,31 @@ def convert_ndb_scalar_property(graphene_type, ndb_prop, **kwargs):
return Field(_type, **kwargs)


def convert_ndb_string_property(ndb_prop):
def convert_ndb_string_property(ndb_prop, registry=None):
return convert_ndb_scalar_property(String, ndb_prop)


def convert_ndb_boolean_property(ndb_prop):
def convert_ndb_boolean_property(ndb_prop, registry=None):
return convert_ndb_scalar_property(Boolean, ndb_prop)


def convert_ndb_int_property(ndb_prop):
def convert_ndb_int_property(ndb_prop, registry=None):
return convert_ndb_scalar_property(Int, ndb_prop)


def convert_ndb_float_property(ndb_prop):
def convert_ndb_float_property(ndb_prop, registry=None):
return convert_ndb_scalar_property(Float, ndb_prop)


def convert_ndb_json_property(ndb_prop):
def convert_ndb_json_property(ndb_prop, registry=None):
return Field(JSONString, description=ndb_prop._name)


def convert_ndb_datetime_property(ndb_prop):
def convert_ndb_datetime_property(ndb_prop, registry=None):
return Field(DateTime, description=ndb_prop._name)


def convert_ndb_key_propety(ndb_key_prop):
def convert_ndb_key_propety(ndb_key_prop, registry=None):
"""
Two conventions for handling KeyProperties:
#1.
Expand Down Expand Up @@ -94,20 +94,19 @@ def convert_ndb_key_propety(ndb_key_prop):
resolved_prop_name = name

return [
ConversionResult(name=string_prop_name, field=DynamicNdbKeyStringField(ndb_key_prop)),
ConversionResult(name=resolved_prop_name, field=DynamicNdbKeyReferenceField(ndb_key_prop))
ConversionResult(name=string_prop_name, field=DynamicNdbKeyStringField(ndb_key_prop, registry=registry)),
ConversionResult(name=resolved_prop_name, field=DynamicNdbKeyReferenceField(ndb_key_prop, registry=registry))
]


def convert_local_structured_property(ndb_structured_property):
def convert_local_structured_property(ndb_structured_property, registry=None):
is_required = ndb_structured_property._required
is_repeated = ndb_structured_property._repeated
model = ndb_structured_property._modelclass
name = ndb_structured_property._code_name

def dynamic_type():
from .types import NdbObjectTypeMeta
_type = NdbObjectTypeMeta.REGISTRY.get(model.__name__)
_type = registry.get_type_for_model(model)
if not _type:
return None

Expand All @@ -123,7 +122,7 @@ def dynamic_type():
return ConversionResult(name=name, field=field)


def convert_computed_property(ndb_computed_prop):
def convert_computed_property(ndb_computed_prop, registry=None):
return convert_ndb_scalar_property(String, ndb_computed_prop)


Expand All @@ -143,12 +142,12 @@ def convert_computed_property(ndb_computed_prop):
}


def convert_ndb_property(prop):
def convert_ndb_property(prop, registry=None):
converter_func = converters.get(type(prop))
if not converter_func:
raise Exception("Don't know how to convert NDB field %s (%s)" % (prop._code_name, prop))

field = converter_func(prop)
field = converter_func(prop, registry)
if not field:
raise Exception("Failed to convert NDB propeerty to a GraphQL field %s (%s)" % (prop._code_name, prop))

Expand Down
57 changes: 38 additions & 19 deletions graphene_gae/ndb/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@

from graphql_relay import to_global_id
from graphql_relay.connection.connectiontypes import Edge
from graphene import relay, Argument, Boolean, Int, String, Field, List, NonNull, Dynamic
from graphene.relay.connection import PageInfo
from graphene import Argument, Boolean, Int, String, Field, List, NonNull, Dynamic
from graphene.relay import Connection
from graphene.relay.connection import PageInfo, ConnectionField


from .registry import get_global_registry


__author__ = 'ekampf'
Expand Down Expand Up @@ -49,7 +53,7 @@ def connection_from_ndb_query(query, args=None, connection_type=None, edge_type=
so pagination will only work if the array is static.
'''
args = args or {}
connection_type = connection_type or relay.Connection
connection_type = connection_type or Connection
edge_type = edge_type or Edge
pageinfo_type = pageinfo_type or PageInfo

Expand Down Expand Up @@ -91,7 +95,7 @@ def connection_from_ndb_query(query, args=None, connection_type=None, edge_type=
)


class NdbConnectionField(relay.ConnectionField):
class NdbConnectionField(ConnectionField):
def __init__(self, type, transform_edges=None, *args, **kwargs):
super(NdbConnectionField, self).__init__(
type,
Expand All @@ -104,13 +108,23 @@ def __init__(self, type, transform_edges=None, *args, **kwargs):

self.transform_edges = transform_edges

@property
def type(self):
from .types import NdbObjectType
_type = super(ConnectionField, self).type
assert issubclass(_type, NdbObjectType), (
"NdbConnectionField only accepts NdbObjectType types"
)
assert _type._meta.connection, "The type {} doesn't have a connection".format(_type.__name__)
return _type._meta.connection

@property
def model(self):
return self.type._meta.node._meta.model

@staticmethod
def connection_resolver(resolver, connection, model, transform_edges, root, args, context, info):
ndb_query = resolver(root, args, context, info)
def connection_resolver(resolver, connection, model, transform_edges, root, info, **args):
ndb_query = resolver(root, info, **args)
if ndb_query is None:
ndb_query = model.query()

Expand All @@ -121,26 +135,29 @@ def connection_resolver(resolver, connection, model, transform_edges, root, args
edge_type=connection.Edge,
pageinfo_type=PageInfo,
transform_edges=transform_edges,
context=context
context=info.context
)

def get_resolver(self, parent_resolver):
return partial(self.connection_resolver, parent_resolver, self.type, self.model, self.transform_edges)
return partial(
self.connection_resolver, parent_resolver, self.type, self.model, self.transform_edges
)


class DynamicNdbKeyStringField(Dynamic):
def __init__(self, ndb_key_prop, *args, **kwargs):
def __init__(self, ndb_key_prop, registry=None, *args, **kwargs):
kind = ndb_key_prop._kind
if not registry:
registry = get_global_registry()

def get_type():
from .types import NdbObjectTypeMeta
kind_name = kind if isinstance(kind, six.string_types) else kind.__name__

if not NdbObjectTypeMeta.REGISTRY.get(kind_name):
_type = registry.get_type_for_model_name(kind_name)
if not _type:
return None

global_type_name = NdbObjectTypeMeta.REGISTRY[kind_name].__name__
return NdbKeyStringField(ndb_key_prop, global_type_name)
return NdbKeyStringField(ndb_key_prop, _type._meta.name)

super(DynamicNdbKeyStringField, self).__init__(
get_type,
Expand All @@ -149,13 +166,15 @@ def get_type():


class DynamicNdbKeyReferenceField(Dynamic):
def __init__(self, ndb_key_prop, *args, **kwargs):
def __init__(self, ndb_key_prop, registry=None, *args, **kwargs):
kind = ndb_key_prop._kind
if not registry:
registry = get_global_registry()

def get_type():
from .types import NdbObjectTypeMeta
kind_name = kind if isinstance(kind, six.string_types) else kind.__name__
_type = NdbObjectTypeMeta.REGISTRY.get(kind_name)

_type = registry.get_type_for_model_name(kind_name)
if not _type:
return None

Expand Down Expand Up @@ -187,8 +206,8 @@ def __init__(self, ndb_key_prop, graphql_type_name, *args, **kwargs):

super(NdbKeyStringField, self).__init__(_type, *args, **kwargs)

def resolve_key_to_string(self, entity, args, context, info):
is_global_id = not args.get('ndb', False)
def resolve_key_to_string(self, entity, info, ndb=False):
is_global_id = not ndb
key_value = self.__ndb_key_prop._get_user_value(entity)
if not key_value:
return None
Expand Down Expand Up @@ -218,7 +237,7 @@ def __init__(self, ndb_key_prop, graphql_type, *args, **kwargs):

super(NdbKeyReferenceField, self).__init__(_type, *args, **kwargs)

def resolve_key_reference(self, entity, args, context, info):
def resolve_key_reference(self, entity, info):
key_value = self.__ndb_key_prop._get_user_value(entity)
if not key_value:
return None
Expand Down
36 changes: 36 additions & 0 deletions graphene_gae/ndb/registry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Registry(object):

def __init__(self):
self._registry = {}

def register(self, cls):
from .types import NdbObjectType
assert issubclass(cls, NdbObjectType), (
'Only classes of type NdbObjectType can be registered, ',
'received "{}"'
).format(cls.__name__)
assert cls._meta.registry == self, 'Registry for a Model have to match.'
self._registry[cls._meta.model] = cls

def get_type_for_model(self, model):
return self._registry.get(model)

def get_type_for_model_name(self, model_name):
for ndb_model, type in self._registry.items():
if ndb_model.__name__ == model_name:
return type


registry = None


def get_global_registry():
global registry
if not registry:
registry = Registry()
return registry


def reset_global_registry():
global registry
registry = None
Loading