Skip to content

Commit 4b71465

Browse files
committed
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")
1 parent bd0d418 commit 4b71465

File tree

9 files changed

+106
-7
lines changed

9 files changed

+106
-7
lines changed

graphene/types/field.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from .mountedtype import MountedType
77
from .structures import NonNull
88
from .unmountedtype import UnmountedType
9+
from .utils import get_type
910

1011

1112
base_type = type
@@ -60,9 +61,7 @@ def __init__(self, type, args=None, resolver=None, source=None,
6061

6162
@property
6263
def type(self):
63-
if inspect.isfunction(self._type) or type(self._type) is partial:
64-
return self._type()
65-
return self._type
64+
return get_type(self._type)
6665

6766
def get_resolver(self, parent_resolver):
6867
return self.resolver or parent_resolver

graphene/types/inputfield.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .mountedtype import MountedType
22
from .structures import NonNull
3+
from .utils import get_type
34

45

56
class InputField(MountedType):
@@ -11,7 +12,11 @@ def __init__(self, type, name=None, default_value=None,
1112
self.name = name
1213
if required:
1314
type = NonNull(type)
14-
self.type = type
15+
self._type = type
1516
self.deprecation_reason = deprecation_reason
1617
self.default_value = default_value
1718
self.description = description
19+
20+
@property
21+
def type(self):
22+
return get_type(self._type)

graphene/types/structures.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .unmountedtype import UnmountedType
2+
from .utils import get_type
23

34

45
class Structure(UnmountedType):
@@ -18,7 +19,11 @@ def __init__(self, of_type, *args, **kwargs):
1819
cls_name,
1920
of_type_name,
2021
))
21-
self.of_type = of_type
22+
self._of_type = of_type
23+
24+
@property
25+
def of_type(self):
26+
return get_type(self._of_type)
2227

2328
def get_type(self):
2429
'''

graphene/types/tests/test_field.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import pytest
2+
from functools import partial
23

34
from ..argument import Argument
45
from ..field import Field
56
from ..structures import NonNull
67
from ..scalars import String
8+
from .utils import MyLazyType
79

810

911
class MyInstance(object):
@@ -66,6 +68,17 @@ def test_field_with_lazy_type():
6668
assert field.type == MyType
6769

6870

71+
def test_field_with_lazy_partial_type():
72+
MyType = object()
73+
field = Field(partial(lambda: MyType))
74+
assert field.type == MyType
75+
76+
77+
def test_field_with_string_type():
78+
field = Field("graphene.types.tests.utils.MyLazyType")
79+
assert field.type == MyLazyType
80+
81+
6982
def test_field_not_source_and_resolver():
7083
MyType = object()
7184
with pytest.raises(Exception) as exc_info:
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pytest
2+
from functools import partial
3+
4+
from ..inputfield import InputField
5+
from ..structures import NonNull
6+
from .utils import MyLazyType
7+
8+
9+
def test_inputfield_required():
10+
MyType = object()
11+
field = InputField(MyType, required=True)
12+
assert isinstance(field.type, NonNull)
13+
assert field.type.of_type == MyType
14+
15+
16+
def test_inputfield_with_lazy_type():
17+
MyType = object()
18+
field = InputField(lambda: MyType)
19+
assert field.type == MyType
20+
21+
22+
def test_inputfield_with_lazy_partial_type():
23+
MyType = object()
24+
field = InputField(partial(lambda: MyType))
25+
assert field.type == MyType
26+
27+
28+
def test_inputfield_with_string_type():
29+
field = InputField("graphene.types.tests.utils.MyLazyType")
30+
assert field.type == MyLazyType

graphene/types/tests/test_structures.py

+36
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import pytest
2+
from functools import partial
23

34
from ..structures import List, NonNull
45
from ..scalars import String
6+
from .utils import MyLazyType
57

68

79
def test_list():
@@ -17,6 +19,23 @@ def test_list_with_unmounted_type():
1719
assert str(exc_info.value) == 'List could not have a mounted String() as inner type. Try with List(String).'
1820

1921

22+
def test_list_with_lazy_type():
23+
MyType = object()
24+
field = List(lambda: MyType)
25+
assert field.of_type == MyType
26+
27+
28+
def test_list_with_lazy_partial_type():
29+
MyType = object()
30+
field = List(partial(lambda: MyType))
31+
assert field.of_type == MyType
32+
33+
34+
def test_list_with_string_type():
35+
field = List("graphene.types.tests.utils.MyLazyType")
36+
assert field.of_type == MyLazyType
37+
38+
2039
def test_list_inherited_works_list():
2140
_list = List(List(String))
2241
assert isinstance(_list.of_type, List)
@@ -35,6 +54,23 @@ def test_nonnull():
3554
assert str(nonnull) == 'String!'
3655

3756

57+
def test_nonnull_with_lazy_type():
58+
MyType = object()
59+
field = NonNull(lambda: MyType)
60+
assert field.of_type == MyType
61+
62+
63+
def test_nonnull_with_lazy_partial_type():
64+
MyType = object()
65+
field = NonNull(partial(lambda: MyType))
66+
assert field.of_type == MyType
67+
68+
69+
def test_nonnull_with_string_type():
70+
field = NonNull("graphene.types.tests.utils.MyLazyType")
71+
assert field.of_type == MyLazyType
72+
73+
3874
def test_nonnull_inherited_works_list():
3975
_list = NonNull(List(String))
4076
assert isinstance(_list.of_type, List)

graphene/types/tests/utils.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MyLazyType = object()

graphene/types/typemap.py

-2
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,4 @@ def get_field_type(self, map, type):
283283
return GraphQLList(self.get_field_type(map, type.of_type))
284284
if isinstance(type, NonNull):
285285
return GraphQLNonNull(self.get_field_type(map, type.of_type))
286-
if inspect.isfunction(type):
287-
type = type()
288286
return map.get(type._meta.name)

graphene/types/utils.py

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import inspect
12
from collections import OrderedDict
3+
from functools import partial
4+
from six import string_types
25

6+
from ..utils.module_loading import import_string
37
from .mountedtype import MountedType
48
from .unmountedtype import UnmountedType
59

@@ -62,3 +66,11 @@ def yank_fields_from_attrs(attrs, _as=None, delete=True, sort=True):
6266
if sort:
6367
fields_with_names = sorted(fields_with_names, key=lambda f: f[1])
6468
return OrderedDict(fields_with_names)
69+
70+
71+
def get_type(_type):
72+
if isinstance(_type, string_types):
73+
return import_string(_type)
74+
if inspect.isfunction(_type) or type(_type) is partial:
75+
return _type()
76+
return _type

0 commit comments

Comments
 (0)