prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  make_executable_schema resolvers arg should accept dict of dicts or list of dicts of dicts
  The `make_executable_schema` utility should optionally take list of dicts of dicts (AKA "resolvers map"), this would allow larger projects to easily split and compose resolvers as needed:
  
  ```python
  from ariadne import make_executable_schema
  
  from products.graphql import resolvers as products_resolvers
  from users.graphql import resolvers as users_resolvers
  
  
  typedefs = "..."
  resolvers = [products_resolvers, users_resolvers]
  
  schema = make_executable_schema(typedefs, resolvers)
  ```
  
  This task will likely require #13 to be done first, so we are 100% certain that all resolver mappings are dicts.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `ariadne/executable_schema.py`
  Content:
  ```
  1 from typing import List, Union
  2 
  3 from graphql import GraphQLSchema
  4 
  5 from .build_schema import build_schema_from_type_definitions
  6 from .resolvers import add_resolve_functions_to_schema
  7 
  8 
  9 def make_executable_schema(
  10     type_defs: Union[str, List[str]], resolvers: dict
  11 ) -> GraphQLSchema:
  12     schema = build_schema_from_type_definitions(type_defs)
  13     add_resolve_functions_to_schema(schema, resolvers)
  14     return schema
  15
  ```
  
  Path: `ariadne/build_schema.py`
  Content:
  ```
  1 from typing import List, Union
  2 
  3 from graphql import GraphQLSchema, parse
  4 from graphql.language.ast import (
  5     Document,
  6     ObjectTypeDefinition,
  7     OperationTypeDefinition,
  8     Name,
  9     NamedType,
  10     SchemaDefinition,
  11 )
  12 from graphql.utils.build_ast_schema import build_ast_schema
  13 
  14 
  15 def build_schema_from_type_definitions(
  16     type_defs: Union[str, List[str]]
  17 ) -> GraphQLSchema:
  18     if isinstance(type_defs, list):
  19         type_defs = concatenate_type_defs(type_defs)
  20 
  21     document = parse(type_defs)
  22 
  23     if not document_has_schema(document):
  24         schema_definition = build_default_schema(document)
  25         document.definitions.append(schema_definition)
  26 
  27     return build_ast_schema(document)
  28 
  29 
  30 def concatenate_type_defs(type_defs: List[str]) -> str:
  31     resolved_type_defs = []
  32     for type_def in type_defs:
  33         resolved_type_defs.append(type_def.strip())
  34     return "\n\n".join(resolved_type_defs)
  35 
  36 
  37 def build_default_schema(document: Document) -> SchemaDefinition:
  38     defined_types = [
  39         td.name.value
  40         for td in document.definitions
  41         if isinstance(td, ObjectTypeDefinition)
  42     ]
  43     operations = []
  44     if "Query" in defined_types:
  45         operations.append(
  46             OperationTypeDefinition("query", type=NamedType(name=Name("Query")))
  47         )
  48     if "Mutation" in defined_types:
  49         operations.append(
  50             OperationTypeDefinition("mutation", type=NamedType(name=Name("Mutation")))
  51         )
  52     if "Subscription" in defined_types:
  53         operations.append(
  54             OperationTypeDefinition(
  55                 "subscription", type=NamedType(name=Name("Subscription"))
  56             )
  57         )
  58     return SchemaDefinition(operation_types=operations, directives=[])
  59 
  60 
  61 def document_has_schema(document: Document) -> bool:
  62     return any(isinstance(td, SchemaDefinition) for td in document.definitions)
  63
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/ariadne/build_schema.py b/ariadne/build_schema.py
  --- a/ariadne/build_schema.py
  +++ b/ariadne/build_schema.py
  @@ -1,5 +1,3 @@
  -from typing import List, Union
  -
   from graphql import GraphQLSchema, parse
   from graphql.language.ast import (
       Document,
  @@ -12,12 +10,7 @@
   from graphql.utils.build_ast_schema import build_ast_schema
   
   
  -def build_schema_from_type_definitions(
  -    type_defs: Union[str, List[str]]
  -) -> GraphQLSchema:
  -    if isinstance(type_defs, list):
  -        type_defs = concatenate_type_defs(type_defs)
  -
  +def build_schema_from_type_definitions(type_defs: str) -> GraphQLSchema:
       document = parse(type_defs)
   
       if not document_has_schema(document):
  @@ -27,13 +20,6 @@
       return build_ast_schema(document)
   
   
  -def concatenate_type_defs(type_defs: List[str]) -> str:
  -    resolved_type_defs = []
  -    for type_def in type_defs:
  -        resolved_type_defs.append(type_def.strip())
  -    return "\n\n".join(resolved_type_defs)
  -
  -
   def build_default_schema(document: Document) -> SchemaDefinition:
       defined_types = [
           td.name.value
  diff --git a/ariadne/executable_schema.py b/ariadne/executable_schema.py
  --- a/ariadne/executable_schema.py
  +++ b/ariadne/executable_schema.py
  @@ -1,4 +1,6 @@
  -from typing import List, Union
  +from collections import defaultdict
  +from itertools import chain
  +from typing import Iterator, List, Union
   
   from graphql import GraphQLSchema
   
  @@ -6,9 +8,39 @@
   from .resolvers import add_resolve_functions_to_schema
   
   
  +def decompose_maps(resolvers_maps: List[dict]) -> Iterator[tuple]:
  +    def flatten(rm):
  +        for key, value in rm.items():
  +            for resolver_name, resolver in value.items():
  +                yield (key, resolver_name, resolver)
  +
  +    return chain.from_iterable(flatten(m) for m in resolvers_maps)
  +
  +
  +def merge_resolvers(resolver_list: Iterator[tuple]) -> dict:
  +    output = defaultdict(dict)  # type: dict
  +    for key, resolver_name, resolver in resolver_list:
  +        output[key][resolver_name] = resolver
  +    return output
  +
  +
  +def join_type_defs(type_defs: List[str]) -> str:
  +    return "\n\n".join(t.strip() for t in type_defs)
  +
  +
   def make_executable_schema(
  -    type_defs: Union[str, List[str]], resolvers: dict
  +    type_defs: Union[str, List[str]], resolvers: Union[dict, List[dict]]
   ) -> GraphQLSchema:
  +    if isinstance(type_defs, list):
  +        type_defs = join_type_defs(type_defs)
  +
       schema = build_schema_from_type_definitions(type_defs)
  -    add_resolve_functions_to_schema(schema, resolvers)
  +
  +    if isinstance(resolvers, list):
  +        add_resolve_functions_to_schema(
  +            schema, merge_resolvers(decompose_maps(resolvers))
  +        )
  +    elif isinstance(resolvers, dict):
  +        add_resolve_functions_to_schema(schema, resolvers)
  +
       return schema
  
verification_info: {"golden_diff": "diff --git a/ariadne/build_schema.py b/ariadne/build_schema.py\n--- a/ariadne/build_schema.py\n+++ b/ariadne/build_schema.py\n@@ -1,5 +1,3 @@\n-from typing import List, Union\n-\n from graphql import GraphQLSchema, parse\n from graphql.language.ast import (\n     Document,\n@@ -12,12 +10,7 @@\n from graphql.utils.build_ast_schema import build_ast_schema\n \n \n-def build_schema_from_type_definitions(\n-    type_defs: Union[str, List[str]]\n-) -> GraphQLSchema:\n-    if isinstance(type_defs, list):\n-        type_defs = concatenate_type_defs(type_defs)\n-\n+def build_schema_from_type_definitions(type_defs: str) -> GraphQLSchema:\n     document = parse(type_defs)\n \n     if not document_has_schema(document):\n@@ -27,13 +20,6 @@\n     return build_ast_schema(document)\n \n \n-def concatenate_type_defs(type_defs: List[str]) -> str:\n-    resolved_type_defs = []\n-    for type_def in type_defs:\n-        resolved_type_defs.append(type_def.strip())\n-    return \"\\n\\n\".join(resolved_type_defs)\n-\n-\n def build_default_schema(document: Document) -> SchemaDefinition:\n     defined_types = [\n         td.name.value\ndiff --git a/ariadne/executable_schema.py b/ariadne/executable_schema.py\n--- a/ariadne/executable_schema.py\n+++ b/ariadne/executable_schema.py\n@@ -1,4 +1,6 @@\n-from typing import List, Union\n+from collections import defaultdict\n+from itertools import chain\n+from typing import Iterator, List, Union\n \n from graphql import GraphQLSchema\n \n@@ -6,9 +8,39 @@\n from .resolvers import add_resolve_functions_to_schema\n \n \n+def decompose_maps(resolvers_maps: List[dict]) -> Iterator[tuple]:\n+    def flatten(rm):\n+        for key, value in rm.items():\n+            for resolver_name, resolver in value.items():\n+                yield (key, resolver_name, resolver)\n+\n+    return chain.from_iterable(flatten(m) for m in resolvers_maps)\n+\n+\n+def merge_resolvers(resolver_list: Iterator[tuple]) -> dict:\n+    output = defaultdict(dict)  # type: dict\n+    for key, resolver_name, resolver in resolver_list:\n+        output[key][resolver_name] = resolver\n+    return output\n+\n+\n+def join_type_defs(type_defs: List[str]) -> str:\n+    return \"\\n\\n\".join(t.strip() for t in type_defs)\n+\n+\n def make_executable_schema(\n-    type_defs: Union[str, List[str]], resolvers: dict\n+    type_defs: Union[str, List[str]], resolvers: Union[dict, List[dict]]\n ) -> GraphQLSchema:\n+    if isinstance(type_defs, list):\n+        type_defs = join_type_defs(type_defs)\n+\n     schema = build_schema_from_type_definitions(type_defs)\n-    add_resolve_functions_to_schema(schema, resolvers)\n+\n+    if isinstance(resolvers, list):\n+        add_resolve_functions_to_schema(\n+            schema, merge_resolvers(decompose_maps(resolvers))\n+        )\n+    elif isinstance(resolvers, dict):\n+        add_resolve_functions_to_schema(schema, resolvers)\n+\n     return schema\n", "issue": "make_executable_schema resolvers arg should accept dict of dicts or list of dicts of dicts\nThe `make_executable_schema` utility should optionally take list of dicts of dicts (AKA \"resolvers map\"), this would allow larger projects to easily split and compose resolvers as needed:\r\n\r\n```python\r\nfrom ariadne import make_executable_schema\r\n\r\nfrom products.graphql import resolvers as products_resolvers\r\nfrom users.graphql import resolvers as users_resolvers\r\n\r\n\r\ntypedefs = \"...\"\r\nresolvers = [products_resolvers, users_resolvers]\r\n\r\nschema = make_executable_schema(typedefs, resolvers)\r\n```\r\n\r\nThis task will likely require #13 to be done first, so we are 100% certain that all resolver mappings are dicts.\n", "before_files": [{"content": "from typing import List, Union\n\nfrom graphql import GraphQLSchema\n\nfrom .build_schema import build_schema_from_type_definitions\nfrom .resolvers import add_resolve_functions_to_schema\n\n\ndef make_executable_schema(\n    type_defs: Union[str, List[str]], resolvers: dict\n) -> GraphQLSchema:\n    schema = build_schema_from_type_definitions(type_defs)\n    add_resolve_functions_to_schema(schema, resolvers)\n    return schema\n", "path": "ariadne/executable_schema.py"}, {"content": "from typing import List, Union\n\nfrom graphql import GraphQLSchema, parse\nfrom graphql.language.ast import (\n    Document,\n    ObjectTypeDefinition,\n    OperationTypeDefinition,\n    Name,\n    NamedType,\n    SchemaDefinition,\n)\nfrom graphql.utils.build_ast_schema import build_ast_schema\n\n\ndef build_schema_from_type_definitions(\n    type_defs: Union[str, List[str]]\n) -> GraphQLSchema:\n    if isinstance(type_defs, list):\n        type_defs = concatenate_type_defs(type_defs)\n\n    document = parse(type_defs)\n\n    if not document_has_schema(document):\n        schema_definition = build_default_schema(document)\n        document.definitions.append(schema_definition)\n\n    return build_ast_schema(document)\n\n\ndef concatenate_type_defs(type_defs: List[str]) -> str:\n    resolved_type_defs = []\n    for type_def in type_defs:\n        resolved_type_defs.append(type_def.strip())\n    return \"\\n\\n\".join(resolved_type_defs)\n\n\ndef build_default_schema(document: Document) -> SchemaDefinition:\n    defined_types = [\n        td.name.value\n        for td in document.definitions\n        if isinstance(td, ObjectTypeDefinition)\n    ]\n    operations = []\n    if \"Query\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\"query\", type=NamedType(name=Name(\"Query\")))\n        )\n    if \"Mutation\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\"mutation\", type=NamedType(name=Name(\"Mutation\")))\n        )\n    if \"Subscription\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\n                \"subscription\", type=NamedType(name=Name(\"Subscription\"))\n            )\n        )\n    return SchemaDefinition(operation_types=operations, directives=[])\n\n\ndef document_has_schema(document: Document) -> bool:\n    return any(isinstance(td, SchemaDefinition) for td in document.definitions)\n", "path": "ariadne/build_schema.py"}], "after_files": [{"content": "from collections import defaultdict\nfrom itertools import chain\nfrom typing import Iterator, List, Union\n\nfrom graphql import GraphQLSchema\n\nfrom .build_schema import build_schema_from_type_definitions\nfrom .resolvers import add_resolve_functions_to_schema\n\n\ndef decompose_maps(resolvers_maps: List[dict]) -> Iterator[tuple]:\n    def flatten(rm):\n        for key, value in rm.items():\n            for resolver_name, resolver in value.items():\n                yield (key, resolver_name, resolver)\n\n    return chain.from_iterable(flatten(m) for m in resolvers_maps)\n\n\ndef merge_resolvers(resolver_list: Iterator[tuple]) -> dict:\n    output = defaultdict(dict)  # type: dict\n    for key, resolver_name, resolver in resolver_list:\n        output[key][resolver_name] = resolver\n    return output\n\n\ndef join_type_defs(type_defs: List[str]) -> str:\n    return \"\\n\\n\".join(t.strip() for t in type_defs)\n\n\ndef make_executable_schema(\n    type_defs: Union[str, List[str]], resolvers: Union[dict, List[dict]]\n) -> GraphQLSchema:\n    if isinstance(type_defs, list):\n        type_defs = join_type_defs(type_defs)\n\n    schema = build_schema_from_type_definitions(type_defs)\n\n    if isinstance(resolvers, list):\n        add_resolve_functions_to_schema(\n            schema, merge_resolvers(decompose_maps(resolvers))\n        )\n    elif isinstance(resolvers, dict):\n        add_resolve_functions_to_schema(schema, resolvers)\n\n    return schema\n", "path": "ariadne/executable_schema.py"}, {"content": "from graphql import GraphQLSchema, parse\nfrom graphql.language.ast import (\n    Document,\n    ObjectTypeDefinition,\n    OperationTypeDefinition,\n    Name,\n    NamedType,\n    SchemaDefinition,\n)\nfrom graphql.utils.build_ast_schema import build_ast_schema\n\n\ndef build_schema_from_type_definitions(type_defs: str) -> GraphQLSchema:\n    document = parse(type_defs)\n\n    if not document_has_schema(document):\n        schema_definition = build_default_schema(document)\n        document.definitions.append(schema_definition)\n\n    return build_ast_schema(document)\n\n\ndef build_default_schema(document: Document) -> SchemaDefinition:\n    defined_types = [\n        td.name.value\n        for td in document.definitions\n        if isinstance(td, ObjectTypeDefinition)\n    ]\n    operations = []\n    if \"Query\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\"query\", type=NamedType(name=Name(\"Query\")))\n        )\n    if \"Mutation\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\"mutation\", type=NamedType(name=Name(\"Mutation\")))\n        )\n    if \"Subscription\" in defined_types:\n        operations.append(\n            OperationTypeDefinition(\n                \"subscription\", type=NamedType(name=Name(\"Subscription\"))\n            )\n        )\n    return SchemaDefinition(operation_types=operations, directives=[])\n\n\ndef document_has_schema(document: Document) -> bool:\n    return any(isinstance(td, SchemaDefinition) for td in document.definitions)\n", "path": "ariadne/build_schema.py"}]}