mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-22 09:36:44 +03:00
Make resolvers simple again
This commit is contained in:
parent
800fbdf820
commit
9769612a44
|
@ -32,7 +32,7 @@ Also, Graphene is fully compatible with the GraphQL spec, working seamlessly wit
|
|||
For instaling graphene, just run this command in your shell
|
||||
|
||||
```bash
|
||||
pip install "graphene>=2.0"
|
||||
pip install "graphene>=2.0.dev"
|
||||
```
|
||||
|
||||
## 2.0 Upgrade Guide
|
||||
|
@ -48,7 +48,7 @@ Here is one example for you to get started:
|
|||
class Query(graphene.ObjectType):
|
||||
hello = graphene.String(description='A typical hello world')
|
||||
|
||||
def resolve_hello(self, args, context, info):
|
||||
def resolve_hello(self):
|
||||
return 'World'
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
|
|
|
@ -65,7 +65,7 @@ Here is one example for you to get started:
|
|||
class Query(graphene.ObjectType):
|
||||
hello = graphene.String(description='A typical hello world')
|
||||
|
||||
def resolve_hello(self, args, context, info):
|
||||
def resolve_hello(self):
|
||||
return 'World'
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
|
|
|
@ -49,7 +49,7 @@ class Pet(CommonFields, Interface):
|
|||
|
||||
### resolve\_only\_args
|
||||
|
||||
`resolve_only_args` is now deprecated in favor of type annotations (using the polyfill `@graphene.annotate` in Python 2).
|
||||
`resolve_only_args` is now deprecated in favor of type annotations (using the polyfill `@graphene.annotate` in Python 2 in case is necessary for accessing `context` or `info`).
|
||||
|
||||
Before:
|
||||
|
||||
|
@ -68,8 +68,7 @@ With 2.0:
|
|||
class User(ObjectType):
|
||||
name = String()
|
||||
|
||||
# Decorate the resolver with @annotate in Python 2
|
||||
def resolve_name(self) -> str:
|
||||
def resolve_name(self):
|
||||
return self.name
|
||||
```
|
||||
|
||||
|
@ -129,7 +128,7 @@ def is_user_id(id):
|
|||
return id.startswith('userid_')
|
||||
|
||||
class Query(ObjectType):
|
||||
user = graphene.Field(User, id=UserInput())
|
||||
user = graphene.Field(User, input=UserInput())
|
||||
|
||||
@resolve_only_args
|
||||
def resolve_user(self, input):
|
||||
|
@ -149,10 +148,9 @@ class UserInput(InputObjectType):
|
|||
return self.id.startswith('userid_')
|
||||
|
||||
class Query(ObjectType):
|
||||
user = graphene.Field(User, id=UserInput())
|
||||
user = graphene.Field(User, input=UserInput())
|
||||
|
||||
# Decorate the resolver with @annotate(input=UserInput) in Python 2
|
||||
def resolve_user(self, input: UserInput) -> User:
|
||||
def resolve_user(self, input):
|
||||
if input.is_user_id:
|
||||
return get_user(input.id)
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ class User(graphene.ObjectType):
|
|||
class Query(graphene.ObjectType):
|
||||
me = graphene.Field(User)
|
||||
|
||||
def resolve_me(self, args, context, info):
|
||||
@graphene.annotate(context=graphene.Context)
|
||||
def resolve_me(self, context):
|
||||
return context['user']
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ class Query(graphene.ObjectType):
|
|||
|
||||
patron = graphene.Field(Patron)
|
||||
|
||||
def resolve_patron(self, args, context, info):
|
||||
def resolve_patron(self):
|
||||
return Patron(id=1, name='Syrus', age=27)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import graphene
|
||||
from graphene import annotate
|
||||
|
||||
from .data import get_character, get_droid, get_hero, get_human
|
||||
|
||||
|
@ -16,7 +15,7 @@ class Character(graphene.Interface):
|
|||
friends = graphene.List(lambda: Character)
|
||||
appears_in = graphene.List(Episode)
|
||||
|
||||
def resolve_friends(self, args, *_):
|
||||
def resolve_friends(self):
|
||||
# The character friends is a list of strings
|
||||
return [get_character(f) for f in self.friends]
|
||||
|
||||
|
@ -46,15 +45,12 @@ class Query(graphene.ObjectType):
|
|||
id=graphene.String()
|
||||
)
|
||||
|
||||
@annotate(episode=Episode)
|
||||
def resolve_hero(self, episode=None):
|
||||
return get_hero(episode)
|
||||
|
||||
@annotate(id=str)
|
||||
def resolve_human(self, id):
|
||||
return get_human(id)
|
||||
|
||||
@annotate(id=str)
|
||||
def resolve_droid(self, id):
|
||||
return get_droid(id)
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ class Faction(graphene.ObjectType):
|
|||
name = graphene.String(description='The name of the faction.')
|
||||
ships = relay.ConnectionField(ShipConnection, description='The ships used by the faction.')
|
||||
|
||||
@annotate
|
||||
def resolve_ships(self, **args):
|
||||
# Transform the instance ship_ids into real instances
|
||||
return [get_ship(ship_id) for ship_id in self.ships]
|
||||
|
@ -65,11 +64,9 @@ class Query(graphene.ObjectType):
|
|||
empire = graphene.Field(Faction)
|
||||
node = relay.Node.Field()
|
||||
|
||||
@annotate
|
||||
def resolve_rebels(self):
|
||||
return get_rebels()
|
||||
|
||||
@annotate
|
||||
def resolve_empire(self):
|
||||
return get_empire()
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ from collections import OrderedDict
|
|||
|
||||
from promise import Promise, is_thenable
|
||||
|
||||
from ..types import Field, InputObjectType, String
|
||||
from ..types import Field, InputObjectType, String, Context, ResolveInfo
|
||||
from ..types.mutation import Mutation
|
||||
from ..utils.annotate import annotate
|
||||
|
||||
|
||||
class ClientIDMutation(Mutation):
|
||||
|
@ -49,9 +50,8 @@ class ClientIDMutation(Mutation):
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def mutate(cls, root, args, context, info):
|
||||
input = args.get('input')
|
||||
|
||||
@annotate(context=Context, info=ResolveInfo)
|
||||
def mutate(cls, root, input, context, info):
|
||||
def on_resolve(payload):
|
||||
try:
|
||||
payload.client_mutation_id = input.get('clientMutationId')
|
||||
|
|
|
@ -31,13 +31,13 @@ class Query(ObjectType):
|
|||
|
||||
node = Node.Field()
|
||||
|
||||
def resolve_letters(self, args, context, info):
|
||||
def resolve_letters(self, **args):
|
||||
return list(letters.values())
|
||||
|
||||
def resolve_promise_letters(self, args, context, info):
|
||||
def resolve_promise_letters(self, **args):
|
||||
return Promise.resolve(list(letters.values()))
|
||||
|
||||
def resolve_connection_letters(self, args, context, info):
|
||||
def resolve_connection_letters(self, **args):
|
||||
return LetterConnection(
|
||||
page_info=PageInfo(
|
||||
has_next_page=True,
|
||||
|
|
|
@ -29,7 +29,6 @@ class CreatePost(graphene.Mutation):
|
|||
|
||||
result = graphene.Field(CreatePostResult)
|
||||
|
||||
@resolve_only_args
|
||||
def mutate(self, text):
|
||||
result = Success(yeah='yeah')
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ import graphene
|
|||
class Query(graphene.ObjectType):
|
||||
some_field = graphene.String(from_=graphene.String(name="from"))
|
||||
|
||||
def resolve_some_field(_, args, context, infos):
|
||||
return args.get("from_")
|
||||
def resolve_some_field(self, from_=None):
|
||||
return from_
|
||||
|
||||
|
||||
def test_issue():
|
||||
|
|
|
@ -7,7 +7,6 @@ from .mountedtype import MountedType
|
|||
from .structures import NonNull
|
||||
from .unmountedtype import UnmountedType
|
||||
from .utils import get_type
|
||||
from ..utils.auto_resolver import auto_resolver
|
||||
|
||||
base_type = type
|
||||
|
||||
|
@ -64,4 +63,4 @@ class Field(MountedType):
|
|||
return get_type(self._type)
|
||||
|
||||
def get_resolver(self, parent_resolver):
|
||||
return auto_resolver(self.resolver or parent_resolver)
|
||||
return self.resolver or parent_resolver
|
||||
|
|
|
@ -5,6 +5,7 @@ from ..utils.props import props
|
|||
from .field import Field
|
||||
from .objecttype import ObjectType, ObjectTypeOptions
|
||||
from .utils import yank_fields_from_attrs
|
||||
from ..utils.auto_resolver import auto_resolver
|
||||
|
||||
|
||||
class MutationOptions(ObjectTypeOptions):
|
||||
|
@ -59,7 +60,7 @@ class Mutation(ObjectType):
|
|||
_meta.fields = fields
|
||||
|
||||
_meta.output = output
|
||||
_meta.resolver = resolver
|
||||
_meta.resolver = auto_resolver(resolver)
|
||||
_meta.arguments = arguments
|
||||
|
||||
super(Mutation, cls).__init_subclass_with_meta__(_meta=_meta, **options)
|
||||
|
|
|
@ -11,12 +11,11 @@ class Query(ObjectType):
|
|||
datetime = DateTime(_in=DateTime(name='in'))
|
||||
time = Time(_at=Time(name='at'))
|
||||
|
||||
def resolve_datetime(self, args, context, info):
|
||||
_in = args.get('_in')
|
||||
def resolve_datetime(self, _in=None):
|
||||
return _in
|
||||
|
||||
def resolve_time(self, args, context, info):
|
||||
return args.get('_at')
|
||||
def resolve_time(self, _at=None):
|
||||
return _at
|
||||
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
|
|
@ -6,8 +6,7 @@ from ..schema import Schema
|
|||
class Query(ObjectType):
|
||||
generic = GenericScalar(input=GenericScalar())
|
||||
|
||||
def resolve_generic(self, args, context, info):
|
||||
input = args.get('input')
|
||||
def resolve_generic(self, input=None):
|
||||
return input
|
||||
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ from ..schema import Schema
|
|||
class Query(ObjectType):
|
||||
json = JSONString(input=JSONString())
|
||||
|
||||
def resolve_json(self, args, context, info):
|
||||
input = args.get('input')
|
||||
def resolve_json(self, input):
|
||||
return input
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
|
|
@ -12,14 +12,14 @@ def test_generate_mutation_no_args():
|
|||
class MyMutation(Mutation):
|
||||
'''Documentation'''
|
||||
|
||||
@classmethod
|
||||
def mutate(cls, *args, **kwargs):
|
||||
pass
|
||||
def mutate(self, **args):
|
||||
return args
|
||||
|
||||
assert issubclass(MyMutation, ObjectType)
|
||||
assert MyMutation._meta.name == "MyMutation"
|
||||
assert MyMutation._meta.description == "Documentation"
|
||||
assert MyMutation.Field().resolver == MyMutation.mutate
|
||||
resolved = MyMutation.Field().resolver(None, {'name': 'Peter'}, None, None)
|
||||
assert resolved == {'name': 'Peter'}
|
||||
|
||||
|
||||
def test_generate_mutation_with_meta():
|
||||
|
@ -29,13 +29,13 @@ def test_generate_mutation_with_meta():
|
|||
name = 'MyOtherMutation'
|
||||
description = 'Documentation'
|
||||
|
||||
@classmethod
|
||||
def mutate(cls, *args, **kwargs):
|
||||
pass
|
||||
def mutate(self, **args):
|
||||
return args
|
||||
|
||||
assert MyMutation._meta.name == "MyOtherMutation"
|
||||
assert MyMutation._meta.description == "Documentation"
|
||||
assert MyMutation.Field().resolver == MyMutation.mutate
|
||||
resolved = MyMutation.Field().resolver(None, {'name': 'Peter'}, None, None)
|
||||
assert resolved == {'name': 'Peter'}
|
||||
|
||||
|
||||
def test_mutation_raises_exception_if_no_mutate():
|
||||
|
@ -59,15 +59,15 @@ def test_mutation_custom_output_type():
|
|||
|
||||
Output = User
|
||||
|
||||
@classmethod
|
||||
def mutate(cls, args, context, info):
|
||||
name = args.get('name')
|
||||
def mutate(self, name):
|
||||
return User(name=name)
|
||||
|
||||
field = CreateUser.Field()
|
||||
assert field.type == User
|
||||
assert field.args == {'name': Argument(String)}
|
||||
assert field.resolver == CreateUser.mutate
|
||||
resolved = field.resolver(None, {'name': 'Peter'}, None, None)
|
||||
assert isinstance(resolved, User)
|
||||
assert resolved.name == 'Peter'
|
||||
|
||||
|
||||
def test_mutation_execution():
|
||||
|
@ -81,9 +81,7 @@ def test_mutation_execution():
|
|||
name = String()
|
||||
dynamic = Dynamic(lambda: String())
|
||||
|
||||
def mutate(self, args, context, info):
|
||||
name = args.get('name')
|
||||
dynamic = args.get('dynamic')
|
||||
def mutate(self, name, dynamic):
|
||||
return CreateUser(name=name, dynamic=dynamic)
|
||||
|
||||
class Query(ObjectType):
|
||||
|
|
|
@ -57,7 +57,7 @@ def test_query_union():
|
|||
class Query(ObjectType):
|
||||
unions = List(MyUnion)
|
||||
|
||||
def resolve_unions(self, args, context, info):
|
||||
def resolve_unions(self):
|
||||
return [one_object(), two_object()]
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -108,7 +108,7 @@ def test_query_interface():
|
|||
class Query(ObjectType):
|
||||
interfaces = List(MyInterface)
|
||||
|
||||
def resolve_interfaces(self, args, context, info):
|
||||
def resolve_interfaces(self):
|
||||
return [one_object(), two_object()]
|
||||
|
||||
hello_schema = Schema(Query, types=[One, Two])
|
||||
|
@ -188,7 +188,7 @@ def test_query_resolve_function():
|
|||
class Query(ObjectType):
|
||||
hello = String()
|
||||
|
||||
def resolve_hello(self, args, context, info):
|
||||
def resolve_hello(self):
|
||||
return 'World'
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -202,7 +202,7 @@ def test_query_arguments():
|
|||
class Query(ObjectType):
|
||||
test = String(a_str=String(), a_int=Int())
|
||||
|
||||
def resolve_test(self, args, context, info):
|
||||
def resolve_test(self, **args):
|
||||
return json.dumps([self, args], separators=(',', ':'))
|
||||
|
||||
test_schema = Schema(Query)
|
||||
|
@ -231,7 +231,7 @@ def test_query_input_field():
|
|||
class Query(ObjectType):
|
||||
test = String(a_input=Input())
|
||||
|
||||
def resolve_test(self, args, context, info):
|
||||
def resolve_test(self, **args):
|
||||
return json.dumps([self, args], separators=(',', ':'))
|
||||
|
||||
test_schema = Schema(Query)
|
||||
|
@ -254,10 +254,10 @@ def test_query_middlewares():
|
|||
hello = String()
|
||||
other = String()
|
||||
|
||||
def resolve_hello(self, args, context, info):
|
||||
def resolve_hello(self):
|
||||
return 'World'
|
||||
|
||||
def resolve_other(self, args, context, info):
|
||||
def resolve_other(self):
|
||||
return 'other'
|
||||
|
||||
def reversed_middleware(next, *args, **kwargs):
|
||||
|
@ -280,14 +280,14 @@ def test_objecttype_on_instances():
|
|||
class ShipType(ObjectType):
|
||||
name = String(description="Ship name", required=True)
|
||||
|
||||
def resolve_name(self, context, args, info):
|
||||
def resolve_name(self):
|
||||
# Here self will be the Ship instance returned in resolve_ship
|
||||
return self.name
|
||||
|
||||
class Query(ObjectType):
|
||||
ship = Field(ShipType)
|
||||
|
||||
def resolve_ship(self, context, args, info):
|
||||
def resolve_ship(self):
|
||||
return Ship(name='xwing')
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
@ -302,7 +302,7 @@ def test_big_list_query_benchmark(benchmark):
|
|||
class Query(ObjectType):
|
||||
all_ints = List(Int)
|
||||
|
||||
def resolve_all_ints(self, args, context, info):
|
||||
def resolve_all_ints(self):
|
||||
return big_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -319,7 +319,7 @@ def test_big_list_query_compiled_query_benchmark(benchmark):
|
|||
class Query(ObjectType):
|
||||
all_ints = List(Int)
|
||||
|
||||
def resolve_all_ints(self, args, context, info):
|
||||
def resolve_all_ints(self):
|
||||
return big_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -341,7 +341,7 @@ def test_big_list_of_containers_query_benchmark(benchmark):
|
|||
class Query(ObjectType):
|
||||
all_containers = List(Container)
|
||||
|
||||
def resolve_all_containers(self, args, context, info):
|
||||
def resolve_all_containers(self):
|
||||
return big_container_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -364,7 +364,7 @@ def test_big_list_of_containers_multiple_fields_query_benchmark(benchmark):
|
|||
class Query(ObjectType):
|
||||
all_containers = List(Container)
|
||||
|
||||
def resolve_all_containers(self, args, context, info):
|
||||
def resolve_all_containers(self):
|
||||
return big_container_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -382,16 +382,16 @@ def test_big_list_of_containers_multiple_fields_custom_resolvers_query_benchmark
|
|||
z = Int()
|
||||
o = Int()
|
||||
|
||||
def resolve_x(self, args, context, info):
|
||||
def resolve_x(self):
|
||||
return self.x
|
||||
|
||||
def resolve_y(self, args, context, info):
|
||||
def resolve_y(self):
|
||||
return self.y
|
||||
|
||||
def resolve_z(self, args, context, info):
|
||||
def resolve_z(self):
|
||||
return self.z
|
||||
|
||||
def resolve_o(self, args, context, info):
|
||||
def resolve_o(self):
|
||||
return self.o
|
||||
|
||||
big_container_list = [Container(x=x, y=x, z=x, o=x) for x in range(1000)]
|
||||
|
@ -399,7 +399,7 @@ def test_big_list_of_containers_multiple_fields_custom_resolvers_query_benchmark
|
|||
class Query(ObjectType):
|
||||
all_containers = List(Container)
|
||||
|
||||
def resolve_all_containers(self, args, context, info):
|
||||
def resolve_all_containers(self):
|
||||
return big_container_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
@ -420,7 +420,6 @@ def test_query_annotated_resolvers():
|
|||
context = String()
|
||||
info = String()
|
||||
|
||||
@annotate(_trigger_warning=False)
|
||||
def resolve_annotated(self, id):
|
||||
return "{}-{}".format(self, id)
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ def test_objecttype():
|
|||
foo = String(bar=String(description='Argument description', default_value='x'), description='Field description')
|
||||
bar = String(name='gizmo')
|
||||
|
||||
def resolve_foo(self, args, info):
|
||||
return args.get('bar')
|
||||
def resolve_foo(self, bar):
|
||||
return bar
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
assert 'MyObjectType' in typemap
|
||||
|
@ -65,7 +65,7 @@ def test_objecttype():
|
|||
assert isinstance(foo_field, GraphQLField)
|
||||
assert foo_field.description == 'Field description'
|
||||
f = MyObjectType.resolve_foo
|
||||
assert foo_field.resolver == getattr(f, '__func__', f)
|
||||
# assert foo_field.resolver == getattr(f, '__func__', f)
|
||||
assert foo_field.args == {
|
||||
'bar': GraphQLArgument(GraphQLString, description='Argument description', default_value='x', out_name='bar')
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ from graphql.type.typemap import GraphQLTypeMap
|
|||
|
||||
from ..utils.get_unbound_function import get_unbound_function
|
||||
from ..utils.str_converters import to_camel_case
|
||||
from ..utils.auto_resolver import auto_resolver, final_resolver
|
||||
from .definitions import (GrapheneEnumType, GrapheneGraphQLType,
|
||||
GrapheneInputObjectType, GrapheneInterfaceType,
|
||||
GrapheneObjectType, GrapheneScalarType,
|
||||
|
@ -256,8 +257,14 @@ class TypeMap(GraphQLTypeMap):
|
|||
field_type,
|
||||
args=args,
|
||||
resolver=field.get_resolver(
|
||||
self.get_resolver_for_type(type, name,
|
||||
field.default_value)),
|
||||
auto_resolver(
|
||||
self.get_resolver_for_type(
|
||||
type,
|
||||
name,
|
||||
field.default_value
|
||||
)
|
||||
)
|
||||
),
|
||||
deprecation_reason=field.deprecation_reason,
|
||||
description=field.description)
|
||||
field_name = field.name or self.get_name(name)
|
||||
|
@ -287,7 +294,7 @@ class TypeMap(GraphQLTypeMap):
|
|||
|
||||
default_resolver = type._meta.default_resolver or get_default_resolver(
|
||||
)
|
||||
return partial(default_resolver, name, default_value)
|
||||
return final_resolver(partial(default_resolver, name, default_value))
|
||||
|
||||
def get_field_type(self, map, type):
|
||||
if isinstance(type, List):
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
from .resolver_from_annotations import resolver_from_annotations, is_wrapped_from_annotations
|
||||
from .resolver_from_annotations import resolver_from_annotations
|
||||
|
||||
|
||||
def final_resolver(func):
|
||||
func._is_final_resolver = True
|
||||
return func
|
||||
|
||||
|
||||
def auto_resolver(func=None):
|
||||
annotations = getattr(func, '__annotations__', {})
|
||||
is_annotated = getattr(func, '_is_annotated', False)
|
||||
if not func:
|
||||
return
|
||||
|
||||
if (annotations or is_annotated) and not is_wrapped_from_annotations(func):
|
||||
if not is_final_resolver(func):
|
||||
# Is a Graphene 2.0 resolver function
|
||||
return resolver_from_annotations(func)
|
||||
return final_resolver(resolver_from_annotations(func))
|
||||
else:
|
||||
return func
|
||||
|
||||
|
||||
def is_final_resolver(func):
|
||||
return getattr(func, '_is_final_resolver', False)
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
from ..pyutils.compat import signature
|
||||
from functools import wraps
|
||||
from functools import wraps, partial
|
||||
|
||||
|
||||
def resolver_from_annotations(func):
|
||||
from ..types import Context, ResolveInfo
|
||||
|
||||
_is_wrapped_from_annotations = is_wrapped_from_annotations(func)
|
||||
assert not _is_wrapped_from_annotations, "The function {func_name} is already wrapped.".format(
|
||||
func_name=func.func_name
|
||||
)
|
||||
|
||||
func_signature = signature(func)
|
||||
|
||||
_context_var = None
|
||||
|
@ -38,9 +33,7 @@ def resolver_from_annotations(func):
|
|||
def inner(root, args, context, info):
|
||||
return func(root, **args)
|
||||
|
||||
inner._is_wrapped_from_annotations = True
|
||||
if isinstance(func, partial):
|
||||
return inner
|
||||
|
||||
return wraps(func)(inner)
|
||||
|
||||
|
||||
def is_wrapped_from_annotations(func):
|
||||
return getattr(func, '_is_wrapped_from_annotations', False)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import pytest
|
||||
from ..annotate import annotate
|
||||
from ..auto_resolver import auto_resolver
|
||||
from ..auto_resolver import auto_resolver, final_resolver
|
||||
|
||||
from ...types import Context, ResolveInfo
|
||||
|
||||
|
||||
@final_resolver
|
||||
def resolver(root, args, context, info):
|
||||
return root, args, context, info
|
||||
|
||||
|
||||
@annotate
|
||||
def resolver_annotated(root, **args):
|
||||
return root, args, None, None
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user