mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-08 23:50:38 +03:00
Improved lazy types support in Graphene
This commit also adds support for string types in Field, InputField, List and NonNull, where the string will be import. Usage like: Field("graphene.String")
This commit is contained in:
parent
bd0d418986
commit
4b71465922
|
@ -6,6 +6,7 @@ from .argument import Argument, to_arguments
|
||||||
from .mountedtype import MountedType
|
from .mountedtype import MountedType
|
||||||
from .structures import NonNull
|
from .structures import NonNull
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
from .utils import get_type
|
||||||
|
|
||||||
|
|
||||||
base_type = type
|
base_type = type
|
||||||
|
@ -60,9 +61,7 @@ class Field(MountedType):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
if inspect.isfunction(self._type) or type(self._type) is partial:
|
return get_type(self._type)
|
||||||
return self._type()
|
|
||||||
return self._type
|
|
||||||
|
|
||||||
def get_resolver(self, parent_resolver):
|
def get_resolver(self, parent_resolver):
|
||||||
return self.resolver or parent_resolver
|
return self.resolver or parent_resolver
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from .mountedtype import MountedType
|
from .mountedtype import MountedType
|
||||||
from .structures import NonNull
|
from .structures import NonNull
|
||||||
|
from .utils import get_type
|
||||||
|
|
||||||
|
|
||||||
class InputField(MountedType):
|
class InputField(MountedType):
|
||||||
|
@ -11,7 +12,11 @@ class InputField(MountedType):
|
||||||
self.name = name
|
self.name = name
|
||||||
if required:
|
if required:
|
||||||
type = NonNull(type)
|
type = NonNull(type)
|
||||||
self.type = type
|
self._type = type
|
||||||
self.deprecation_reason = deprecation_reason
|
self.deprecation_reason = deprecation_reason
|
||||||
self.default_value = default_value
|
self.default_value = default_value
|
||||||
self.description = description
|
self.description = description
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return get_type(self._type)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
from .utils import get_type
|
||||||
|
|
||||||
|
|
||||||
class Structure(UnmountedType):
|
class Structure(UnmountedType):
|
||||||
|
@ -18,7 +19,11 @@ class Structure(UnmountedType):
|
||||||
cls_name,
|
cls_name,
|
||||||
of_type_name,
|
of_type_name,
|
||||||
))
|
))
|
||||||
self.of_type = of_type
|
self._of_type = of_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def of_type(self):
|
||||||
|
return get_type(self._of_type)
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from ..argument import Argument
|
from ..argument import Argument
|
||||||
from ..field import Field
|
from ..field import Field
|
||||||
from ..structures import NonNull
|
from ..structures import NonNull
|
||||||
from ..scalars import String
|
from ..scalars import String
|
||||||
|
from .utils import MyLazyType
|
||||||
|
|
||||||
|
|
||||||
class MyInstance(object):
|
class MyInstance(object):
|
||||||
|
@ -66,6 +68,17 @@ def test_field_with_lazy_type():
|
||||||
assert field.type == MyType
|
assert field.type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_field_with_lazy_partial_type():
|
||||||
|
MyType = object()
|
||||||
|
field = Field(partial(lambda: MyType))
|
||||||
|
assert field.type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_field_with_string_type():
|
||||||
|
field = Field("graphene.types.tests.utils.MyLazyType")
|
||||||
|
assert field.type == MyLazyType
|
||||||
|
|
||||||
|
|
||||||
def test_field_not_source_and_resolver():
|
def test_field_not_source_and_resolver():
|
||||||
MyType = object()
|
MyType = object()
|
||||||
with pytest.raises(Exception) as exc_info:
|
with pytest.raises(Exception) as exc_info:
|
||||||
|
|
30
graphene/types/tests/test_inputfield.py
Normal file
30
graphene/types/tests/test_inputfield.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import pytest
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from ..inputfield import InputField
|
||||||
|
from ..structures import NonNull
|
||||||
|
from .utils import MyLazyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_inputfield_required():
|
||||||
|
MyType = object()
|
||||||
|
field = InputField(MyType, required=True)
|
||||||
|
assert isinstance(field.type, NonNull)
|
||||||
|
assert field.type.of_type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_inputfield_with_lazy_type():
|
||||||
|
MyType = object()
|
||||||
|
field = InputField(lambda: MyType)
|
||||||
|
assert field.type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_inputfield_with_lazy_partial_type():
|
||||||
|
MyType = object()
|
||||||
|
field = InputField(partial(lambda: MyType))
|
||||||
|
assert field.type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_inputfield_with_string_type():
|
||||||
|
field = InputField("graphene.types.tests.utils.MyLazyType")
|
||||||
|
assert field.type == MyLazyType
|
|
@ -1,7 +1,9 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from ..structures import List, NonNull
|
from ..structures import List, NonNull
|
||||||
from ..scalars import String
|
from ..scalars import String
|
||||||
|
from .utils import MyLazyType
|
||||||
|
|
||||||
|
|
||||||
def test_list():
|
def test_list():
|
||||||
|
@ -17,6 +19,23 @@ def test_list_with_unmounted_type():
|
||||||
assert str(exc_info.value) == 'List could not have a mounted String() as inner type. Try with List(String).'
|
assert str(exc_info.value) == 'List could not have a mounted String() as inner type. Try with List(String).'
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_with_lazy_type():
|
||||||
|
MyType = object()
|
||||||
|
field = List(lambda: MyType)
|
||||||
|
assert field.of_type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_with_lazy_partial_type():
|
||||||
|
MyType = object()
|
||||||
|
field = List(partial(lambda: MyType))
|
||||||
|
assert field.of_type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_with_string_type():
|
||||||
|
field = List("graphene.types.tests.utils.MyLazyType")
|
||||||
|
assert field.of_type == MyLazyType
|
||||||
|
|
||||||
|
|
||||||
def test_list_inherited_works_list():
|
def test_list_inherited_works_list():
|
||||||
_list = List(List(String))
|
_list = List(List(String))
|
||||||
assert isinstance(_list.of_type, List)
|
assert isinstance(_list.of_type, List)
|
||||||
|
@ -35,6 +54,23 @@ def test_nonnull():
|
||||||
assert str(nonnull) == 'String!'
|
assert str(nonnull) == 'String!'
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonnull_with_lazy_type():
|
||||||
|
MyType = object()
|
||||||
|
field = NonNull(lambda: MyType)
|
||||||
|
assert field.of_type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonnull_with_lazy_partial_type():
|
||||||
|
MyType = object()
|
||||||
|
field = NonNull(partial(lambda: MyType))
|
||||||
|
assert field.of_type == MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonnull_with_string_type():
|
||||||
|
field = NonNull("graphene.types.tests.utils.MyLazyType")
|
||||||
|
assert field.of_type == MyLazyType
|
||||||
|
|
||||||
|
|
||||||
def test_nonnull_inherited_works_list():
|
def test_nonnull_inherited_works_list():
|
||||||
_list = NonNull(List(String))
|
_list = NonNull(List(String))
|
||||||
assert isinstance(_list.of_type, List)
|
assert isinstance(_list.of_type, List)
|
||||||
|
|
1
graphene/types/tests/utils.py
Normal file
1
graphene/types/tests/utils.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
MyLazyType = object()
|
|
@ -283,6 +283,4 @@ class TypeMap(GraphQLTypeMap):
|
||||||
return GraphQLList(self.get_field_type(map, type.of_type))
|
return GraphQLList(self.get_field_type(map, type.of_type))
|
||||||
if isinstance(type, NonNull):
|
if isinstance(type, NonNull):
|
||||||
return GraphQLNonNull(self.get_field_type(map, type.of_type))
|
return GraphQLNonNull(self.get_field_type(map, type.of_type))
|
||||||
if inspect.isfunction(type):
|
|
||||||
type = type()
|
|
||||||
return map.get(type._meta.name)
|
return map.get(type._meta.name)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
import inspect
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from functools import partial
|
||||||
|
from six import string_types
|
||||||
|
|
||||||
|
from ..utils.module_loading import import_string
|
||||||
from .mountedtype import MountedType
|
from .mountedtype import MountedType
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
|
||||||
|
@ -62,3 +66,11 @@ def yank_fields_from_attrs(attrs, _as=None, delete=True, sort=True):
|
||||||
if sort:
|
if sort:
|
||||||
fields_with_names = sorted(fields_with_names, key=lambda f: f[1])
|
fields_with_names = sorted(fields_with_names, key=lambda f: f[1])
|
||||||
return OrderedDict(fields_with_names)
|
return OrderedDict(fields_with_names)
|
||||||
|
|
||||||
|
|
||||||
|
def get_type(_type):
|
||||||
|
if isinstance(_type, string_types):
|
||||||
|
return import_string(_type)
|
||||||
|
if inspect.isfunction(_type) or type(_type) is partial:
|
||||||
|
return _type()
|
||||||
|
return _type
|
||||||
|
|
Loading…
Reference in New Issue
Block a user