2323 JSONString ,
2424 ID
2525)
26-
26+ import graphene
2727from graphene .types .base import BaseType
2828from graphene .types .datetime import Date , DateTime , Time
2929from pydantic import BaseModel
3535
3636from pydantic import fields
3737
38+ GRAPHENE2 = graphene .VERSION [0 ] < 3
39+
3840SHAPE_SINGLETON = (fields .SHAPE_SINGLETON ,)
3941SHAPE_SEQUENTIAL = (
4042 fields .SHAPE_LIST ,
5153else :
5254 SHAPE_MAPPING = T .cast (T .Tuple , (fields .SHAPE_MAPPING ,))
5355
56+
5457try :
5558 from graphene .types .decimal import Decimal as GrapheneDecimal
5659
5962 # graphene 2.1.5+ is required for Decimals
6063 DECIMAL_SUPPORTED = False
6164
65+
6266NONE_TYPE = None .__class__ # need to do this because mypy complains about type(None)
6367
6468
@@ -79,19 +83,19 @@ def _get_field(root, _info):
7983
8084
8185def convert_pydantic_input_field (
82- field : ModelField ,
83- registry : Registry ,
84- parent_type : T .Type = None ,
85- model : T .Type [BaseModel ] = None ,
86- ** field_kwargs ,
86+ field : ModelField ,
87+ registry : Registry ,
88+ parent_type : T .Type = None ,
89+ model : T .Type [BaseModel ] = None ,
90+ ** field_kwargs ,
8791) -> InputField :
8892 """
8993 Convert a Pydantic model field into a Graphene type field that we can add
9094 to the generated Graphene data model type.
9195 """
9296 declared_type = getattr (field , "type_" , None )
9397 field_kwargs .setdefault (
94- "type_" ,
98+ "type" if GRAPHENE2 else " type_" ,
9599 convert_pydantic_type (
96100 declared_type , field , registry , parent_type = parent_type , model = model
97101 ),
@@ -108,25 +112,27 @@ def convert_pydantic_input_field(
108112
109113
110114def convert_pydantic_field (
111- field : ModelField ,
112- registry : Registry ,
113- parent_type : T .Type = None ,
114- model : T .Type [BaseModel ] = None ,
115- ** field_kwargs ,
115+ field : ModelField ,
116+ registry : Registry ,
117+ parent_type : T .Type = None ,
118+ model : T .Type [BaseModel ] = None ,
119+ ** field_kwargs ,
116120) -> Field :
117121 """
118122 Convert a Pydantic model field into a Graphene type field that we can add
119123 to the generated Graphene data model type.
120124 """
121125 declared_type = getattr (field , "type_" , None )
122126 field_kwargs .setdefault (
123- "type" ,
127+ "type" if GRAPHENE2 else "type_" ,
124128 convert_pydantic_type (
125129 declared_type , field , registry , parent_type = parent_type , model = model
126130 ),
127131 )
128- field_kwargs .setdefault ("required" , field .required )
132+ field_kwargs .setdefault ("required" , not field .allow_none )
129133 field_kwargs .setdefault ("default_value" , field .default )
134+ if field .has_alias :
135+ field_kwargs .setdefault ("name" , field .alias )
130136 # TODO: find a better way to get a field's description. Some ideas include:
131137 # - hunt down the description from the field's schema, or the schema
132138 # from the field's base model
@@ -138,15 +144,21 @@ def convert_pydantic_field(
138144 if field_type is None :
139145 raise ValueError ("No field type could be determined." )
140146
141- return Field (field_type , resolver = get_attr_resolver (field .name ), ** field_kwargs )
147+ resolver_function = getattr (parent_type , "resolve_" + field .name , None )
148+ if resolver_function and callable (resolver_function ):
149+ field_resolver = resolver_function
150+ else :
151+ field_resolver = get_attr_resolver (field .name )
152+
153+ return Field (field_type , resolver = field_resolver , ** field_kwargs )
142154
143155
144156def convert_pydantic_type (
145- type_ : T .Type ,
146- field : ModelField ,
147- registry : Registry ,
148- parent_type : T .Type = None ,
149- model : T .Type [BaseModel ] = None ,
157+ type_ : T .Type ,
158+ field : ModelField ,
159+ registry : Registry ,
160+ parent_type : T .Type = None ,
161+ model : T .Type [BaseModel ] = None ,
150162) -> BaseType : # noqa: C901
151163 """
152164 Convert a Pydantic type to a Graphene Field type, including not just the
@@ -166,11 +178,11 @@ def convert_pydantic_type(
166178
167179
168180def find_graphene_type (
169- type_ : T .Type ,
170- field : ModelField ,
171- registry : Registry ,
172- parent_type : T .Type = None ,
173- model : T .Type [BaseModel ] = None ,
181+ type_ : T .Type ,
182+ field : ModelField ,
183+ registry : Registry ,
184+ parent_type : T .Type = None ,
185+ model : T .Type [BaseModel ] = None ,
174186) -> BaseType : # noqa: C901
175187 """
176188 Map a native Python type to a Graphene-supported Field type, where possible,
@@ -204,8 +216,8 @@ def find_graphene_type(
204216 elif registry and registry .get_type_for_model (type_ ):
205217 return registry .get_type_for_model (type_ )
206218 elif registry and (
207- isinstance (type_ , BaseModel )
208- or (inspect .isclass (type_ ) and issubclass (type_ , BaseModel ))
219+ isinstance (type_ , BaseModel )
220+ or (inspect .isclass (type_ ) and issubclass (type_ , BaseModel ))
209221 ):
210222 # If it's a Pydantic model that hasn't yet been wrapped with a ObjectType,
211223 # we can put a placeholder in and request that `resolve_placeholders()`
@@ -240,20 +252,36 @@ def find_graphene_type(
240252 )
241253 elif issubclass (type_ , enum .Enum ):
242254 return Enum .from_enum (type_ )
243- elif issubclass (type_ , str ):
255+ elif issubclass (type_ , ( str , bytes ) ):
244256 return String
257+ elif issubclass (type_ , datetime .datetime ):
258+ return DateTime
259+ elif issubclass (type_ , datetime .date ):
260+ return Date
261+ elif issubclass (type_ , datetime .time ):
262+ return Time
263+ elif issubclass (type_ , bool ):
264+ return Boolean
265+ elif issubclass (type_ , float ):
266+ return Float
267+ elif issubclass (type_ , decimal .Decimal ):
268+ return GrapheneDecimal if DECIMAL_SUPPORTED else Float
269+ elif issubclass (type_ , int ):
270+ return Int
271+ elif issubclass (type_ , (tuple , list , set )):
272+ return List
245273 else :
246274 raise ConversionError (
247275 f"Don't know how to convert the Pydantic field { field !r} ({ field .type_ } )"
248276 )
249277
250278
251279def convert_generic_python_type (
252- type_ : T .Type ,
253- field : ModelField ,
254- registry : Registry ,
255- parent_type : T .Type = None ,
256- model : T .Type [BaseModel ] = None ,
280+ type_ : T .Type ,
281+ field : ModelField ,
282+ registry : Registry ,
283+ parent_type : T .Type = None ,
284+ model : T .Type [BaseModel ] = None ,
257285) -> BaseType : # noqa: C901
258286 """
259287 Convert annotated Python generic types into the most appropriate Graphene
@@ -274,19 +302,15 @@ def convert_generic_python_type(
274302 return convert_literal_type (
275303 type_ , field , registry , parent_type = parent_type , model = model
276304 )
277- elif (
278- origin
279- in (
280- T .Tuple ,
281- T .List ,
282- T .Set ,
283- T .Collection ,
284- T .Iterable ,
285- list ,
286- set ,
287- )
288- or issubclass (origin , collections .abc .Sequence )
289- ):
305+ elif origin in (
306+ T .Tuple ,
307+ T .List ,
308+ T .Set ,
309+ T .Collection ,
310+ T .Iterable ,
311+ list ,
312+ set ,
313+ ) or issubclass (origin , collections .abc .Sequence ):
290314 # TODO: find a better way of divining that the origin is sequence-like
291315 inner_types = getattr (type_ , "__args__" , [])
292316 if not inner_types : # pragma: no cover # this really should be impossible
@@ -302,19 +326,19 @@ def convert_generic_python_type(
302326 )
303327 )
304328 elif origin in (T .Dict , T .Mapping , collections .OrderedDict , dict ) or issubclass (
305- origin , collections .abc .Mapping
329+ origin , collections .abc .Mapping
306330 ):
307331 raise ConversionError ("Don't know how to handle mappings in Graphene" )
308332 else :
309333 raise ConversionError (f"Don't know how to handle { type_ } (generic: { origin } )" )
310334
311335
312336def convert_union_type (
313- type_ : T .Type ,
314- field : ModelField ,
315- registry : Registry ,
316- parent_type : T .Type = None ,
317- model : T .Type [BaseModel ] = None ,
337+ type_ : T .Type ,
338+ field : ModelField ,
339+ registry : Registry ,
340+ parent_type : T .Type = None ,
341+ model : T .Type [BaseModel ] = None ,
318342):
319343 """
320344 Convert an annotated Python Union type into a Graphene Union.
@@ -343,11 +367,11 @@ def convert_union_type(
343367
344368
345369def convert_literal_type (
346- type_ : T .Type ,
347- field : ModelField ,
348- registry : Registry ,
349- parent_type : T .Type = None ,
350- model : T .Type [BaseModel ] = None ,
370+ type_ : T .Type ,
371+ field : ModelField ,
372+ registry : Registry ,
373+ parent_type : T .Type = None ,
374+ model : T .Type [BaseModel ] = None ,
351375):
352376 """
353377 Convert an annotated Python Literal type into a Graphene Scalar or Union of Scalars.
0 commit comments