Repository: mirumee/ariadne

Issue:
Add extension support to make_executable_schema issue #95
This addresses issue #95 

I have ported the logic from graphql-tools [buildSchemaFromTypeDefs](https://github.com/apollographql/graphql-tools/blob/master/src/generate/buildSchemaFromTypeDefinitions.ts#L48), which parse an ast document node then checks if there is any extension type included in the type defs. Those are pulled out and added to a new document that then uses the 'extend_schema' to extend the existing schema. 

Not exactly sure how you want to organize this but this is a working first pass.

Thanks!


Discussion:

Resolving patch:
diff --git a/ariadne/executable_schema.py b/ariadne/executable_schema.py
--- a/ariadne/executable_schema.py
+++ b/ariadne/executable_schema.py
@@ -1,6 +1,6 @@
 from typing import List, Union
 
-from graphql import GraphQLSchema, build_schema
+from graphql import DocumentNode, GraphQLSchema, build_ast_schema, extend_schema, parse
 
 from .types import SchemaBindable
 
@@ -12,7 +12,8 @@ def make_executable_schema(
     if isinstance(type_defs, list):
         type_defs = join_type_defs(type_defs)
 
-    schema = build_schema(type_defs)
+    ast_document = parse(type_defs)
+    schema = build_and_extend_schema(ast_document)
 
     if isinstance(bindables, list):
         for obj in bindables:
@@ -25,3 +26,28 @@ def make_executable_schema(
 
 def join_type_defs(type_defs: List[str]) -> str:
     return "\n\n".join(t.strip() for t in type_defs)
+
+
+def build_and_extend_schema(ast: DocumentNode) -> GraphQLSchema:
+    schema = build_ast_schema(ast)
+    extension_ast = extract_extensions(ast)
+
+    if extension_ast.definitions:
+        schema = extend_schema(schema, extension_ast)
+
+    return schema
+
+
+EXTENSION_KINDS = [
+    "scalar_type_extension",
+    "object_type_extension",
+    "interface_type_extension",
+    "union_type_extension",
+    "enum_type_extension",
+    "input_object_type_extension",
+]
+
+
+def extract_extensions(ast: DocumentNode) -> DocumentNode:
+    extensions = [node for node in ast.definitions if node.kind in EXTENSION_KINDS]
+    return DocumentNode(definitions=extensions)


Test patch:
diff --git a/tests/test_modularization.py b/tests/test_modularization.py
--- a/tests/test_modularization.py
+++ b/tests/test_modularization.py
@@ -23,6 +23,12 @@
     }
 """
 
+extend_typedef = """
+    extend type Query {
+        admin: User
+    }
+"""
+
 
 def test_list_of_type_defs_is_merged_into_executable_schema():
     query = QueryType()
@@ -89,3 +95,15 @@ def test_different_types_resolver_maps_are_merged_into_executable_schema():
     result = graphql_sync(schema, "{ user { username } }")
     assert result.errors is None
     assert result.data == {"user": {"username": "Joe"}}
+
+
+def test_defined_type_can_be_extended_with_new_field():
+    query = QueryType()
+    query.set_field("admin", lambda *_: Mock(username="Abby"))
+
+    type_defs = [root_typedef, module_typedef, extend_typedef]
+    schema = make_executable_schema(type_defs, query)
+
+    result = graphql_sync(schema, "{ admin { username } }")
+    assert result.errors is None
+    assert result.data == {"admin": {"username": "Abby"}}