1from functools import partial 2from typing import Any, Dict, List, Optional, Union 3 4from tartiflette.language.ast import ListTypeNode, NonNullTypeNode 5from tartiflette.language.parsers.lark import parse_to_document 6from tartiflette.schema.schema import GraphQLSchema 7from tartiflette.types.argument import GraphQLArgument 8from tartiflette.types.directive import GraphQLDirective 9from tartiflette.types.enum import ( 10 GraphQLEnumType, 11 GraphQLEnumTypeExtension, 12 GraphQLEnumValue, 13) 14from tartiflette.types.field import GraphQLField 15from tartiflette.types.input_field import GraphQLInputField 16from tartiflette.types.input_object import ( 17 GraphQLInputObjectType, 18 GraphQLInputObjectTypeExtension, 19) 20from tartiflette.types.interface import ( 21 GraphQLInterfaceType, 22 GraphQLInterfaceTypeExtension, 23) 24from tartiflette.types.list import GraphQLList 25from tartiflette.types.non_null import GraphQLNonNull 26from tartiflette.types.object import ( 27 GraphQLObjectType, 28 GraphQLObjectTypeExtension, 29) 30from tartiflette.types.scalar import ( 31 GraphQLScalarType, 32 GraphQLScalarTypeExtension, 33) 34from tartiflette.types.schema_extension import GraphQLSchemaExtension 35from tartiflette.types.union import GraphQLUnionType, GraphQLUnionTypeExtension 36 37__all__ = ("schema_from_sdl",) 38 39 40def parse_name( 41 name_node: "NameNode", schema: "GraphQLSchema" 42) -> Optional[str]: 43 """ 44 Returns the value of an AST name node. 45 :param name_node: AST name node to treat 46 :param schema: the GraphQLSchema instance linked to the engine 47 :type name_node: NameNode 48 :type schema: GraphQLSchema 49 :return: the name value 50 :rtype: Optional[str] 51 """ 52 # pylint: disable=unused-argument 53 return name_node.value if name_node else None 54 55 56def parse_named_type( 57 named_type_node: "NamedTypeNode", schema: "GraphQLSchema" 58) -> Optional[str]: 59 """ 60 Returns the value of the name of an AST named type node. 61 :param named_type_node: AST named type node to treat 62 :param schema: the GraphQLSchema instance linked to the engine 63 :type named_type_node: NamedTypeNode 64 :type schema: GraphQLSchema 65 :return: the name value 66 :rtype: Optional[str] 67 """ 68 if not named_type_node: 69 return None 70 return parse_name(named_type_node.name, schema) 71 72 73def parse_boolean_value( 74 boolean_value_node: "BooleanValueNode", schema: "GraphQLSchema" 75) -> Optional[bool]: 76 """ 77 Returns the value of an AST boolean value node. 78 :param boolean_value_node: AST boolean value node to treat 79 :param schema: the GraphQLSchema instance linked to the engine 80 :type boolean_value_node: BooleanValueNode 81 :type schema: GraphQLSchema 82 :return: the boolean value 83 :rtype: Optional[bool] 84 """ 85 # pylint: disable=unused-argument 86 return boolean_value_node.value if boolean_value_node else None 87 88 89def parse_enum_value( 90 enum_value_node: "EnumValueNode", schema: "GraphQLSchema" 91) -> Optional[str]: 92 """ 93 Returns the value of an AST enum value node. 94 :param enum_value_node: AST enum value node to treat 95 :param schema: the GraphQLSchema instance linked to the engine 96 :type enum_value_node: EnumValueNode 97 :type schema: GraphQLSchema 98 :return: the enum value 99 :rtype: Optional[str] 100 """ 101 # pylint: disable=unused-argument 102 return enum_value_node.value if enum_value_node else None 103 104 105def parse_float_value( 106 float_value_node: "FloatValueNode", schema: "GraphQLSchema" 107) -> Optional[float]: 108 """ 109 Returns the value of an AST float value node. 110 :param float_value_node: AST float value node to treat 111 :param schema: the GraphQLSchema instance linked to the engine 112 :type float_value_node: FloatValueNode 113 :type schema: GraphQLSchema 114 :return: the float value 115 :rtype: Optional[float] 116 """ 117 # pylint: disable=unused-argument 118 return float_value_node.value if float_value_node else None 119 120 121def parse_int_value( 122 int_value_node: "IntValueNode", schema: "GraphQLSchema" 123) -> Optional[int]: 124 """ 125 Returns the value of an AST int value node. 126 :param int_value_node: AST int value node to treat 127 :param schema: the GraphQLSchema instance linked to the engine 128 :type int_value_node: IntValueNode 129 :type schema: GraphQLSchema 130 :return: the int value 131 :rtype: Optional[int] 132 """ 133 # pylint: disable=unused-argument 134 return int_value_node.value if int_value_node else None 135 136 137def parse_string_value( 138 string_value_node: "StringValueNode", schema: "GraphQLSchema" 139) -> Optional[str]: 140 """ 141 Returns the value of an AST string value node. 142 :param string_value_node: AST string value node to treat 143 :param schema: the GraphQLSchema instance linked to the engine 144 :type string_value_node: StringValueNode 145 :type schema: GraphQLSchema 146 :return: the string value 147 :rtype: Optional[str] 148 """ 149 # pylint: disable=unused-argument 150 return string_value_node.value if string_value_node else None 151 152 153def parse_list_value( 154 list_value_node: "ListValueNode", schema: "GraphQLSchema" 155) -> Optional[List[Any]]: 156 """ 157 Returns the value of an AST list value node. 158 :param list_value_node: AST list value node to treat 159 :param schema: the GraphQLSchema instance linked to the engine 160 :type list_value_node: ListValueNode 161 :type schema: GraphQLSchema 162 :return: the list value 163 :rtype: Optional[List[Any]] 164 """ 165 if not list_value_node: 166 return None 167 return [parse_value(value, schema) for value in list_value_node.values] 168 169 170def parse_null_value( 171 null_value_node: "NullValueNode", schema: "GraphQLSchema" 172) -> None: 173 """ 174 Returns the value of an AST null value node. 175 :param null_value_node: AST null value node to treat 176 :param schema: the GraphQLSchema instance linked to the engine 177 :type null_value_node: NullValueNode 178 :type schema: GraphQLSchema 179 """ 180 # pylint: disable=unused-argument 181 return None 182 183 184def parse_object_value( 185 object_value_node: "ObjectValueNode", schema: "GraphQLSchema" 186) -> Optional[Dict[str, Any]]: 187 """ 188 Returns the value of an AST object value node 189 :param object_value_node: AST object value node to treat 190 :param schema: the GraphQLSchema instance linked to the engine 191 :type object_value_node: ObjectValueNode 192 :type schema: GraphQLSchema 193 :return: the object value 194 :rtype: Optional[Dict[str, Any]] 195 """ 196 if not object_value_node: 197 return None 198 return { 199 parse_name(field_node.name, schema): parse_value( 200 field_node.value, schema 201 ) 202 for field_node in object_value_node.fields 203 } 204 205 206_VALUE_PARSER_MAPPING = { 207 "BooleanValueNode": parse_boolean_value, 208 "EnumValueNode": parse_enum_value, 209 "FloatValueNode": parse_float_value, 210 "IntValueNode": parse_int_value, 211 "ListValueNode": parse_list_value, 212 "NullValueNode": parse_null_value, 213 "ObjectValueNode": parse_object_value, 214 "StringValueNode": parse_string_value, 215} 216 217 218def parse_value( 219 value_node: "ValueNode", schema: "GraphQLSchema" 220) -> Optional[Any]: 221 """ 222 Returns the value of an AST value node 223 :param value_node: AST value node to treat 224 :param schema: the GraphQLSchema instance linked to the engine 225 :type value_node: ValueNode 226 :type schema: GraphQLSchema 227 :return: the value 228 :rtype: Optional[Any] 229 """ 230 if not value_node: 231 return None 232 return _VALUE_PARSER_MAPPING[value_node.__class__.__name__]( 233 value_node, schema 234 ) 235 236 237def parse_input_value_definition( 238 input_value_definition_node: "InputValueDefinitionNode", 239 schema: "GraphQLSchema", 240 as_argument_definition: bool = False, 241) -> Optional[Union["GraphQLArgument", "GraphQLInputField"]]: 242 """ 243 Computes an AST input value definition node into a GraphQLArgument or 244 GraphQLInputField instance. 245 :param input_value_definition_node: AST input value definition node to 246 treat 247 :param schema: the GraphQLSchema instance linked to the engine 248 :param as_argument_definition: determines whether or not the return type 249 should be a GraphQLArgument or a GraphQLInputField 250 :type input_value_definition_node: InputValueDefinitionNode 251 :type schema: GraphQLSchema 252 :type as_argument_definition: bool 253 :return: the computed GraphQLArgument or GraphQLInputField instance 254 :rtype: Optional[Union[GraphQLArgument, GraphQLInputField]] 255 """ 256 if not input_value_definition_node: 257 return None 258 259 init_kwargs = { 260 "name": parse_name(input_value_definition_node.name, schema), 261 "description": parse_name( 262 input_value_definition_node.description, schema 263 ), 264 "gql_type": parse_type(input_value_definition_node.type, schema), 265 "default_value": input_value_definition_node.default_value, 266 "directives": input_value_definition_node.directives, 267 } 268 269 if not as_argument_definition: 270 return GraphQLInputField(**init_kwargs) 271 return GraphQLArgument( 272 **init_kwargs, definition=input_value_definition_node 273 ) 274 275 276def parse_arguments_definition( 277 argument_definitions_node: List["InputValueDefinitionNode"], 278 schema: "GraphQLSchema", 279) -> Optional[Dict[str, "GraphQLArgument"]]: 280 """ 281 Returns a dictionary of computed GraphQLArgument. 282 :param argument_definitions_node: list of AST input value definition 283 node to treat 284 :param schema: the GraphQLSchema instance linked to the engine 285 :type argument_definitions_node: List[InputValueDefinitionNode] 286 :type schema: GraphQLSchema 287 :return: dictionary of computed GraphQLArgument 288 :rtype: Optional[Dict[str, GraphQLArgument]] 289 """ 290 if not argument_definitions_node: 291 return None 292 293 computed_arguments = {} 294 for input_value_definition_node in argument_definitions_node: 295 computed_argument = parse_input_value_definition( 296 input_value_definition_node, schema, as_argument_definition=True 297 ) 298 computed_arguments[computed_argument.name] = computed_argument 299 return computed_arguments 300 301 302def parse_operation_type_definition( 303 operation_type_definition_node: "OperationTypeDefinitionNode", 304 schema: "GraphQLSchema", 305) -> None: 306 """ 307 Computes the new operation type definition name and update it in the 308 schema. 309 :param operation_type_definition_node: AST operation type definition node 310 to treat 311 :param schema: the GraphQLSchema instance linked to the engine 312 :type operation_type_definition_node: OperationTypeDefinitionNode 313 :type schema: GraphQLSchema 314 """ 315 if not operation_type_definition_node: 316 return 317 setattr( 318 schema, 319 f"{operation_type_definition_node.operation_type}_operation_name", 320 parse_named_type(operation_type_definition_node.type, schema), 321 ) 322 323 324def parse_operation_type_definitions( 325 operation_type_definitions_node: List["OperationTypeDefinitionNode"], 326 schema: "GraphQLSchema", 327) -> None: 328 """ 329 Parses all AST operation type definition node in order to update the 330 schema. 331 :param operation_type_definitions_node: list of AST operation type 332 definition node to treat 333 :param schema: the GraphQLSchema instance linked to the engine 334 :type operation_type_definitions_node: List[OperationTypeDefinitionNode] 335 :type schema: GraphQLSchema 336 """ 337 if not operation_type_definitions_node: 338 return 339 340 for operation_type_definition_node in operation_type_definitions_node: 341 parse_operation_type_definition(operation_type_definition_node, schema) 342 343 344def parse_schema_definition( 345 schema_definition_node: "SchemaDefinitionNode", schema: "GraphQLSchema" 346) -> None: 347 """ 348 Parses the AST operation type definition nodes from the AST schema 349 definition node. 350 :param schema_definition_node: AST schema definition node to treat 351 :param schema: the GraphQLSchema instance linked to the engine 352 :type schema_definition_node: SchemaDefinitionNode 353 :type schema: GraphQLSchema 354 """ 355 if not schema_definition_node: 356 return 357 parse_operation_type_definitions( 358 schema_definition_node.operation_type_definitions, schema 359 ) 360 schema.add_schema_directives(schema_definition_node.directives) 361 362 363def parse_scalar_type_definition( 364 scalar_type_definition_node: "ScalarTypeDefinitionNode", 365 schema: "GraphQLSchema", 366) -> Optional["GraphQLScalarType"]: 367 """ 368 Computes an AST scalar type definition node into a GraphQLScalarType 369 instance. 370 :param scalar_type_definition_node: AST scalar type definition node to 371 treat 372 :param schema: the GraphQLSchema instance linked to the engine 373 :type scalar_type_definition_node: ScalarTypeDefinitionNode 374 :type schema: GraphQLSchema 375 :return: the computed GraphQLScalarType instance 376 :rtype: Optional[GraphQLScalarType] 377 """ 378 if not scalar_type_definition_node: 379 return None 380 381 scalar_type = GraphQLScalarType( 382 name=parse_name(scalar_type_definition_node.name, schema), 383 description=parse_name( 384 scalar_type_definition_node.description, schema 385 ), 386 directives=scalar_type_definition_node.directives, 387 ) 388 schema.add_scalar_definition(scalar_type) 389 return scalar_type 390 391 392def parse_implements_interfaces( 393 interfaces_node: List["NamedTypeNode"], schema: "GraphQLSchema" 394) -> Optional[List[str]]: 395 """ 396 Returns the list of implemented interface names. 397 :param interfaces_node: list of AST named type node to treat 398 :param schema: the GraphQLSchema instance linked to the engine 399 :type interfaces_node: List[NamedTypeNode] 400 :type schema: GraphQLSchema 401 :return: the list of implemented interface names 402 :rtype: Optional[List[str]] 403 """ 404 if not interfaces_node: 405 return None 406 407 return [ 408 parse_named_type(interface_node, schema) 409 for interface_node in interfaces_node 410 ] 411 412 413def parse_object_type_definition( 414 object_type_definition_node: "ObjectTypeDefinitionNode", 415 schema: "GraphQLSchema", 416) -> Optional["GraphQLObjectType"]: 417 """ 418 Computes an AST object type definition node into a GraphQLObjectType 419 instance. 420 :param object_type_definition_node: AST object type definition node to 421 treat 422 :param schema: the GraphQLSchema instance linked to the engine 423 :type object_type_definition_node: ObjectTypeDefinitionNode 424 :type schema: GraphQLSchema 425 :return: the GraphQLObjectType instance 426 :rtype: Optional[GraphQLObjectType] 427 """ 428 if not object_type_definition_node: 429 return None 430 431 object_type = GraphQLObjectType( 432 name=parse_name(object_type_definition_node.name, schema), 433 description=parse_name( 434 object_type_definition_node.description, schema 435 ), 436 interfaces=parse_implements_interfaces( 437 object_type_definition_node.interfaces, schema 438 ), 439 fields=parse_fields_definition( 440 object_type_definition_node.fields, schema 441 ), 442 directives=object_type_definition_node.directives, 443 ) 444 schema.add_type_definition(object_type) 445 return object_type 446 447 448def parse_field_definition( 449 field_definition_node: "FieldDefinitionNode", schema: "GraphQLSchema" 450) -> Optional["GraphQLField"]: 451 """ 452 Computes an AST field definition node into a GraphQLField instance. 453 :param field_definition_node: AST field definition node to treat 454 :param schema: the GraphQLSchema instance linked to the engine 455 :type field_definition_node: FieldDefinitionNode 456 :type schema: GraphQLSchema 457 :return: the GraphQLField instance 458 :rtype: Optional[GraphQLField] 459 """ 460 if not field_definition_node: 461 return None 462 463 return GraphQLField( 464 name=parse_name(field_definition_node.name, schema), 465 description=parse_name(field_definition_node.description, schema), 466 gql_type=parse_type(field_definition_node.type, schema), 467 arguments=parse_arguments_definition( 468 field_definition_node.arguments, schema 469 ), 470 directives=field_definition_node.directives, 471 ) 472 473 474def parse_fields_definition( 475 fields_definition_node: List["FieldDefinitionNode"], 476 schema: "GraphQLSchema", 477) -> Optional[Dict[str, "GraphQLField"]]: 478 """ 479 Returns a dictionary of computed GraphQLField. 480 :param fields_definition_node: list of AST field definition node to treat 481 :param schema: the GraphQLSchema instance linked to the engine 482 :type fields_definition_node: List[FieldDefinitionNode] 483 :type schema: GraphQLSchema 484 :return: dictionary of computed GraphQLField 485 :rtype: Optional[Dict[str, GraphQLField]] 486 """ 487 if not fields_definition_node: 488 return None 489 490 computed_fields = {} 491 for field_definition_node in fields_definition_node: 492 computed_field = parse_field_definition(field_definition_node, schema) 493 computed_fields[computed_field.name] = computed_field 494 return computed_fields 495 496 497def parse_interface_type_definition( 498 interface_type_definition_node: "InterfaceTypeDefinitionNode", 499 schema: "GraphQLSchema", 500) -> Optional["GraphQLInterfaceType"]: 501 """ 502 Computes an AST interface type definition node into a GraphQLInterfaceType 503 instance. 504 :param interface_type_definition_node: AST interface type definition node 505 to treat 506 :param schema: the GraphQLSchema instance linked to the engine 507 :type interface_type_definition_node: InterfaceTypeDefinitionNode 508 :type schema: GraphQLSchema 509 :return: the GraphQLInterfaceType instance 510 :rtype: Optional[GraphQLInterfaceType] 511 """ 512 if not interface_type_definition_node: 513 return None 514 515 interface_type = GraphQLInterfaceType( 516 name=parse_name(interface_type_definition_node.name, schema), 517 description=parse_name( 518 interface_type_definition_node.description, schema 519 ), 520 fields=parse_fields_definition( 521 interface_type_definition_node.fields, schema 522 ), 523 directives=interface_type_definition_node.directives, 524 ) 525 schema.add_type_definition(interface_type) 526 return interface_type 527 528 529def parse_union_member_types( 530 types_node: List["NamedTypeNode"], schema: "GraphQLSchema" 531) -> Optional[List[str]]: 532 """ 533 Returns the list of union member type name. 534 :param types_node: list of AST named type node to treat 535 :param schema: the GraphQLSchema instance linked to the engine 536 :type types_node: List[NamedTypeNode] 537 :type schema: GraphQLSchema 538 :return: the list of union member type name 539 :rtype: Optional[List[str]] 540 """ 541 if not types_node: 542 return None 543 544 return [ 545 parse_named_type(union_member_type_node, schema) 546 for union_member_type_node in types_node 547 ] 548 549 550def parse_union_type_definition( 551 union_type_definition_node: "UnionTypeDefinitionNode", 552 schema: "GraphQLSchema", 553) -> Optional["GraphQLUnionType"]: 554 """ 555 Computes an AST union type definition node into a GraphQLUnionType 556 instance. 557 :param union_type_definition_node: AST union type definition node to treat 558 :param schema: the GraphQLSchema instance linked to the engine 559 :type union_type_definition_node: UnionTypeDefinitionNode 560 :type schema: GraphQLSchema 561 :return: the GraphQLUnionType instance 562 :rtype: Optional[GraphQLUnionType] 563 """ 564 if not union_type_definition_node: 565 return None 566 567 union_type = GraphQLUnionType( 568 name=parse_name(union_type_definition_node.name, schema), 569 description=parse_name(union_type_definition_node.description, schema), 570 types=parse_union_member_types( 571 union_type_definition_node.types, schema 572 ), 573 directives=union_type_definition_node.directives, 574 ) 575 schema.add_type_definition(union_type) 576 return union_type 577 578 579def parse_enum_value_definition( 580 enum_value_definition_node: "EnumValueDefinitionNode", 581 schema: "GraphQLSchema", 582) -> Optional["GraphQLEnumValue"]: 583 """ 584 Computes an AST enum value definition node into a GraphQLEnumValue 585 instance. 586 :param enum_value_definition_node: AST enum value definition node to treat 587 :param schema: the GraphQLSchema instance linked to the engine 588 :type enum_value_definition_node: EnumValueDefinitionNode 589 :type schema: GraphQLSchema 590 :return: the GraphQLEnumValue instance 591 :rtype: Optional[GraphQLEnumValue] 592 """ 593 if not enum_value_definition_node: 594 return None 595 return GraphQLEnumValue( 596 value=parse_name(enum_value_definition_node.name, schema), 597 description=parse_name(enum_value_definition_node.description, schema), 598 directives=enum_value_definition_node.directives, 599 ) 600 601 602def parse_enum_values_definition( 603 enum_values_definition_node: List["EnumValueDefinitionNode"], 604 schema: "GraphQLSchema", 605) -> Optional[List["GraphQLEnumValue"]]: 606 """ 607 Returns a list of computed GraphQLEnumValue. 608 :param enum_values_definition_node: list of AST enum value definition node 609 to treat 610 :param schema: the GraphQLSchema instance linked to the engine 611 :type enum_values_definition_node: List[EnumValueDefinitionNode] 612 :type schema: GraphQLSchema 613 :return: list of computed GraphQLEnumValue 614 :rtype: Optional[List[GraphQLEnumValue]] 615 """ 616 if not enum_values_definition_node: 617 return None 618 619 return [ 620 parse_enum_value_definition(enum_value_definition_node, schema) 621 for enum_value_definition_node in enum_values_definition_node 622 ] 623 624 625def parse_enum_type_definition( 626 enum_type_definition_node: "EnumTypeDefinitionNode", 627 schema: "GraphQLSchema", 628) -> Optional["GraphQLEnumType"]: 629 """ 630 Computes an AST enum type definition node into a GraphQLEnumType instance. 631 :param enum_type_definition_node: AST enum type definition node to treat 632 :param schema: the GraphQLSchema instance linked to the engine 633 :type enum_type_definition_node: EnumTypeDefinitionNode 634 :type schema: GraphQLSchema 635 :return: the GraphQLEnumType instance 636 :rtype: Optional[GraphQLEnumType] 637 """ 638 if not enum_type_definition_node: 639 return None 640 641 enum_type = GraphQLEnumType( 642 name=parse_name(enum_type_definition_node.name, schema), 643 description=parse_name(enum_type_definition_node.description, schema), 644 values=parse_enum_values_definition( 645 enum_type_definition_node.values, schema 646 ), 647 directives=enum_type_definition_node.directives, 648 ) 649 schema.add_enum_definition(enum_type) 650 return enum_type 651 652 653def parse_input_fields_definition( 654 input_fields_definition_node: List["InputValueDefinitionNode"], 655 schema: "GraphQLSchema", 656) -> Optional[Dict[str, "GraphQLInputField"]]: 657 """ 658 Returns a dictionary of computed GraphQLInputField. 659 :param input_fields_definition_node: list of AST input value definition 660 node to treat 661 :param schema: the GraphQLSchema instance linked to the engine 662 :type input_fields_definition_node: List[InputValueDefinitionNode] 663 :type schema: GraphQLSchema 664 :return: dictionary of computed GraphQLInputField 665 :rtype: Optional[Dict[str, GraphQLInputField]] 666 """ 667 if not input_fields_definition_node: 668 return None 669 670 computed_input_fields = {} 671 for input_field_definition_node in input_fields_definition_node: 672 input_value_definition = parse_input_value_definition( 673 input_field_definition_node, schema 674 ) 675 computed_input_fields[ 676 input_value_definition.name 677 ] = input_value_definition 678 return computed_input_fields 679 680 681def parse_input_object_type_definition( 682 input_object_type_definition_node: "InputObjectTypeDefinitionNode", 683 schema: "GraphQLSchema", 684) -> Optional["GraphQLInputObjectType"]: 685 """ 686 Computes an AST input object type definition node into a 687 GraphQLInputObjectType instance. 688 :param input_object_type_definition_node: AST input object type 689 definition node to treat 690 :param schema: the GraphQLSchema instance linked to the engine 691 :type input_object_type_definition_node: InputObjectTypeDefinitionNode 692 :type schema: GraphQLSchema 693 :return: the GraphQLInputObjectType instance 694 :rtype: Optional[GraphQLInputObjectType] 695 """ 696 if not input_object_type_definition_node: 697 return None 698 699 input_object_type = GraphQLInputObjectType( 700 name=parse_name(input_object_type_definition_node.name, schema), 701 description=parse_name( 702 input_object_type_definition_node.description, schema 703 ), 704 fields=parse_input_fields_definition( 705 input_object_type_definition_node.fields, schema 706 ), 707 directives=input_object_type_definition_node.directives, 708 ) 709 schema.add_type_definition(input_object_type) 710 return input_object_type 711 712 713def parse_type( 714 type_node: "TypeNode", schema: "GraphQLSchema" 715) -> Union["GraphQLList", "GraphQLNonNull", str]: 716 """ 717 Computes an AST type node into its GraphQL representation. 718 :param type_node: AST type node to treat 719 :param schema: the GraphQLSchema instance linked to the engine 720 :type type_node: TypeNode 721 :type schema: GraphQLSchema 722 :return: the GraphQL representation of the type node 723 :rtype: Union[GraphQLList, GraphQLNonNull, str] 724 """ 725 inner_type_node = type_node 726 type_wrappers = [] 727 while isinstance(inner_type_node, (NonNullTypeNode, ListTypeNode)): 728 if isinstance(inner_type_node, ListTypeNode): 729 type_wrappers.append(partial(GraphQLList, schema=schema)) 730 elif isinstance(inner_type_node, NonNullTypeNode): 731 type_wrappers.append( 732 partial(partial(GraphQLNonNull, schema=schema)) 733 ) 734 inner_type_node = inner_type_node.type 735 736 graphql_type = parse_named_type(inner_type_node, schema) 737 for type_wrapper in reversed(type_wrappers): 738 graphql_type = type_wrapper(gql_type=graphql_type) 739 return graphql_type 740 741 742def parse_directive_definition( 743 directive_definition_node: "DirectiveDefinitionNode", 744 schema: "GraphQLSchema", 745) -> Optional["GraphQLDirective"]: 746 """ 747 Computes an AST directive definition node into a GraphQLDirective instance. 748 :param directive_definition_node: AST directive definition node to treat 749 :param schema: the GraphQLSchema instance linked to the engine 750 :type directive_definition_node: DirectiveDefinitionNode 751 :type schema: GraphQLSchema 752 :return: the GraphQLDirective instance 753 :rtype: Optional[GraphQLDirective] 754 """ 755 if not directive_definition_node: 756 return None 757 directive = GraphQLDirective( 758 name=parse_name(directive_definition_node.name, schema), 759 description=parse_name(directive_definition_node.description, schema), 760 locations=[ 761 location.value for location in directive_definition_node.locations 762 ], 763 arguments=parse_arguments_definition( 764 directive_definition_node.arguments, schema 765 ), 766 ) 767 schema.add_directive_definition(directive) 768 return directive 769 770 771def parse_enum_type_extension( 772 enum_type_extension_node: "EnumTypeExtensionNode", schema: "GraphQLSchema" 773) -> "GraphQLEnumTypeExtension": 774 775 enum_extension = GraphQLEnumTypeExtension( 776 name=parse_name(enum_type_extension_node.name, schema), 777 directives=enum_type_extension_node.directives, 778 values=parse_enum_values_definition( 779 enum_type_extension_node.values, schema 780 ), 781 ) 782 783 schema.add_extension(enum_extension) 784 785 return enum_extension 786 787 788def parse_input_object_type_extension( 789 input_object_type_extension_node: "InputObjectTypeExtensionNode", 790 schema: "GraphQLSchema", 791) -> "GraphQLInputObjectTypeExtension": 792 793 input_object_extenstion = GraphQLInputObjectTypeExtension( 794 name=parse_name(input_object_type_extension_node.name, schema), 795 directives=input_object_type_extension_node.directives, 796 input_fields=parse_input_fields_definition( 797 input_object_type_extension_node.fields, schema 798 ), 799 ) 800 801 schema.add_extension(input_object_extenstion) 802 803 return input_object_extenstion 804 805 806def parse_object_type_extension( 807 object_type_extension_node: "ObjectTypeExtensionNode", 808 schema: "GraphQLSchema", 809) -> "GraphQLObjectTypeExtension": 810 811 object_extension = GraphQLObjectTypeExtension( 812 name=parse_name(object_type_extension_node.name, schema), 813 fields=parse_fields_definition( 814 object_type_extension_node.fields, schema 815 ), 816 directives=object_type_extension_node.directives, 817 interfaces=parse_implements_interfaces( 818 object_type_extension_node.interfaces, schema 819 ), 820 ) 821 822 schema.add_extension(object_extension) 823 824 return object_extension 825 826 827def parse_interface_type_extension( 828 interface_type_extension_node: "InterfaceTypeExtensionNode", 829 schema: "GraphQLSchema", 830) -> "GraphQLInterfaceTypeExtension": 831 832 interface_extension = GraphQLInterfaceTypeExtension( 833 name=parse_name(interface_type_extension_node.name, schema), 834 fields=parse_fields_definition( 835 interface_type_extension_node.fields, schema 836 ), 837 directives=interface_type_extension_node.directives, 838 ) 839 840 schema.add_extension(interface_extension) 841 842 return interface_extension 843 844 845def parse_scalar_type_extension( 846 scalar_type_extension_node: "ScalarTypeExtensionNode", 847 schema: "GraphQLSchema", 848) -> "GraphQLScalarTypeExtension": 849 850 scalar_extension = GraphQLScalarTypeExtension( 851 name=parse_name(scalar_type_extension_node.name, schema), 852 directives=scalar_type_extension_node.directives, 853 ) 854 855 schema.add_extension(scalar_extension) 856 857 return scalar_extension 858 859 860def parse_union_type_extension( 861 union_type_extension_node: "UnionTypeExtensionNode", 862 schema: "GraphQLSchema", 863) -> "GraphQLUnionTypeExtension": 864 865 union_extension = GraphQLUnionTypeExtension( 866 name=parse_name(union_type_extension_node.name, schema), 867 directives=union_type_extension_node.directives, 868 types=parse_union_member_types( 869 union_type_extension_node.types, schema 870 ), 871 ) 872 873 schema.add_extension(union_extension) 874 875 return union_extension 876 877 878def parse_schema_extension( 879 schema_extension_node: "SchemaExtensionNode", schema: "GraphQLSchema" 880) -> "GraphQLSchemaExtension": 881 schema_extension = GraphQLSchemaExtension( 882 directives=schema_extension_node.directives, 883 operations={ 884 x.operation_type: parse_named_type(x.type, schema) 885 for x in schema_extension_node.operation_type_definitions 886 }, 887 ) 888 889 schema.add_extension(schema_extension) 890 891 return schema_extension 892 893 894_DEFINITION_PARSER_MAPPING = { 895 "SchemaDefinitionNode": parse_schema_definition, 896 "ScalarTypeDefinitionNode": parse_scalar_type_definition, 897 "ObjectTypeDefinitionNode": parse_object_type_definition, 898 "InterfaceTypeDefinitionNode": parse_interface_type_definition, 899 "UnionTypeDefinitionNode": parse_union_type_definition, 900 "EnumTypeDefinitionNode": parse_enum_type_definition, 901 "InputObjectTypeDefinitionNode": parse_input_object_type_definition, 902 "DirectiveDefinitionNode": parse_directive_definition, 903 "EnumTypeExtensionNode": parse_enum_type_extension, 904 "InputObjectTypeExtensionNode": parse_input_object_type_extension, 905 "ObjectTypeExtensionNode": parse_object_type_extension, 906 "InterfaceTypeExtensionNode": parse_interface_type_extension, 907 "ScalarTypeExtensionNode": parse_scalar_type_extension, 908 "UnionTypeExtensionNode": parse_union_type_extension, 909 "SchemaExtensionNode": parse_schema_extension, 910} 911 912 913def parse_definition( 914 definition_node: "DefinitionNode", schema: "GraphQLSchema" 915) -> Any: 916 """ 917 Attempts to parses and computes an AST definition node. 918 :param definition_node: AST definition node to treat 919 :param schema: the GraphQLSchema instance linked to the engine 920 :type definition_node: DefinitionNode 921 :type schema: GraphQLSchema 922 :return: the computed result 923 :rtype: Any 924 """ 925 definition_parser = _DEFINITION_PARSER_MAPPING.get( 926 definition_node.__class__.__name__ 927 ) 928 if definition_parser is None: 929 return None 930 return definition_parser(definition_node, schema) 931 932 933def schema_from_document( 934 document_node: "DocumentNode", schema_name: str 935) -> "GraphQLSchema": 936 """ 937 Parses all AST definition node from the AST document node in order to build 938 the GraphQLSchema. 939 :param document_node: AST document node to treat 940 :param schema_name: name of the schema to build 941 :type document_node: DocumentNode 942 :type schema_name: str 943 :return: build GraphQLSchema 944 :rtype: GraphQLSchema 945 """ 946 schema = GraphQLSchema(name=schema_name) 947 for definition_node in document_node.definitions: 948 parse_definition(definition_node, schema) 949 return schema 950 951 952def schema_from_sdl( 953 sdl: Union[str, bytes], schema_name: str 954) -> "GraphQLSchema": 955 """ 956 Parse the SDL into an AST document node before validating it and building a 957 GraphQL Schema instance upon it. 958 :param sdl: sdl to parse 959 :param schema_name: name of the schema to build 960 :type sdl: Union[str, bytes] 961 :type schema_name: str 962 :return: build GraphQLSchema 963 :rtype: GraphQLSchema 964 """ 965 document_node = parse_to_document(sdl) 966 # TODO: implements the `validate_document` function 967 # errors = validate_document(document) 968 # if errors: 969 # raise Something(errors) 970 return schema_from_document(document_node, schema_name=schema_name) 971