diff --git a/graphene/relay/connection.py b/graphene/relay/connection.py index 02b3dbe53..e88d1b822 100644 --- a/graphene/relay/connection.py +++ b/graphene/relay/connection.py @@ -54,6 +54,10 @@ def __new__(cls, name, bases, attrs): ) cls.Edge = type(edge.name, (ObjectType, ), {'Meta': type('Meta', (object,), {'graphql_type': edge})}) cls._meta.graphql_type = connection + fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) + + cls._meta.get_fields = lambda: fields + return cls diff --git a/graphene/relay/mutation.py b/graphene/relay/mutation.py index f5fbec83c..24a828a0e 100644 --- a/graphene/relay/mutation.py +++ b/graphene/relay/mutation.py @@ -52,6 +52,8 @@ def __new__(cls, name, bases, attrs): mutate_and_get_payload=cls.mutate_and_get_payload, ) options.graphql_type = field.type + options.get_fields = lambda: output_fields + cls.Field = partial(Field.copy_and_extend, field, type=field.type, _creation_counter=None) return cls diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 4467746d8..e0d6f3d17 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -10,6 +10,8 @@ from ..types.options import Options from .connection import Connection +from ..utils.copy_fields import copy_fields + # We inherit from ObjectTypeMeta as we want to allow # inheriting from Node, and also ObjectType. @@ -23,16 +25,17 @@ def _get_interface_options(meta): meta, ) - def __new__(cls, name, bases, attrs): - - if is_objecttype(bases): - cls = super(NodeMeta, cls).__new__(cls, name, bases, attrs) - # The interface provided by node_definitions is not an instance - # of GrapheneInterfaceType, so it will have no graphql_type, - # so will not trigger Node.implements - cls.implements(cls) - return cls + @staticmethod + def _create_objecttype(cls, name, bases, attrs): + # The interface provided by node_definitions is not an instance + # of GrapheneInterfaceType, so it will have no graphql_type, + # so will not trigger Node.implements + cls = super(NodeMeta, cls)._create_objecttype(cls, name, bases, attrs) + cls.implements(cls) + return cls + @staticmethod + def _create_interface(cls, name, bases, attrs): options = cls._get_interface_options(attrs.pop('Meta', None)) cls = type.__new__(cls, name, bases, dict(attrs, _meta=options)) @@ -45,6 +48,10 @@ def __new__(cls, name, bases, attrs): type_resolver=cls.resolve_type, ) options.graphql_type = node_interface + + fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) + options.get_fields = lambda: fields + cls.Field = partial( Field.copy_and_extend, node_field, diff --git a/graphene/types/mutation.py b/graphene/types/mutation.py index ee015d76d..6874ae3d8 100644 --- a/graphene/types/mutation.py +++ b/graphene/types/mutation.py @@ -11,16 +11,14 @@ class MutationMeta(ObjectTypeMeta): def __new__(cls, name, bases, attrs): - super_new = super(MutationMeta, cls).__new__ - - # Also ensure initialization is only performed for subclasses of Model - # (excluding Model class itself). + # Also ensure initialization is only performed for subclasses of + # Mutation if not is_base_type(bases, MutationMeta): return type.__new__(cls, name, bases, attrs) Input = attrs.pop('Input', None) - cls = super_new(cls, name, bases, attrs) + cls = cls._create_objecttype(cls, name, bases, attrs) field_args = props(Input) if Input else {} resolver = getattr(cls, 'mutate', None) assert resolver, 'All mutations must define a mutate method in it' diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index 19a06dac9..19f5e2c83 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -56,7 +56,7 @@ def __new__(cls, name, bases, attrs): super_new = type.__new__ # Also ensure initialization is only performed for subclasses of - # ObjectType, Interfaces + # ObjectType,or Interfaces if not is_base_type(bases, ObjectTypeMeta): return type.__new__(cls, name, bases, attrs) @@ -100,7 +100,9 @@ def _create_interface(cls, name, bases, attrs): ) else: assert not fields, "Can't mount Fields in an Interface with a defined graphql_type" - fields = copy_fields(options.graphql_type.get_fields(), parent=cls) + fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) + + options.get_fields = lambda: fields for name, field in fields.items(): setattr(cls, field.attname or name, field) @@ -138,6 +140,8 @@ def _create_objecttype(cls, name, bases, attrs): assert not fields, "Can't mount Fields in an ObjectType with a defined graphql_type" fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) + options.get_fields = lambda: fields + for name, field in fields.items(): setattr(cls, field.attname or name, field) @@ -149,11 +153,7 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta)): def __init__(self, *args, **kwargs): # GraphQL ObjectType acting as container args_len = len(args) - _fields = self._meta.graphql_type._fields - if callable(_fields): - _fields = _fields() - - fields = _fields.items() + fields = self._meta.get_fields().items() for name, f in fields: setattr(self, getattr(f, 'attname', name), None) diff --git a/graphene/utils/get_fields.py b/graphene/utils/get_fields.py index 13ba2daee..4e18de678 100644 --- a/graphene/utils/get_fields.py +++ b/graphene/utils/get_fields.py @@ -21,7 +21,7 @@ def get_fields_from_bases_and_types(bases, types): for _class in bases: if not is_graphene_type(_class): continue - _fields = get_graphql_type(_class)._fields + _fields = _class._meta.get_fields() if callable(_fields): _fields = _fields()