diff --git a/.bumpversion.cfg b/.bumpversion.cfg
new file mode 100644
index 0000000..07a7c38
--- /dev/null
+++ b/.bumpversion.cfg
@@ -0,0 +1,20 @@
+[bumpversion]
+current_version = 3.1.2
+commit = False
+tag = False
+
+[bumpversion:file:src/graphql/version.py]
+search = version = "{current_version}"
+replace = version = "{new_version}"
+
+[bumpversion:file:docs/conf.py]
+search = version = release = '{current_version}'
+replace = version = release = '{new_version}'
+
+[bumpversion:file:README.md]
+search = The current version {current_version}
+replace = The current version {new_version}
+
+[bumpversion:file:pyproject.toml]
+search = version = "{current_version}"
+replace = version = "{new_version}"
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..cd976b1
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,21 @@
+[run]
+branch = True
+source = src
+omit =
+    */conftest.py
+    */cached_property.py
+    */is_collection.py
+    */test_*_fuzz.py
+
+[report]
+exclude_lines =
+    pragma: no cover
+    raise NotImplementedError
+    raise TypeError\(f?"Unexpected
+    assert False,
+    \s+next\($
+    if MYPY:
+    if TYPE_CHECKING:
+    ^\s+\.\.\.$
+    ^\s+pass$
+ignore_errors = True
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..d4a2c44
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# http://editorconfig.org
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+insert_final_newline = true
+charset = utf-8
+end_of_line = lf
+
+[*.bat]
+indent_style = tab
+end_of_line = crlf
+
+[LICENSE]
+insert_final_newline = false
+
+[Makefile]
+indent_style = tab
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..ccded58
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,4 @@
+[flake8]
+ignore = E203,W503
+exclude = .git,.mypy_cache,.pytest_cache,.tox,.venv,__pycache__,build,dist,docs
+max-line-length = 88
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..3ba13e0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@
+blank_issues_enabled: false
diff --git a/.github/ISSUE_TEMPLATE/open-a-graphql-core-issue.md b/.github/ISSUE_TEMPLATE/open-a-graphql-core-issue.md
new file mode 100644
index 0000000..a6fc342
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/open-a-graphql-core-issue.md
@@ -0,0 +1,26 @@
+---
+name: Open a GraphQL-core issue
+about: General template for all GraphQL-core issues
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+# Questions regarding how to use GraphQL
+
+If you have a question on how to use GraphQL, please [post it to Stack Overflow](https://stackoverflow.com/questions/ask?tags=graphql) with the tag [#graphql](https://stackoverflow.com/questions/tagged/graphql).
+
+# Reporting issues with GraphQL-core 3
+
+Before filing a new issue, make sure an issue for your problem doesn't already exist and that this is not an issue that should be filed against a different repository (see below).
+
+The best way to get a bug fixed is to provide a _pull request_ with a simplified failing test case (or better yet, include a fix).
+
+# Reporting issues with GraphQL-core 2
+
+Please use the issue tracker of the [legacy repository](https://github.com/graphql-python/graphql-core-legacy) for issues with legacy versions of GraphQL-core.
+
+# Feature requests
+
+GraphQL-core is a Python port of the [GraphQL.js](https://github.com/graphql/graphql-js) reference implementation of the [GraphQL specification](https://github.com/graphql/graphql-spec). To discuss new features which are not Python specific, please open an issue against the GraphQL.js project. To discuss features that fundamentally change the way GraphQL works, open an issue against the specification.
diff --git a/.gitignore b/.gitignore
index b0ba7d2..6b51313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,64 +1,27 @@
-# Compile Python files
-__pycache__/
-*.py[cod]
-
-# Distribution / packaging
-.Python
-venv
-.venv
-env
-.env
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
 
-# PyInstaller
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
+.cache/
 .coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
+.env*/
+.idea/
+.mypy_cache/
 .pytest_cache/
+.tox/
+.venv*/
+.vs/
 
-# PyBuilder
-target/
-
-# Type checking
-/.mypy_cache
-.pyre
-/type_info.json
-
-# Sphinx documentation
+build/
+dist/
 docs/_build/
+htmlcov/
+pip-wheel-metadata/
+wheels/
 
-# IntelliJ
-.idea
-*.iml
+play/
 
-# Visual Studio
-/.vscode
+__pycache__/
 
-# OS X
-.DS_Store
+*.cover
+*.egg
+*.egg-info
+*.log
+*.py[cod]
diff --git a/.mypy.ini b/.mypy.ini
new file mode 100644
index 0000000..0daa396
--- /dev/null
+++ b/.mypy.ini
@@ -0,0 +1,20 @@
+[mypy]
+python_version = 3.8
+check_untyped_defs = True
+no_implicit_optional = True
+strict_optional = True
+warn_redundant_casts = True
+warn_unused_ignores = True
+disallow_untyped_defs = True
+
+[mypy-graphql.pyutils.frozen_dict]
+disallow_untyped_defs = False
+
+[mypy-graphql.pyutils.frozen_list]
+disallow_untyped_defs = False
+
+[mypy-graphql.type.introspection]
+disallow_untyped_defs = False
+
+[mypy-tests.*]
+disallow_untyped_defs = False
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index 172fc3b..0000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-repos:
--   repo: git://github.com/pre-commit/pre-commit-hooks
-    rev: v2.1.0
-    hooks:
-    -   id: check-merge-conflict
-    -   id: check-json
-    -   id: check-yaml
-    -   id: debug-statements
-    -   id: end-of-file-fixer
-        exclude: ^docs/.*$
-    -   id: pretty-format-json
-        args:
-        - --autofix
-    -   id: trailing-whitespace
-        exclude: README.md
--   repo: https://github.com/asottile/pyupgrade
-    rev: v1.12.0
-    hooks:
-    -   id: pyupgrade
--   repo: https://github.com/ambv/black
-    rev: 19.3b0
-    hooks:
-    - id: black
-      language_version: python3.6
--   repo: https://github.com/pycqa/flake8
-    rev: 3.7.7
-    hooks:
-    -   id: flake8
-        exclude: test_.*$
diff --git a/.travis.yml b/.travis.yml
index d565f32..8be142f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,36 +1,37 @@
 language: python
 matrix:
   include:
-    -  env: TOXENV=py27
-       python: 2.7
-    -  env: TOXENV=py34
-       python: 3.4
-    -  env: TOXENV=py35
-       python: 3.5
-    -  env: TOXENV=py36
-       python: 3.6
-    -  env: TOXENV=py37
-       python: 3.7
-       dist: xenial
-       sudo: true # required workaround for https://github.com/travis-ci/travis-ci/issues/9815
-    -  env: TOXENV=pypy
-       python: pypy-5.7.1
-    -  env: TOXENV=pre-commit
-       python: 3.6
-    -  env: TOXENV=mypy
-       python: 3.6
-install: pip install coveralls tox
-script: tox
-after_success: coveralls
+    - name: Code quality tests
+      env: TOXENV=black,flake8,mypy,docs,manifest
+      python: 3.8
+    - name: Unit tests with Python 3.8
+      env: TOXENV=py38
+      python: 3.8
+    - name: Unit tests with Python 3.7
+      env: TOXENV=py37
+      python: 3.7
+    - name: Unit tests with Python 3.6
+      env: TOXENV=py36
+      python: 3.6
 cache:
   directories:
-    - $HOME/.cache/pip
-    - $HOME/.cache/pre-commit
+    - "$HOME/.cache/pip"
+    - "$TRAVIS_BUILD_DIR/.tox"
+install:
+  - pip install "poetry>=1,<2"
+  - poetry install
+script:
+  - tox -e $TOXENV
+after_success:
+  - codecov
 deploy:
   provider: pypi
-  user: syrusakbary
+  distributions: sdist bdist_wheel
   on:
+    branch: master
     tags: true
+    python: 3.8
+  skip_existing: true
+  user: mvanlonden
   password:
-    secure: q7kMxnJQ5LWr8fxVbQPm3pAXKRfYa1d2defM1UXKTQ+Gi6ZQ+QEOAOSbX1SKzYH62+hNRY2JGTeLkTQBeEYn05GJRh+WOkFzIFV1EnsgFbimSb6B83EmM57099GjJnO2nRUU4jyuNGU1joTeaD/g08ede072Es1I7DTuholNbYIq+brL/LQMJycuqZMoWUW4+pP8dE9SmjThMNYHlqNhzdXSE3BlZU0xcw7F2Ea384DNcekIIcapZuPjL167VouuSH/oMQMxBJo+ExEHdbqn5zsA9xcoF931XCgz4ag8U3jHhE48ZXM/xwdQt+S8JnOZcuv3MoAAioMbh+bYXUt2lmENWXCKK1kMDz2bJymwEUeZLA6lFxJQwvlVShowdi7xeyDYLIbeF7yG90Hd+5BqCZn5imzlcQxpjanaQq6xLwAzo6AHssWtd5bBOjDydknPxd1t3QGDoDvtfRdqrfOhlVX5813Hmd/vAopBAba7msKPMLxhsqDZKkwsVrLJLJDjGdpHNl/bbVaMsYcPrsFxa2W8PuddQFviHbL4HDNqHn5SpRwJcQ18YL1X5StQnUz1J+4E0W4mLrU3YW1k8RGlKTes/GeTH4sU+Sh3I9vrDv7849A8U9sSFyB2PT4Jyy8O2R5UyjoqnZDrkYYbLdn/caVo3ThrubTpwdPBmNwcDLA=
-  distributions: "sdist bdist_wheel"
+    secure: BjKsrn6rww8EEevU2VspVOFqrX/O09Yh8Xbjg+m6/yHmKDsX7kh+U3smgtOXGneKvnu6pLqXJS+gqGDi/u8OJfa8zrYyLlOXMEjPg0kWMl+w+s8E6BtEbOJ1qghS00kqk8xQeMK1YcfJLzztHt4g1VQM0C/y1kMub+Q8nz6KWHifgiSxcud7G/y8TrSYHcm74XWiY0U1zStUfx4z9Zftjr4MRFG9igXXLYCvGYoHOo0Ji4/6Ssgr3lX7GMT7glgBgrv5DmFpCWkVSuHrdyA7x32+O2XU8hLtGGPVoRWFhxc3cQ/QR4VrzCDauZMMOQG3c8dHoXz2T3dgsf9vN6XAB2HiaC1G2E3sI9C44hlUWxl3/5arZ0P4pq1MTRZaX2P6jU+cgyzWyuJ6f3bM2sYo0xOswhG1uP85iVWa2NlJIxmL8NMSoHlDtRLGWxMdqA6Vprn/Jn93AOkywa810ZCuSbgJEHS4ukJYVqE13mmwhL6Ocy9dZDvYGpYro05MlzDUvA8nN5HPuGdXYDRJFMfmBAkMlO0zWd+AtPx3CydFcs2bI5gKmANCfA5fdUot+xWAndMjJB89W0lCgl9b5N9LMxGL//erRbn7PDANB7xNcBrcDaV857lvUJsf2x5P0CE0NOHgEMW7SXZe6rPQZ+9fB+KEhN2RAFG/iIxRlNa+5kM=
diff --git a/CODEOWNERS b/CODEOWNERS
index 9a73b37..9a4d3d1 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1 +1 @@
-/ @syrusakbary @ekampf @dan98765 @projectcheshire @cito
+* @Cito
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 141776c..5012202 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,8 @@
-The MIT License (MIT)
+MIT License
 
-Copyright (c) 2016 GraphQL Python
+Copyright (c) GraphQL Contributors (GraphQL.js)
+Copyright (c) Syrus Akbary (GraphQL-core 2)
+Copyright (c) Christoph Zwerschke (GraphQL-core 3)
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/MANIFEST.in b/MANIFEST.in
index b912b3d..c1e8c0f 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,24 @@
-global-exclude tests/*
-recursive-exclude tests *
-recursive-exclude tests_py35 *
+include MANIFEST.in
+
+include CODEOWNERS
 include LICENSE
 include README.md
+
+include .bumpversion.cfg
+include .coveragerc
+include .editorconfig
+include .flake8
+include .mypy.ini
+
+include codecov.yml
+include tox.ini
+
+include poetry.lock
+include pyproject.toml
+
+graft src/graphql
+graft tests
+recursive-include docs *.txt *.rst conf.py Makefile make.bat *.jpg *.png *.gif
+prune docs/_build
+
+global-exclude *.py[co] __pycache__
diff --git a/README.md b/README.md
index 0234d66..b6900ae 100644
--- a/README.md
+++ b/README.md
@@ -1,159 +1,249 @@
-# GraphQL-core
+# GraphQL-core 3
 
-GraphQL for Python.
-
-_This library is a port of [graphql-js](https://github.com/graphql/graphql-js) to Python and currently is up-to-date with release [0.6.0](https://github.com/graphql/graphql-js/releases/tag/v0.6.0)._
+GraphQL-core 3 is a Python 3.6+ port of [GraphQL.js](https://github.com/graphql/graphql-js),
+the JavaScript reference implementation for [GraphQL](https://graphql.org/),
+a query language for APIs created by Facebook.
 
 [![PyPI version](https://badge.fury.io/py/graphql-core.svg)](https://badge.fury.io/py/graphql-core)
-[![Build Status](https://travis-ci.org/graphql-python/graphql-core.svg?branch=master)](https://travis-ci.org/graphql-python/graphql-core)
-[![Coverage Status](https://coveralls.io/repos/graphql-python/graphql-core/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-python/graphql-core?branch=master)
-[![Public Slack Discussion](https://graphql-slack.herokuapp.com/badge.svg)](https://graphql-slack.herokuapp.com/)
+[![Documentation Status](https://readthedocs.org/projects/graphql-core-3/badge/)](https://graphql-core-3.readthedocs.io)
+[![Build Status](https://travis-ci.com/graphql-python/graphql-core.svg?branch=master)](https://travis-ci.com/graphql-python/graphql-core)
+[![Coverage Status](https://codecov.io/gh/graphql-python/graphql-core/branch/master/graph/badge.svg)](https://codecov.io/gh/graphql-python/graphql-core)
+[![Dependency Updates](https://pyup.io/repos/github/graphql-python/graphql-core/shield.svg)](https://pyup.io/repos/github/graphql-python/graphql-core/)
+[![Python 3 Status](https://pyup.io/repos/github/graphql-python/graphql-core/python-3-shield.svg)](https://pyup.io/repos/github/graphql-python/graphql-core/)
+[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
 
-See more complete documentation at http://graphql.org/ and
-http://graphql.org/docs/api-reference-graphql/.
+The current version 3.1.2 of GraphQL-core is up-to-date with GraphQL.js version 15.1.0.
 
-For questions, ask [Stack Overflow](http://stackoverflow.com/questions/tagged/graphql).
+An extensive test suite with over 2200 unit tests and 100% coverage comprises a
+replication of the complete test suite of GraphQL.js, making sure this port is
+reliable and compatible with GraphQL.js.
 
-## Getting Started
 
-An overview of the GraphQL language is available in the
-[README](https://github.com/facebook/graphql/blob/master/README.md) for the
-[Specification for GraphQL](https://github.com/facebook/graphql).
+## Documentation
 
-The overview describes a simple set of GraphQL examples that exist as [tests](https://github.com/graphql-python/graphql-core/tree/master/tests/)
-in this repository. A good way to get started is to walk through that README and the corresponding tests
-in parallel.
+A more detailed documentation for GraphQL-core 3 can be found at
+[graphql-core-3.readthedocs.io](https://graphql-core-3.readthedocs.io/).
 
-### Using graphql-core
+The documentation for GraphQL.js can be found at [graphql.org/graphql-js/](https://graphql.org/graphql-js/).
 
-Install from pip:
+The documentation for GraphQL itself can be found at [graphql.org](https://graphql.org/).
 
-```sh
-pip install graphql-core
-```
+There will be also [blog articles](https://cito.github.io/tags/graphql/) with more usage
+examples.
+
+
+## Getting started
+
+An overview of GraphQL in general is available in the
+[README](https://github.com/graphql/graphql-spec/blob/master/README.md) for the
+[Specification for GraphQL](https://github.com/graphql/graphql-spec). That overview
+describes a simple set of GraphQL examples that exist as [tests](tests) in this
+repository. A good way to get started with this repository is to walk through that
+README and the corresponding tests in parallel.
+
+
+## Installation
+
+GraphQL-core 3 can be installed from PyPI using the built-in pip command:
+
+    python -m pip install "graphql-core>=3"
+
+Alternatively, you can also use [pipenv](https://docs.pipenv.org/) for installation in a
+virtual environment:
 
-GraphQL.js provides two important capabilities: building a type schema, and
+    pipenv install "graphql-core>=3"
+
+
+## Usage
+
+GraphQL-core provides two important capabilities: building a type schema, and
 serving queries against that type schema.
 
-First, build a GraphQL type schema which maps to your code base.
+First, build a GraphQL type schema which maps to your code base:
 
 ```python
 from graphql import (
-    graphql,
-    GraphQLSchema,
-    GraphQLObjectType,
-    GraphQLField,
-    GraphQLString
-)
+    GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)
 
 schema = GraphQLSchema(
-  query= GraphQLObjectType(
-    name='RootQueryType',
-    fields={
-      'hello': GraphQLField(
-        type= GraphQLString,
-        resolver=lambda *_: 'world'
-      )
-    }
-  )
-)
+    query=GraphQLObjectType(
+        name='RootQueryType',
+        fields={
+            'hello': GraphQLField(
+                GraphQLString,
+                resolve=lambda obj, info: 'world')
+        }))
 ```
 
-This defines a simple schema with one type and one field, that resolves
-to a fixed value. The `resolve` function can return a value, a promise,
-or an array of promises. A more complex example is included in the top
-level [tests](https://github.com/graphql-python/graphql-core/tree/master/tests/) directory.
+This defines a simple schema with one type and one field, that resolves to a fixed
+value. The `resolve` function can return a value, a co-routine object or a list of
+these. It takes two positional arguments; the first one provides the root or the
+resolved parent field, the second one provides a `GraphQLResolveInfo` object which
+contains information about the execution state of the query, including a `context`
+attribute holding per-request state such as authentication information or database
+session. Any GraphQL arguments are passed to the `resolve` functions as individual
+keyword arguments.
+
+Note that the signature of the resolver functions is a bit different in GraphQL.js,
+where the context is passed separately and arguments are passed as a single object.
+Also note that GraphQL fields must be passed as a `GraphQLField` object explicitly.
+Similarly, GraphQL arguments must be passed as `GraphQLArgument` objects.
+
+A more complex example is included in the top level [tests](tests) directory.
 
 Then, serve the result of a query against that type schema.
 
 ```python
+from graphql import graphql_sync
+
 query = '{ hello }'
 
-result = graphql(schema, query)
+print(graphql_sync(schema, query))
+```
 
-# Prints
-# {'hello': 'world'} (as OrderedDict)
+This runs a query fetching the one field defined, and then prints the result:
 
-print result.data
+```python
+ExecutionResult(data={'hello': 'world'}, errors=None)
 ```
 
-This runs a query fetching the one field defined. The `graphql` function will
-first ensure the query is syntactically and semantically valid before executing
-it, reporting errors otherwise.
+The `graphql_sync` function will first ensure the query is syntactically and
+semantically valid before executing it, reporting errors otherwise.
 
 ```python
-query = '{ boyhowdy }'
+from graphql import graphql_sync
 
-result = graphql(schema, query)
+query = '{ BoyHowdy }'
 
-# Prints
-# [GraphQLError('Cannot query field "boyhowdy" on type "RootQueryType".',)]
-
-print result.errors
+print(graphql_sync(schema, query))
 ```
 
-### Executors
+Because we queried a non-existing field, we will get the following result:
 
-The graphql query is executed, by default, synchronously (using `SyncExecutor`).
-However the following executors are available if we want to resolve our fields in parallel:
+```python
+ExecutionResult(data=None, errors=[GraphQLError(
+    "Cannot query field 'BoyHowdy' on type 'RootQueryType'.",
+    locations=[SourceLocation(line=1, column=3)])])
+```
 
-- `graphql.execution.executors.asyncio.AsyncioExecutor`: This executor executes the resolvers in the Python asyncio event loop.
-- `graphql.execution.executors.gevent.GeventExecutor`: This executor executes the resolvers in the Gevent event loop.
-- `graphql.execution.executors.process.ProcessExecutor`: This executor executes each resolver as a process.
-- `graphql.execution.executors.thread.ThreadExecutor`: This executor executes each resolver in a Thread.
-- `graphql.execution.executors.sync.SyncExecutor`: This executor executes each resolver synchronusly (default).
+The `graphql_sync` function assumes that all resolvers return values synchronously. By
+using coroutines as resolvers, you can also create results in an asynchronous fashion
+with the `graphql` function.
 
-#### Usage
+```python
+import asyncio
+from graphql import (
+    graphql, GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)
 
-You can specify the executor to use via the executor keyword argument in the `grapqhl.execution.execute` function.
 
-```python
-from graphql.execution.execute import execute
+async def resolve_hello(obj, info):
+    await asyncio.sleep(3)
+    return 'world'
 
-execute(schema, ast, executor=SyncExecutor())
+schema = GraphQLSchema(
+    query=GraphQLObjectType(
+        name='RootQueryType',
+        fields={
+            'hello': GraphQLField(
+                GraphQLString,
+                resolve=resolve_hello)
+        }))
+
+
+async def main():
+    query = '{ hello }'
+    print('Fetching the result...')
+    result = await graphql(schema, query)
+    print(result)
+
+
+loop = asyncio.get_event_loop()
+try:
+    loop.run_until_complete(main())
+finally:
+    loop.close()
 ```
 
-### Contributing
 
-After cloning this repo, create a [virtualenv](https://virtualenv.pypa.io/en/stable/) and ensure dependencies are installed by running:
+## Goals and restrictions
 
-```sh
-virtualenv venv
-source venv/bin/activate
-pip install -e ".[test]"
-```
+GraphQL-core tries to reproduce the code of the reference implementation GraphQL.js
+in Python as closely as possible and to stay up-to-date with the latest development of
+GraphQL.js.
 
-Well-written tests and maintaining good test coverage is important to this project. While developing, run new and existing tests with:
+GraphQL-core 3 (formerly known as GraphQL-core-next) has been created as a modern
+alternative to [GraphQL-core 2](https://github.com/graphql-python/graphql-core-legacy),
+a prior work by Syrus Akbary, based on an older version of GraphQL.js and also
+targeting older Python versions. Some parts of GraphQL-core 3 have been inspired by
+GraphQL-core 2 or directly taken over with only slight modifications, but most of the
+code has been re-implemented from scratch, replicating the latest code in GraphQL.js
+very closely and adding type hints for Python.
 
-```sh
-py.test PATH/TO/MY/DIR/test_test.py # Single file
-py.test PATH/TO/MY/DIR/ # All tests in directory
-```
+Design goals for the GraphQL-core 3 library are:
 
-Add the `-s` flag if you have introduced breakpoints into the code for debugging.
-Add the `-v` ("verbose") flag to get more detailed test output. For even more detailed output, use `-vv`.
-Check out the [pytest documentation](https://docs.pytest.org/en/latest/) for more options and test running controls.
+* to be a simple, cruft-free, state-of-the-art implementation of GraphQL using current
+  library and language versions
+* to be very close to the GraphQL.js reference implementation, while still using a
+  Pythonic API and code style
+* to make extensive use of Python type hints, similar to how GraphQL.js makes uses Flow
+* to use [black](https://github.com/ambv/black) for automatic code formatting
+* to replicate the complete Mocha-based test suite of GraphQL.js using
+  [pytest](https://docs.pytest.org/)
 
-GraphQL-core supports several versions of Python. To make sure that changes do not break compatibility with any of those versions, we use `tox` to create virtualenvs for each python version and run tests with that version. To run against all python versions defined in the `tox.ini` config file, just run:
+Some restrictions (mostly in line with the design goals):
 
-```sh
-tox
-```
+* requires Python 3.6 or newer
+* does not support some already deprecated methods and options of GraphQL.js
+* supports asynchronous operations only via async.io
+  (does not support the additional executors in GraphQL-core)
 
-If you wish to run against a specific version defined in the `tox.ini` file:
 
-```sh
-tox -e py36
-```
+## Integration with other libraries and roadmap
+
+* [Graphene](http://graphene-python.org/) is a more high-level framework for building
+  GraphQL APIs in Python, and there is already a whole ecosystem of libraries, server
+  integrations and tools built on top of Graphene. Most of this Graphene ecosystem has
+  also been created by Syrus Akbary, who meanwhile has handed over the maintenance
+  and future development to members of the GraphQL-Python community.
+
+  The current version 2 of Graphene is using Graphql-core 2 as core library for much of
+  the heavy lifting. Note that Graphene 2 is not compatible with GraphQL-core 3.
+  The  new version 3 of Graphene will use GraphQL-core 3 instead of GraphQL-core 2.
+
+* [Ariadne](https://github.com/mirumee/ariadne) is a Python library for implementing
+  GraphQL servers using schema-first approach created by Mirumee Software.
+
+  Ariadne is already using GraphQL-core 3 as its GraphQL implementation.
+
+* [Strawberry](https://github.com/strawberry-graphql/strawberry), created by Patrick
+  Arminio, is a new GraphQL library for Python 3, inspired by dataclasses,
+  that is also using GraphQL-core 3 as underpinning.
+
+
+## Changelog
+
+Changes are tracked as
+[GitHub releases](https://github.com/graphql-python/graphql-core/releases).
+
+
+## Credits and history
 
-Tox can only use whatever versions of python are installed on your system. When you create a pull request, Travis will also be running the same tests and report the results, so there is no need for potential contributors to try to install every single version of python on their own system ahead of time. We appreciate opening issues and pull requests to make GraphQL-core even more stable & useful!
+The GraphQL-core 3 library
+* has been created and is maintained by Christoph Zwerschke
+* uses ideas and code from GraphQL-core 2, a prior work by Syrus Akbary
+* is a Python port of GraphQL.js which has been developed by Lee Byron and others
+  at Facebook, Inc. and is now maintained
+  by the [GraphQL foundation](https://gql.foundation/join/)
 
-## Main Contributors
+Please watch the recording of Lee Byron's short keynote on the
+[history of GraphQL](https://www.youtube.com/watch?v=VjHWkBr3tjI)
+at the open source leadership summit 2019 to better understand
+how and why GraphQL was created at Facebook and then became open sourced
+and ported to many different programming languages.
 
-- [@syrusakbary](https://github.com/syrusakbary/)
-- [@jhgg](https://github.com/jhgg/)
-- [@dittos](https://github.com/dittos/)
 
 ## License
 
-[MIT License](https://github.com/graphql-python/graphql-core/blob/master/LICENSE)
+GraphQL-core 3 is
+[MIT-licensed](https://github.com/graphql-python/graphql-core/blob/master/LICENSE),
+just like GraphQL.js.
diff --git a/bin/autolinter b/bin/autolinter
deleted file mode 100755
index cd4ef37..0000000
--- a/bin/autolinter
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-# Install the required scripts with
-# pip install autoflake autopep8 isort
-autoflake ./graphql/ ./tests/ -r --remove-unused-variables --in-place
-autopep8 ./tests/ ./graphql/ -r --in-place --experimental --aggressive --max-line-length 120
-isort -rc ./tests/ ./graphql/
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..c393a12
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,10 @@
+codecov:
+  notify:
+    require_ci_to_pass: yes
+
+comment: no
+coverage:
+  status:
+    project:
+      default:
+        target: auto
\ No newline at end of file
diff --git a/conftest.py b/conftest.py
deleted file mode 100644
index 6b91637..0000000
--- a/conftest.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Configuration for pytest to automatically collect types.
-# Thanks to Guilherme Salgado.
-import pytest
-
-try:
-    import pyannotate_runtime
-
-    PYANOTATE_PRESENT = True
-except ImportError:
-    PYANOTATE_PRESENT = False
-
-if PYANOTATE_PRESENT:
-
-    def pytest_collection_finish(session):
-        """Handle the pytest collection finish hook: configure pyannotate.
-        Explicitly delay importing `collect_types` until all tests have
-        been collected.  This gives gevent a chance to monkey patch the
-        world before importing pyannotate.
-        """
-        from pyannotate_runtime import collect_types
-
-        collect_types.init_types_collection()
-
-    @pytest.fixture(autouse=True)
-    def collect_types_fixture():
-        from pyannotate_runtime import collect_types
-
-        collect_types.resume()
-        yield
-        collect_types.pause()
-
-    def pytest_sessionfinish(session, exitstatus):
-        from pyannotate_runtime import collect_types
-
-        collect_types.dump_stats("type_info.json")
diff --git a/docs/Makefile b/docs/Makefile
index 1d14ddd..d4bb2cb 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,192 +1,20 @@
-# Makefile for Sphinx documentation
+# Minimal makefile for Sphinx documentation
 #
 
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
 BUILDDIR      = _build
 
-# User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
-endif
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
-
+# Put it first so that "make" without argument is like "make help".
 help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html       to make standalone HTML files"
-	@echo "  dirhtml    to make HTML files named index.html in directories"
-	@echo "  singlehtml to make a single large HTML file"
-	@echo "  pickle     to make pickle files"
-	@echo "  json       to make JSON files"
-	@echo "  htmlhelp   to make HTML files and a HTML help project"
-	@echo "  qthelp     to make HTML files and a qthelp project"
-	@echo "  applehelp  to make an Apple Help Book"
-	@echo "  devhelp    to make HTML files and a Devhelp project"
-	@echo "  epub       to make an epub"
-	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
-	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
-	@echo "  text       to make text files"
-	@echo "  man        to make manual pages"
-	@echo "  texinfo    to make Texinfo files"
-	@echo "  info       to make Texinfo files and run them through makeinfo"
-	@echo "  gettext    to make PO message catalogs"
-	@echo "  changes    to make an overview of all changed/added/deprecated items"
-	@echo "  xml        to make Docutils-native XML files"
-	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
-	@echo "  linkcheck  to check all external links for integrity"
-	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
-	@echo "  coverage   to run coverage check of the documentation (if enabled)"
-
-clean:
-	rm -rf $(BUILDDIR)/*
-
-html:
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
-	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
-	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
-	@echo
-	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files."
-
-json:
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
-	@echo
-	@echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
-	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
-	@echo
-	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
-	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/graphql-py.qhcp"
-	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/graphql-py.qhc"
-
-applehelp:
-	$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
-	@echo
-	@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
-	@echo "N.B. You won't be able to view it unless you put it in" \
-	      "~/Library/Documentation/Help or install it in your application" \
-	      "bundle."
-
-devhelp:
-	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
-	@echo
-	@echo "Build finished."
-	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/graphql-py"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/graphql-py"
-	@echo "# devhelp"
-
-epub:
-	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
-	@echo
-	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
-	@echo "Run \`make' in that directory to run these through (pdf)latex" \
-	      "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo "Running LaTeX files through pdflatex..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-latexpdfja:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo "Running LaTeX files through platex and dvipdfmx..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
-	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
-	@echo
-	@echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
-	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
-	@echo
-	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-	@echo
-	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
-	@echo "Run \`make' in that directory to run these through makeinfo" \
-	      "(use \`make info' here to do that automatically)."
-
-info:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-	@echo "Running Texinfo files through makeinfo..."
-	make -C $(BUILDDIR)/texinfo info
-	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
-	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
-	@echo
-	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
-	@echo
-	@echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
-	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
-	@echo "Testing of doctests in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/doctest/output.txt."
-
-coverage:
-	$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
-	@echo "Testing of coverage in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/coverage/python.txt."
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
 
-xml:
-	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
-	@echo
-	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+.PHONY: help Makefile
 
-pseudoxml:
-	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
-	@echo
-	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/conf.py b/docs/conf.py
index 0e34c36..0d198e6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
-# graphqllib documentation build configuration file, created by
-# sphinx-quickstart on Wed Sep 16 20:08:39 2015.
+# GraphQL-core 3 documentation build configuration file, created by
+# sphinx-quickstart on Thu Jun 21 16:28:30 2018.
 #
 # This file is execfile()d with the current directory set to its
 # containing dir.
@@ -12,57 +12,56 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys
-import os
-
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath(".."))
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
 
 # -- General configuration ------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
+#
 # needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    "sphinx.ext.autodoc",
-    "sphinx.ext.intersphinx",
-    "sphinx.ext.todo",
-    "sphinx.ext.coverage",
-    "sphinx.ext.viewcode",
+    'sphinx.ext.autodoc',
 ]
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ["_templates"]
+templates_path = ['_templates']
 
 # The suffix(es) of source filenames.
 # You can specify multiple suffix as a list of string:
+#
 # source_suffix = ['.rst', '.md']
-source_suffix = ".rst"
+source_suffix = '.rst'
 
 # The encoding of source files.
+#
 # source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = "index"
+master_doc = 'index'
 
 # General information about the project.
-project = u"graphqllib"
-copyright = u"2015, Taeho Kim"
-author = u"Taeho Kim"
+project = 'GraphQL-core 3'
+copyright = '2020, Christoph Zwerschke'
+author = 'Christoph Zwerschke'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = "0.1"
+# version = '3.1'
 # The full version, including alpha/beta/rc tags.
-release = "0.1a0"
+version = release = '3.1.2'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -73,31 +72,85 @@ language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
+#
 # today = ''
+#
 # Else, today_fmt is used as the format for a strftime call.
+#
 # today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ["_build"]
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# AutoDoc configuration
+#autoclass_content = "both"
+autodoc_default_options = {
+    'members': True,
+    'inherited-members': True,
+    'private-members': False,
+    'special-members': '__init__',
+    'undoc-members': True,
+    'show-inheritance': True
+}
+autosummary_generate = True
+
+# ignore certain warnings
+# (references to some of the Python built-in types do not resolve correctly)
+nitpicky = True
+nitpick_ignore = [('py:class', t) for t in (
+    'dict', 'list', 'object', 'tuple',
+    'Exception', 'TypeError', 'ValueError',
+    'builtins.str', 'enum.Enum',
+    'typing.Callable', 'typing.Dict', 'typing.Generic', 'typing.List',
+    'graphql.pyutils.cached_property.CachedProperty',
+    'graphql.pyutils.path.Path',
+    'graphql.error.graphql_error.GraphQLError',
+    'graphql.language.ast.DefinitionNode',
+    'graphql.language.ast.ExecutableDefinitionNode',
+    'graphql.language.ast.Node',
+    'graphql.language.ast.ScalarTypeDefinitionNode',
+    'graphql.language.ast.SelectionNode',
+    'graphql.language.ast.TypeDefinitionNode',
+    'graphql.language.ast.TypeExtensionNode',
+    'graphql.language.ast.TypeNode',
+    'graphql.language.ast.TypeSystemDefinitionNode',
+    'graphql.language.ast.ValueNode',
+    'graphql.language.visitor.Visitor',
+    'graphql.type.definition.GraphQLNamedType',
+    'graphql.type.definition.GraphQLType',
+    'graphql.type.definition.GraphQLWrappingType',
+    'graphql.validation.rules.ASTValidationRule',
+    'graphql.validation.rules.SDLValidationRule',
+    'graphql.validation.rules.ValidationRule',
+    'graphql.validation.validation_context.ASTValidationContext',
+    'graphql.validation.rules.known_argument_names'
+    '.KnownArgumentNamesOnDirectivesRule',
+    'graphql.validation.rules.provided_required_arguments'
+    '.ProvidedRequiredArgumentsOnDirectivesRule')]
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
+#
 # default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
+#
 # add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
+#
 # add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
+#
 # show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = "sphinx"
+pygments_style = 'sphinx'
 
 # A list of ignored prefixes for module index sorting.
 # modindex_common_prefix = []
@@ -106,37 +159,42 @@ pygments_style = "sphinx"
 # keep_warnings = False
 
 # If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = True
-
+todo_include_todos = False
 
 # -- Options for HTML output ----------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = "alabaster"
+#
+html_theme = 'sphinx_rtd_theme'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
+#
 # html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
 # html_theme_path = []
 
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-# html_title = None
+# The name for this set of Sphinx documents.
+# "<project> v<release> documentation" by default.
+#
+# html_title = 'GraphQL-core v3.1.0'
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
+#
 # html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
+#
 # html_logo = None
 
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# The name of an image file (relative to this directory) to use as a favicon of
+# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
+#
 # html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
@@ -147,44 +205,57 @@ html_theme = "alabaster"
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
+#
 # html_extra_path = []
 
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-# html_last_updated_fmt = '%b %d, %Y'
+# If not None, a 'Last updated on:' timestamp is inserted at every page
+# bottom, using the given strftime format.
+# The empty string is equivalent to '%b %d, %Y'.
+#
+# html_last_updated_fmt = None
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
+#
 # html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
+#
 # html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
+#
 # html_additional_pages = {}
 
 # If false, no module index is generated.
+#
 # html_domain_indices = True
 
 # If false, no index is generated.
+#
 # html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
+#
 # html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-# html_show_sourcelink = True
+#
+html_show_sourcelink = False
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#
 # html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#
 # html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
+#
 # html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
@@ -193,58 +264,76 @@ html_theme = "alabaster"
 # Language to be used for generating the HTML full-text search index.
 # Sphinx supports the following languages:
 #   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
+#
 # html_search_language = 'en'
 
 # A dictionary with options for the search language support, empty by default.
-# Now only 'ja' uses this config value
+# 'ja' uses this config value.
+# 'zh' user can custom change `jieba` dictionary path.
+#
 # html_search_options = {'type': 'default'}
 
 # The name of a javascript file (relative to the configuration directory) that
 # implements a search results scorer. If empty, the default will be used.
+#
 # html_search_scorer = 'scorer.js'
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = "graphqllibdoc"
+htmlhelp_basename = 'GraphQL-core-3-doc'
 
 # -- Options for LaTeX output ---------------------------------------------
 
 latex_elements = {
-    # The paper size ('letterpaper' or 'a4paper').
-    # 'papersize': 'letterpaper',
-    # The font size ('10pt', '11pt' or '12pt').
-    # 'pointsize': '10pt',
-    # Additional stuff for the LaTeX preamble.
-    # 'preamble': '',
-    # Latex figure (float) alignment
-    # 'figure_align': 'htbp',
+     # The paper size ('letterpaper' or 'a4paper').
+     #
+     # 'papersize': 'letterpaper',
+
+     # The font size ('10pt', '11pt' or '12pt').
+     #
+     # 'pointsize': '10pt',
+
+     # Additional stuff for the LaTeX preamble.
+     #
+     # 'preamble': '',
+
+     # Latex figure (float) alignment
+     #
+     # 'figure_align': 'htbp',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-    (master_doc, "graphqllib.tex", u"graphqllib Documentation", u"Taeho Kim", "manual")
+    (master_doc, 'GraphQL-core-3.tex', 'GraphQL-core 3 Documentation',
+     'Christoph Zwerschke', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
+#
 # latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
+#
 # latex_use_parts = False
 
 # If true, show page references after internal links.
+#
 # latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
+#
 # latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
+#
 # latex_appendices = []
 
 # If false, no module index is generated.
+#
 # latex_domain_indices = True
 
 
@@ -252,9 +341,13 @@ latex_documents = [
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
-man_pages = [(master_doc, "graphqllib", u"graphqllib Documentation", [author], 1)]
+man_pages = [
+    (master_doc, 'graphql-core', 'GraphQL-core 3 Documentation',
+     [author], 1)
+]
 
 # If true, show URL addresses after external links.
+#
 # man_show_urls = False
 
 
@@ -264,29 +357,23 @@ man_pages = [(master_doc, "graphqllib", u"graphqllib Documentation", [author], 1
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    (
-        master_doc,
-        "graphqllib",
-        u"graphqllib Documentation",
-        author,
-        "graphqllib",
-        "One line description of project.",
-        "Miscellaneous",
-    )
+    (master_doc, 'GraphQL-core', 'GraphQL-core 3 Documentation',
+     author, 'GraphQL-core 3', 'One line description of project.',
+     'Miscellaneous'),
 ]
 
 # Documents to append as an appendix to all manuals.
+#
 # texinfo_appendices = []
 
 # If false, no module index is generated.
+#
 # texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
+#
 # texinfo_show_urls = 'footnote'
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
+#
 # texinfo_no_detailmenu = False
-
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {"https://docs.python.org/": None}
diff --git a/docs/diffs.rst b/docs/diffs.rst
new file mode 100644
index 0000000..0bdae09
--- /dev/null
+++ b/docs/diffs.rst
@@ -0,0 +1,82 @@
+Differences from GraphQL.js
+===========================
+
+The goal of GraphQL-core 3 is to be a faithful replication of `GraphQL.js`_,  the JavaScript reference implementation for GraphQL, in Python 3, and to keep it aligned and up to date with the ongoing development of GraphQL.js. Therefore, we strive to be as compatible as possible to the original JavaScript library, sometimes at the cost of being less Pythonic than other libraries written particularly for Python. We also avoid incorporating additional features that do not exist in the JavaScript library, in order to keep the task of maintaining the Python code and keeping it in line with the JavaScript code manageable. The preferred way of getting new features into GraphQL-core is to propose and discuss them on the `GraphQL.js issue tracker`_ first, try to get them included into GraphQL.js, and from there ported to GraphQL-core.
+
+.. _GraphQL.js: https://github.com/graphql/graphql-js
+.. _GraphQL.js issue tracker: https://github.com/graphql/graphql-js/issues
+.. _Graphene: https://graphene-python.org/
+
+.. currentmodule:: graphql
+
+Having said this, in a few places we allowed the API to be a bit more Pythonic than the direct equivalent would have been. We also added a few features that do not exist in the JavaScript library, mostly to support existing higher level libraries such as Graphene_ and the different naming conventions in Python. The most notable differences are the following:
+
+
+Direct attribute access in GraphQL types
+----------------------------------------
+
+You can access
+
+* the **fields** of GraphQLObjectTypes, GraphQLInterfaceTypes and GraphQLInputObjectTypes,
+* the **interfaces** of GraphQLObjectTypes,
+* the **types** of GraphQLUnionTypes,
+* the **values** of GraphQLEnumTypes and
+* the **query**, **mutation**, **subscription** and **type_map** of GraphQLSchemas
+
+directly as attributes, instead of using getters.
+
+For example, to get the fields of a GraphQLObjectType ``obj``, you write ``obj.fields`` instead of ``obj.getFields()``.
+
+
+Arguments, fields and values are dictionaries
+---------------------------------------------
+
+* The **arguments** of GraphQLDirectives and GraphQLFields,
+* the **fields** of GraphQLObjectTypes, GraphQLInterfaceTypes and GraphQLInputObjectTypes, and
+* the **values** of GraphQLEnumTypes
+
+are always Python dictionaries in GraphQL-core, while they are returned as Arrays in GraphQL.js. Also, the values of these dictionaries do not have ``name`` attributes, since the names are already used as the keys of these dictionaries.
+
+
+Shorthand notation for creating GraphQL types
+---------------------------------------------
+
+The following shorthand notations are possible:
+
+* Where you need to pass a GraphQLArgumentMap, i.e. a dictionary with names as keys and GraphQLArguments as values, you can also pass GraphQLInputTypes as values. The GraphQLInputTypes are then automatically wrapped into GraphQLArguments.
+* Where you need to pass a GraphQLFieldMap, i.e. a dictionary with names as keys and GraphQLFields as values, you can also pass GraphQLOutputTypes as values. The GraphQLOutputTypes are then automatically wrapped into GraphQLFields.
+* Where you need to pass a GraphQLInputFieldMap, i.e. a dictionary with names as keys and GraphQLInputFields as values, you can also pass GraphQLInputTypes as values. The GraphQLInputTypes are then automatically wrapped into GraphQLInputFields.
+* Where you need to pass a GraphQLEnumValueMap, i.e. a dictionary with names as keys and GraphQLEnumValues as values, you can pass any other Python objects as values. These will be automatically wrapped into GraphQLEnumValues. You can also pass a Python Enum type as GraphQLEnumValueMap.
+
+
+Custom output names of arguments and input fields
+-------------------------------------------------
+
+You can pass a custom ``out_name`` argument to :class:`GraphQLArgument` and :class:`GraphQLInputField` that allows using JavaScript naming conventions (camelCase) on ingress and Python naming conventions (snake_case) on egress. This feature is used by Graphene.
+
+
+Custom output types of input object types
+-----------------------------------------
+
+You can also pass a custom ``out_type`` argument to :class:`GraphQLInputObjectType` that allows conversion to any Python type on egress instead of conversion to a dictionary, which is the default. This is used to support the container feature of Graphene InputObjectTypes.
+
+
+Custom middleware
+-----------------
+
+The :func:`execution.execute` function takes an additional ``middleware`` argument which must be a sequence of middleware functions or a :class:`MiddlewareManager` object. This feature is used by Graphene to affect the evaluation of fields using custom middleware. There has been a `request <https://github.com/graphql/graphql-js/issues/1516>`_ to add this to GraphQL.js as well, but so far this feature only exists in GraphQL-core.
+
+
+Custom execution context
+------------------------
+
+The :func:`execution.execute` function takes an additional ``execution_context_class`` argument which allows specifying a custom execution context class instead of the default :class:`ExecutionContext` used by GraphQL-core.
+
+
+Registering special types for descriptions
+------------------------------------------
+
+Normally, descriptions for GraphQL types must be strings. However, sometimes you may want to use other kinds of objects which are not strings, but are only resolved to strings at runtime. This is possible if you register the classes of such objects with :func:`pyutils.register_description`.
+
+
+If you notice any other important differences, please let us know so that they can be either removed or listed here.
diff --git a/docs/index.rst b/docs/index.rst
index 1a3b48b..81102c2 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,20 +1,20 @@
-.. graphql-py documentation master file, created by
-   sphinx-quickstart on Wed Sep 16 20:08:39 2015.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
+Welcome to GraphQL-core 3
+=========================
 
-Welcome to graphql-py's documentation!
-======================================
-
-Contents:
+Contents
+--------
 
 .. toctree::
    :maxdepth: 2
 
+   intro
+   usage/index
+   diffs
+   modules/graphql
 
 
 Indices and tables
-==================
+------------------
 
 * :ref:`genindex`
 * :ref:`modindex`
diff --git a/docs/intro.rst b/docs/intro.rst
new file mode 100644
index 0000000..3bd8383
--- /dev/null
+++ b/docs/intro.rst
@@ -0,0 +1,97 @@
+Introduction
+============
+
+`GraphQL-core-3`_ is a Python port of `GraphQL.js`_,
+the JavaScript reference implementation for GraphQL_,
+a query language for APIs created by Facebook.
+
+`GraphQL`_ consists of three parts:
+
+* A type system that you define
+* A query language that you use to query the API
+* An execution and validation engine
+
+The reference implementation closely follows the `Specification for GraphQL`_
+which consists of the following sections:
+
+* Language_
+* `Type System`_
+* Introspection_
+* Validation_
+* Execution_
+* Response_
+
+This division into subsections is reflected in the :ref:`sub-packages` of
+GraphQL-core 3. Each of these sub-packages implements the aspects specified in
+one of the sections of the specification.
+
+
+Getting started
+---------------
+
+You can install GraphQL-core 3 using pip_::
+
+    pip install "graphql-core>=3"
+
+You can also install GraphQL-core 3 with pipenv_, if you prefer that::
+
+    pipenv install "graphql-core>=3"
+
+Now you can start using GraphQL-core 3 by importing from the top-level
+:mod:`graphql` package. Nearly everything defined in the sub-packages
+can also be imported directly from the top-level package.
+
+.. currentmodule:: graphql
+
+For instance, using the types defined in the :mod:`graphql.type` package,
+you can define a GraphQL schema, like this simple one::
+
+    from graphql import (
+        GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)
+
+    schema = GraphQLSchema(
+        query=GraphQLObjectType(
+            name='RootQueryType',
+            fields={
+                'hello': GraphQLField(
+                    GraphQLString,
+                    resolve=lambda obj, info: 'world')
+            }))
+
+The :mod:`graphql.execution` package implements the mechanism for executing
+GraphQL queries. The top-level :func:`graphql` and :func:`graphql_sync`
+functions also parse and validate queries using the :mod:`graphql.language`
+and :mod:`graphql.validation` modules.
+
+So to validate and execute a query against our simple schema, you can do::
+
+    from graphql import graphql_sync
+
+    query = '{ hello }'
+
+    print(graphql_sync(schema, query))
+
+This will yield the following output::
+
+    ExecutionResult(data={'hello': 'world'}, errors=None)
+
+
+Reporting Issues and Contributing
+---------------------------------
+
+Please visit the `GitHub repository of GraphQL-core 3`_ if you're interested
+in the current development or want to report issues or send pull requests.
+
+.. _GraphQL: https://graphql.org/
+.. _GraphQL.js: https://github.com/graphql/graphql-js
+.. _GraphQL-core-3: https://github.com/graphql-python/graphql-core
+.. _GitHub repository of GraphQL-core 3: https://github.com/graphql-python/graphql-core
+.. _Specification for GraphQL: https://facebook.github.io/graphql/
+.. _Language: https://facebook.github.io/graphql/draft/#sec-Language
+.. _Type System: https://facebook.github.io/graphql/draft/#sec-Type-System
+.. _Introspection: https://facebook.github.io/graphql/draft/#sec-Introspection
+.. _Validation: https://facebook.github.io/graphql/draft/#sec-Validation
+.. _Execution: https://facebook.github.io/graphql/draft/#sec-Execution
+.. _Response: https://facebook.github.io/graphql/draft/#sec-Response
+.. _pip: https://pip.pypa.io/
+.. _pipenv: https://github.com/pypa/pipenv
diff --git a/docs/make.bat b/docs/make.bat
index 578edde..922152e 100644
--- a/docs/make.bat
+++ b/docs/make.bat
@@ -1,263 +1,35 @@
-@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=_build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
-set I18NSPHINXOPTS=%SPHINXOPTS% .
-if NOT "%PAPER%" == "" (
-	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
-	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
-)
-
-if "%1" == "" goto help
-
-if "%1" == "help" (
-	:help
-	echo.Please use `make ^<target^>` where ^<target^> is one of
-	echo.  html       to make standalone HTML files
-	echo.  dirhtml    to make HTML files named index.html in directories
-	echo.  singlehtml to make a single large HTML file
-	echo.  pickle     to make pickle files
-	echo.  json       to make JSON files
-	echo.  htmlhelp   to make HTML files and a HTML help project
-	echo.  qthelp     to make HTML files and a qthelp project
-	echo.  devhelp    to make HTML files and a Devhelp project
-	echo.  epub       to make an epub
-	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
-	echo.  text       to make text files
-	echo.  man        to make manual pages
-	echo.  texinfo    to make Texinfo files
-	echo.  gettext    to make PO message catalogs
-	echo.  changes    to make an overview over all changed/added/deprecated items
-	echo.  xml        to make Docutils-native XML files
-	echo.  pseudoxml  to make pseudoxml-XML files for display purposes
-	echo.  linkcheck  to check all external links for integrity
-	echo.  doctest    to run all doctests embedded in the documentation if enabled
-	echo.  coverage   to run coverage check of the documentation if enabled
-	goto end
-)
-
-if "%1" == "clean" (
-	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
-	del /q /s %BUILDDIR%\*
-	goto end
-)
-
-
-REM Check if sphinx-build is available and fallback to Python version if any
-%SPHINXBUILD% 2> nul
-if errorlevel 9009 goto sphinx_python
-goto sphinx_ok
-
-:sphinx_python
-
-set SPHINXBUILD=python -m sphinx.__init__
-%SPHINXBUILD% 2> nul
-if errorlevel 9009 (
-	echo.
-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-	echo.installed, then set the SPHINXBUILD environment variable to point
-	echo.to the full path of the 'sphinx-build' executable. Alternatively you
-	echo.may add the Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.http://sphinx-doc.org/
-	exit /b 1
-)
-
-:sphinx_ok
-
-
-if "%1" == "html" (
-	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
-	goto end
-)
-
-if "%1" == "dirhtml" (
-	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
-	goto end
-)
-
-if "%1" == "singlehtml" (
-	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
-	goto end
-)
-
-if "%1" == "pickle" (
-	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can process the pickle files.
-	goto end
-)
-
-if "%1" == "json" (
-	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can process the JSON files.
-	goto end
-)
-
-if "%1" == "htmlhelp" (
-	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %BUILDDIR%/htmlhelp.
-	goto end
-)
-
-if "%1" == "qthelp" (
-	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %BUILDDIR%/qthelp, like this:
-	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\graphql-py.qhcp
-	echo.To view the help file:
-	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\graphql-py.ghc
-	goto end
-)
-
-if "%1" == "devhelp" (
-	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished.
-	goto end
-)
-
-if "%1" == "epub" (
-	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The epub file is in %BUILDDIR%/epub.
-	goto end
-)
-
-if "%1" == "latex" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "latexpdf" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	cd %BUILDDIR%/latex
-	make all-pdf
-	cd %~dp0
-	echo.
-	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "latexpdfja" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	cd %BUILDDIR%/latex
-	make all-pdf-ja
-	cd %~dp0
-	echo.
-	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "text" (
-	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The text files are in %BUILDDIR%/text.
-	goto end
-)
-
-if "%1" == "man" (
-	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The manual pages are in %BUILDDIR%/man.
-	goto end
-)
-
-if "%1" == "texinfo" (
-	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
-	goto end
-)
-
-if "%1" == "gettext" (
-	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
-	goto end
-)
-
-if "%1" == "changes" (
-	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.The overview file is in %BUILDDIR%/changes.
-	goto end
-)
-
-if "%1" == "linkcheck" (
-	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Link check complete; look for any errors in the above output ^
-or in %BUILDDIR%/linkcheck/output.txt.
-	goto end
-)
-
-if "%1" == "doctest" (
-	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Testing of doctests in the sources finished, look at the ^
-results in %BUILDDIR%/doctest/output.txt.
-	goto end
-)
-
-if "%1" == "coverage" (
-	%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Testing of coverage in the sources finished, look at the ^
-results in %BUILDDIR%/coverage/python.txt.
-	goto end
-)
-
-if "%1" == "xml" (
-	%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The XML files are in %BUILDDIR%/xml.
-	goto end
-)
-
-if "%1" == "pseudoxml" (
-	%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
-	goto end
-)
-
-:end
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/modules/error.rst b/docs/modules/error.rst
new file mode 100644
index 0000000..ef51316
--- /dev/null
+++ b/docs/modules/error.rst
@@ -0,0 +1,15 @@
+Error
+=====
+
+.. currentmodule:: graphql.error
+
+.. automodule:: graphql.error
+
+.. autoexception:: GraphQLError
+   :members:
+
+.. autoexception:: GraphQLSyntaxError
+
+.. autofunction:: format_error
+.. autofunction:: located_error
+.. autofunction:: print_error
diff --git a/docs/modules/execution.rst b/docs/modules/execution.rst
new file mode 100644
index 0000000..6565b0b
--- /dev/null
+++ b/docs/modules/execution.rst
@@ -0,0 +1,15 @@
+Execution
+=========
+
+.. currentmodule:: graphql.execution
+
+.. automodule:: graphql.execution
+
+.. autofunction:: execute
+.. autofunction:: default_field_resolver
+
+.. autoclass:: ExecutionContext
+.. autoclass:: ExecutionResult
+
+.. autofunction:: get_directive_values
+
diff --git a/docs/modules/graphql.rst b/docs/modules/graphql.rst
new file mode 100644
index 0000000..2109e44
--- /dev/null
+++ b/docs/modules/graphql.rst
@@ -0,0 +1,31 @@
+Reference
+=========
+
+.. currentmodule:: graphql
+
+.. automodule:: graphql
+
+.. _top-level-functions:
+
+Top-Level Functions
+-------------------
+
+.. autofunction:: graphql
+.. autofunction:: graphql_sync
+
+.. _sub-packages:
+
+Sub-Packages
+------------
+
+.. toctree::
+   :maxdepth: 1
+
+   error
+   execution
+   language
+   pyutils
+   subscription
+   type
+   utilities
+   validation
diff --git a/docs/modules/language.rst b/docs/modules/language.rst
new file mode 100644
index 0000000..ef649d6
--- /dev/null
+++ b/docs/modules/language.rst
@@ -0,0 +1,123 @@
+Language
+========
+
+.. automodule:: graphql.language
+
+AST
+---
+
+.. autoclass:: Location
+.. autoclass:: Node
+
+Each kind of AST node has its own class:
+
+.. autoclass:: ArgumentNode
+.. autoclass:: BooleanValueNode
+.. autoclass:: DefinitionNode
+.. autoclass:: DirectiveDefinitionNode
+.. autoclass:: DirectiveNode
+.. autoclass:: DocumentNode
+.. autoclass:: EnumTypeDefinitionNode
+.. autoclass:: EnumTypeExtensionNode
+.. autoclass:: EnumValueDefinitionNode
+.. autoclass:: EnumValueNode
+.. autoclass:: ExecutableDefinitionNode
+.. autoclass:: FieldDefinitionNode
+.. autoclass:: FieldNode
+.. autoclass:: FloatValueNode
+.. autoclass:: FragmentDefinitionNode
+.. autoclass:: FragmentSpreadNode
+.. autoclass:: InlineFragmentNode
+.. autoclass:: InputObjectTypeDefinitionNode
+.. autoclass:: InputObjectTypeExtensionNode
+.. autoclass:: InputValueDefinitionNode
+.. autoclass:: IntValueNode
+.. autoclass:: InterfaceTypeDefinitionNode
+.. autoclass:: InterfaceTypeExtensionNode
+.. autoclass:: ListTypeNode
+.. autoclass:: ListValueNode
+.. autoclass:: NameNode
+.. autoclass:: NamedTypeNode
+.. autoclass:: NonNullTypeNode
+.. autoclass:: NullValueNode
+.. autoclass:: ObjectFieldNode
+.. autoclass:: ObjectTypeDefinitionNode
+.. autoclass:: ObjectTypeExtensionNode
+.. autoclass:: ObjectValueNode
+.. autoclass:: OperationDefinitionNode
+.. autoclass:: OperationType
+.. autoclass:: OperationTypeDefinitionNode
+.. autoclass:: ScalarTypeDefinitionNode
+.. autoclass:: ScalarTypeExtensionNode
+.. autoclass:: SchemaDefinitionNode
+.. autoclass:: SchemaExtensionNode
+.. autoclass:: SelectionNode
+.. autoclass:: SelectionSetNode
+.. autoclass:: StringValueNode
+.. autoclass:: TypeDefinitionNode
+.. autoclass:: TypeExtensionNode
+.. autoclass:: TypeNode
+.. autoclass:: TypeSystemDefinitionNode
+.. autoclass:: TypeSystemExtensionNode
+.. autoclass:: UnionTypeDefinitionNode
+.. autoclass:: UnionTypeExtensionNode
+.. autoclass:: ValueNode
+.. autoclass:: VariableDefinitionNode
+.. autoclass:: VariableNode
+
+Lexer
+-----
+
+.. autoclass:: Lexer
+.. autoclass:: TokenKind
+.. autoclass:: Token
+
+Location
+--------
+
+.. autofunction:: get_location
+.. autoclass:: SourceLocation
+.. autofunction:: print_location
+
+Parser
+------
+
+.. autofunction:: parse
+.. autofunction:: parse_type
+.. autofunction:: parse_value
+
+Source
+------
+
+.. autoclass:: Source
+.. autofunction:: print_source_location
+
+Visitor
+-------
+
+.. autofunction:: visit
+.. autoclass:: Visitor
+.. autoclass:: ParallelVisitor
+
+The module also exports the following special symbols which can be used as
+return values in the :class:`Visitor` methods to signal particular actions:
+
+.. data:: BREAK
+   :annotation: (same as ``True``)
+
+   This return value signals that no further nodes shall be visited.
+
+.. data:: SKIP
+   :annotation: (same as ``False``)
+
+   This return value signals that the current node shall be skipped.
+
+.. data:: REMOVE
+   :annotation: (same as``Ellipsis``)
+
+   This return value signals that the current node shall be deleted.
+
+.. data:: IDLE
+   :annotation: = None
+
+   This return value signals that no additional action shall take place.
diff --git a/docs/modules/pyutils.rst b/docs/modules/pyutils.rst
new file mode 100644
index 0000000..b11d6ee
--- /dev/null
+++ b/docs/modules/pyutils.rst
@@ -0,0 +1,32 @@
+PyUtils
+=======
+
+.. currentmodule:: graphql.pyutils
+
+.. automodule:: graphql.pyutils
+
+.. autofunction:: camel_to_snake
+.. autofunction:: snake_to_camel
+.. autofunction:: cached_property
+.. autofunction:: did_you_mean
+.. autofunction:: register_description
+.. autofunction:: unregister_description
+.. autoclass:: EventEmitter
+   :members:
+.. autoclass:: EventEmitterAsyncIterator
+   :members:
+.. autofunction:: identity_func
+.. autofunction:: inspect
+.. autofunction:: is_finite
+.. autofunction:: is_integer
+.. autoclass:: AwaitableOrValue
+   :members:
+.. autofunction:: suggestion_list
+.. autoclass:: FrozenError
+.. autoclass:: FrozenList
+.. autoclass:: FrozenDict
+.. autoclass:: Path
+   :members:
+.. autofunction:: print_path_list
+
+.. autodata:: Undefined
diff --git a/docs/modules/subscription.rst b/docs/modules/subscription.rst
new file mode 100644
index 0000000..2dfc4a1
--- /dev/null
+++ b/docs/modules/subscription.rst
@@ -0,0 +1,10 @@
+Subscription
+============
+
+.. currentmodule:: graphql.subscription
+
+.. automodule:: graphql.subscription
+
+.. autofunction:: subscribe
+.. autofunction:: create_source_event_stream
+
diff --git a/docs/modules/type.rst b/docs/modules/type.rst
new file mode 100644
index 0000000..91ed899
--- /dev/null
+++ b/docs/modules/type.rst
@@ -0,0 +1,195 @@
+Type
+====
+
+.. currentmodule:: graphql.type
+
+.. automodule:: graphql.type
+
+
+Definition
+----------
+
+Predicates
+^^^^^^^^^^
+
+.. autofunction:: is_composite_type
+.. autofunction:: is_enum_type
+.. autofunction:: is_input_object_type
+.. autofunction:: is_input_type
+.. autofunction:: is_interface_type
+.. autofunction:: is_leaf_type
+.. autofunction:: is_list_type
+.. autofunction:: is_named_type
+.. autofunction:: is_non_null_type
+.. autofunction:: is_nullable_type
+.. autofunction:: is_object_type
+.. autofunction:: is_output_type
+.. autofunction:: is_scalar_type
+.. autofunction:: is_type
+.. autofunction:: is_union_type
+.. autofunction:: is_wrapping_type
+
+Assertions
+^^^^^^^^^^
+
+.. autofunction:: assert_abstract_type
+.. autofunction:: assert_composite_type
+.. autofunction:: assert_enum_type
+.. autofunction:: assert_input_object_type
+.. autofunction:: assert_input_type
+.. autofunction:: assert_interface_type
+.. autofunction:: assert_leaf_type
+.. autofunction:: assert_list_type
+.. autofunction:: assert_named_type
+.. autofunction:: assert_non_null_type
+.. autofunction:: assert_nullable_type
+.. autofunction:: assert_object_type
+.. autofunction:: assert_output_type
+.. autofunction:: assert_scalar_type
+.. autofunction:: assert_type
+.. autofunction:: assert_union_type
+.. autofunction:: assert_wrapping_type
+
+Un-modifiers
+^^^^^^^^^^^^
+
+.. autofunction:: get_nullable_type
+.. autofunction:: get_named_type
+
+Definitions
+^^^^^^^^^^^
+.. autoclass:: GraphQLEnumType
+.. autoclass:: GraphQLInputObjectType
+.. autoclass:: GraphQLInterfaceType
+.. autoclass:: GraphQLObjectType
+.. autoclass:: GraphQLScalarType
+.. autoclass:: GraphQLUnionType
+
+Type Wrappers
+^^^^^^^^^^^^^
+
+.. autoclass:: GraphQLList
+.. autoclass:: GraphQLNonNull
+
+Types
+^^^^^
+.. autoclass:: GraphQLAbstractType
+.. autoclass:: GraphQLArgument
+.. autoclass:: GraphQLArgumentMap
+.. autoclass:: GraphQLCompositeType
+.. autoclass:: GraphQLEnumValue
+.. autoclass:: GraphQLEnumValueMap
+.. autoclass:: GraphQLField
+.. autoclass:: GraphQLFieldMap
+.. autoclass:: GraphQLInputField
+.. autoclass:: GraphQLInputFieldMap
+.. autoclass:: GraphQLInputType
+.. autoclass:: GraphQLLeafType
+.. autoclass:: GraphQLNamedType
+.. autoclass:: GraphQLNullableType
+.. autoclass:: GraphQLOutputType
+.. autoclass:: GraphQLType
+.. autoclass:: GraphQLWrappingType
+
+.. autoclass:: Thunk
+
+Resolvers
+^^^^^^^^^
+
+.. autoclass:: GraphQLFieldResolver
+.. autoclass:: GraphQLIsTypeOfFn
+.. autoclass:: GraphQLResolveInfo
+.. autoclass:: GraphQLTypeResolver
+
+
+Directives
+----------
+
+Predicates
+^^^^^^^^^^
+
+.. autofunction:: is_directive
+.. autofunction:: is_specified_directive
+
+Definitions
+^^^^^^^^^^^
+
+.. autoclass:: GraphQLDirective
+.. autoclass:: GraphQLIncludeDirective
+.. autoclass:: GraphQLSkipDirective
+.. autoclass:: GraphQLDeprecatedDirective
+
+.. autodata:: specified_directives
+
+.. data:: DEFAULT_DEPRECATION_REASON
+   :annotation: = 'No longer supported'
+
+   String constant that can be used as the default value for ``deprecation_reason``.
+
+
+Introspection
+-------------
+
+Predicates
+^^^^^^^^^^
+
+.. autofunction:: is_introspection_type
+
+Definitions
+^^^^^^^^^^^
+
+.. autoclass:: TypeKind
+.. autoclass:: TypeMetaFieldDef
+.. autoclass:: TypeNameMetaFieldDef
+.. autoclass:: SchemaMetaFieldDef
+
+.. autodata:: introspection_types
+
+
+Scalars
+-------
+
+Predicates
+^^^^^^^^^^
+
+.. autofunction:: is_specified_scalar_type
+
+Definitions
+^^^^^^^^^^^
+
+.. autoclass:: GraphQLBoolean
+.. autoclass:: GraphQLFloat
+.. autoclass:: GraphQLID
+.. autoclass:: GraphQLInt
+.. autoclass:: GraphQLString
+
+The list of all specified directives is available as
+:data:`specified_directives`.
+
+
+Schema
+------
+
+Predicates
+^^^^^^^^^^
+
+.. autofunction:: is_schema
+
+Definitions
+^^^^^^^^^^^
+
+.. autoclass:: GraphQLSchema
+
+
+Validate
+--------
+
+Functions:
+^^^^^^^^^^
+
+.. autofunction:: validate_schema
+
+Assertions
+^^^^^^^^^^
+
+.. autofunction:: assert_valid_schema
diff --git a/docs/modules/utilities.rst b/docs/modules/utilities.rst
new file mode 100644
index 0000000..bb0ae33
--- /dev/null
+++ b/docs/modules/utilities.rst
@@ -0,0 +1,110 @@
+Utilities
+=========
+
+.. currentmodule:: graphql.utilities
+
+.. automodule:: graphql.utilities
+
+The GraphQL query recommended for a full schema introspection:
+
+.. autofunction:: get_introspection_query
+
+Get the target Operation from a Document:
+
+.. autofunction:: get_operation_ast
+
+Get the Type for the target Operation AST:
+
+.. autofunction:: get_operation_root_type
+
+Convert a GraphQLSchema to an IntrospectionQuery:
+
+.. autofunction:: introspection_from_schema
+
+Build a GraphQLSchema from an introspection result:
+
+.. autofunction:: build_client_schema
+
+Build a GraphQLSchema from GraphQL Schema language:
+
+.. autofunction:: build_ast_schema
+.. autofunction:: build_schema
+
+Extend an existing GraphQLSchema from a parsed GraphQL Schema language AST:
+
+.. autofunction:: extend_schema
+
+Sort a GraphQLSchema:
+
+.. autofunction:: lexicographic_sort_schema
+
+Print a GraphQLSchema to GraphQL Schema language:
+
+.. autofunction:: print_introspection_schema
+.. autofunction:: print_schema
+.. autofunction:: print_type
+.. autofunction:: print_value
+
+Create a GraphQLType from a GraphQL language AST:
+
+.. autofunction:: type_from_ast
+
+Create a Python value from a GraphQL language AST with a type:
+
+.. autofunction:: value_from_ast
+
+Create a Python value from a GraphQL language AST without a type:
+
+.. autofunction:: value_from_ast_untyped
+
+Create a GraphQL language AST from a Python value:
+
+.. autofunction:: ast_from_value
+
+A helper to use within recursive-descent visitors which need to be aware of the GraphQL
+type system:
+
+.. autoclass:: TypeInfo
+.. autoclass:: TypeInfoVisitor
+
+Coerce a Python value to a GraphQL type, or produce errors:
+
+.. autofunction:: coerce_input_value
+
+Concatenate multiple ASTs together:
+
+.. autofunction:: concat_ast
+
+Separate an AST into an AST per Operation:
+
+.. autofunction:: separate_operations
+
+Strip characters that are not significant to the validity or execution
+of a GraphQL document:
+
+.. autofunction:: strip_ignored_characters
+
+Comparators for types:
+
+.. autofunction:: is_equal_type
+.. autofunction:: is_type_sub_type_of
+.. autofunction:: do_types_overlap
+
+Assert that a string is a valid GraphQL name:
+
+.. autofunction:: assert_valid_name
+.. autofunction:: is_valid_name_error
+
+Compare two GraphQLSchemas and detect breaking changes:
+
+.. autofunction:: find_breaking_changes
+.. autofunction:: find_dangerous_changes
+
+.. autoclass:: BreakingChange
+.. autoclass:: BreakingChangeType
+.. autoclass:: DangerousChange
+.. autoclass:: DangerousChangeType
+
+Report all deprecated usages within a GraphQL document:
+
+.. autofunction:: find_deprecated_usages
diff --git a/docs/modules/validation.rst b/docs/modules/validation.rst
new file mode 100644
index 0000000..7dbb836
--- /dev/null
+++ b/docs/modules/validation.rst
@@ -0,0 +1,145 @@
+Validation
+==========
+
+.. currentmodule:: graphql.validation
+
+.. automodule:: graphql.validation
+
+.. autofunction:: validate
+
+.. autoclass:: ASTValidationContext
+
+.. autoclass:: ASTValidationRule
+
+.. autoclass:: SDLValidationContext
+
+.. autoclass:: SDLValidationRule
+
+.. autoclass:: ValidationContext
+
+.. autoclass:: ValidationRule
+
+
+Rules
+-----
+
+This list includes all validation rules defined by the GraphQL spec. The order of the
+rules in this list has been adjusted to lead to the most clear output when encountering
+multiple validation errors:
+
+.. autodata:: specified_rules
+   :annotation: = FrozenList([...])
+
+Spec Section: "Executable Definitions"
+
+.. autoclass:: ExecutableDefinitionsRule
+
+Spec Section: "Field Selections on Objects, Interfaces, and Unions Types"
+
+.. autoclass:: FieldsOnCorrectTypeRule
+
+Spec Section: "Fragments on Composite Types"
+
+.. autoclass:: FragmentsOnCompositeTypesRule
+
+Spec Section: "Argument Names"
+
+.. autoclass:: KnownArgumentNamesRule
+
+Spec Section: "Directives Are Defined"
+
+.. autoclass:: KnownDirectivesRule
+
+Spec Section: "Fragment spread target defined"
+
+.. autoclass:: KnownFragmentNamesRule
+
+Spec Section: "Fragment Spread Type Existence"
+
+.. autoclass:: KnownTypeNamesRule
+
+Spec Section: "Lone Anonymous Operation"
+
+.. autoclass:: LoneAnonymousOperationRule
+
+Spec Section: "Fragments must not form cycles"
+
+.. autoclass:: NoFragmentCyclesRule
+
+Spec Section: "All Variable Used Defined"
+
+.. autoclass:: NoUndefinedVariablesRule
+
+Spec Section: "Fragments must be used"
+
+.. autoclass:: NoUnusedFragmentsRule
+
+Spec Section: "All Variables Used"
+
+.. autoclass:: NoUnusedVariablesRule
+
+Spec Section: "Field Selection Merging"
+
+.. autoclass:: OverlappingFieldsCanBeMergedRule
+
+Spec Section: "Fragment spread is possible"
+
+.. autoclass:: PossibleFragmentSpreadsRule
+
+Spec Section: "Argument Optionality"
+
+.. autoclass:: ProvidedRequiredArgumentsRule
+
+Spec Section: "Leaf Field Selections"
+
+.. autoclass:: ScalarLeafsRule
+
+Spec Section: "Subscriptions with Single Root Field"
+
+.. autoclass:: SingleFieldSubscriptionsRule
+
+Spec Section: "Argument Uniqueness"
+
+.. autoclass:: UniqueArgumentNamesRule
+
+Spec Section: "Directives Are Unique Per Location"
+
+.. autoclass:: UniqueDirectivesPerLocationRule
+
+Spec Section: "Fragment Name Uniqueness"
+
+.. autoclass:: UniqueFragmentNamesRule
+
+Spec Section: "Input Object Field Uniqueness"
+
+.. autoclass:: UniqueInputFieldNamesRule
+
+Spec Section: "Operation Name Uniqueness"
+
+.. autoclass:: UniqueOperationNamesRule
+
+Spec Section: "Variable Uniqueness"
+
+.. autoclass:: UniqueVariableNamesRule
+
+Spec Section: "Value Type Correctness"
+
+.. autoclass:: ValuesOfCorrectTypeRule
+
+Spec Section: "Variables are Input Types"
+
+.. autoclass:: VariablesAreInputTypesRule
+
+Spec Section: "All Variable Usages Are Allowed"
+
+.. autoclass:: VariablesInAllowedPositionRule
+
+SDL-specific validation rules
+
+.. autoclass:: LoneSchemaDefinitionRule
+.. autoclass:: UniqueOperationTypesRule
+.. autoclass:: UniqueTypeNamesRule
+.. autoclass:: UniqueEnumValueNamesRule
+.. autoclass:: UniqueFieldDefinitionNamesRule
+.. autoclass:: UniqueDirectiveNamesRule
+.. autoclass:: PossibleTypeExtensionsRule
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..c559370
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,2 @@
+sphinx>=2.2,<3
+sphinx_rtd_theme>=0.4
\ No newline at end of file
diff --git a/docs/usage/extension.rst b/docs/usage/extension.rst
new file mode 100644
index 0000000..4d6c49b
--- /dev/null
+++ b/docs/usage/extension.rst
@@ -0,0 +1,49 @@
+Extending a Schema
+------------------
+
+With GraphQL-core 3 you can also extend a given schema using type extensions. For
+example, we might want to add a ``lastName`` property to our ``Human`` data type to
+retrieve only the last name of the person.
+
+This can be achieved with the :func:`graphql.utilities.extend_schema` function as
+follows::
+
+    from graphql import extend_schema, parse
+
+    schema = extend_schema(schema, parse("""
+        extend type Human {
+         lastName: String
+        }
+        """))
+
+Note that this function expects the extensions as an AST, which we can get using the
+:func:`graphql.language.parse` function. Also note that the :func:`~graphql.extend_schema` function
+does not alter the original schema, but returns a new schema object.
+
+We also need to attach a resolver function to the new field::
+
+    def get_last_name(human, info):
+        return human['name'].rsplit(None, 1)[-1]
+
+    schema.get_type('Human').fields['lastName'].resolve = get_last_name
+
+Now we can query only the last name of a human::
+
+    from graphql import graphql_sync
+
+    result = graphql_sync(schema, """
+        {
+          human(id: "1000") {
+            lastName
+            homePlanet
+          }
+        }
+        """)
+    print(result)
+
+This query will give the following result::
+
+    ExecutionResult(
+        data={'human': {'lastName': 'Skywalker', 'homePlanet': 'Tatooine'}},
+        errors=None)
+
diff --git a/docs/usage/index.rst b/docs/usage/index.rst
new file mode 100644
index 0000000..11af8af
--- /dev/null
+++ b/docs/usage/index.rst
@@ -0,0 +1,19 @@
+Usage
+=====
+
+GraphQL-core provides two important capabilities: building a type schema, and serving
+queries against that type schema.
+
+.. toctree::
+   :maxdepth: 2
+
+   schema
+   resolvers
+   queries
+   sdl
+   methods
+   introspection
+   parser
+   extension
+   validator
+   other
diff --git a/docs/usage/introspection.rst b/docs/usage/introspection.rst
new file mode 100644
index 0000000..095ce5e
--- /dev/null
+++ b/docs/usage/introspection.rst
@@ -0,0 +1,63 @@
+Using an Introspection Query
+----------------------------
+
+A third way of building a schema is using an introspection query on an existing server.
+This is what GraphiQL uses to get information about the schema on the remote server. You
+can create an introspection query using GraphQL-core 3 with::
+
+    from graphql import get_introspection_query
+
+    query = get_introspection_query(descriptions=True)
+
+This will also yield the descriptions of the introspected schema fields. You can also
+create a query that omits the descriptions with::
+
+    query = get_introspection_query(descriptions=False)
+
+In practice you would run this query against a remote server, but we can also run it
+against the schema we have just built above::
+
+    from graphql import graphql_sync
+
+    introspection_query_result = graphql_sync(schema, query)
+
+The ``data`` attribute of the introspection query result now gives us a dictionary,
+which constitutes a third way of describing a GraphQL schema::
+
+    {'__schema': {
+        'queryType': {'name': 'Query'},
+        'mutationType': None, 'subscriptionType': None,
+        'types': [
+            {'kind': 'OBJECT', 'name': 'Query', 'description': None,
+             'fields': [{
+                'name': 'hero', 'description': None,
+                'args': [{'name': 'episode', 'description': ... }],
+                ... }, ... ], ... },
+            ... ],
+        ... }
+    }
+
+This result contains all the information that is available in the SDL description of the
+schema, i.e. it does not contain the resolve functions and information on the
+server-side values of the enum types.
+
+You can convert the introspection result into ``GraphQLSchema`` with GraphQL-core 3 by
+using the :func:`graphql.utilities.build_client_schema` function::
+
+    from graphql import build_client_schema
+
+    client_schema = build_client_schema(introspection_query_result.data)
+
+
+It is also possible to convert the result to SDL with GraphQL-core 3 by using the
+:func:`graphql.utilities.print_schema` function::
+
+    from graphql import print_schema
+
+    sdl = print_schema(client_schema)
+    print(sdl)
+
+This prints the SDL representation of the schema that we started with.
+
+As you see, it is easy to convert between the three forms of representing a GraphQL
+schema in GraphQL-core 3.
diff --git a/docs/usage/methods.rst b/docs/usage/methods.rst
new file mode 100644
index 0000000..64f8e30
--- /dev/null
+++ b/docs/usage/methods.rst
@@ -0,0 +1,57 @@
+Using resolver methods
+----------------------
+
+Above we have attached resolver functions to the schema only. However, it is also
+possible to define resolver methods on the resolved objects, starting with the
+``root_value`` object that you can pass to the :func:`graphql.graphql` function when
+executing a query.
+
+In our case, we could create a ``Root`` class with three methods as root resolvers, like
+so::
+
+    class Root:
+        """The root resolvers"""
+
+        def hero(self, info, episode):
+            return luke if episode == 5 else artoo
+
+        def human(self, info, id):
+            return human_data.get(id)
+
+        def droid(self, info, id):
+            return droid_data.get(id)
+
+
+Since we have defined synchronous methods only, we will use the
+:func:`graphql.graphql_sync` function to execute a query, passing a ``Root()`` object as
+the ``root_value``::
+
+    from graphql import graphql_sync
+
+    result = graphql_sync(schema, """
+        {
+          droid(id: "2001") {
+            name
+            primaryFunction
+          }
+        }
+        """, Root())
+    print(result)
+
+Even if we haven't attached a resolver to the ``hero`` field as we did above, this would
+now still resolve and give the following output::
+
+    ExecutionResult(
+        data={'droid': {'name': 'R2-D2', 'primaryFunction': 'Astromech'}},
+        errors=None)
+
+Of course you can also define asynchronous methods as resolvers, and execute queries
+asynchronously with :func:`graphql.graphql`.
+
+In a similar vein, you can also attach resolvers as methods to the resolved objects on
+deeper levels than the root of the query. In that case, instead of resolving to
+dictionaries with keys for all the fields, as we did above, you would resolve to objects
+with attributes for all the fields. For instance, you would define a class ``Human``
+with a method ``friends()`` for resolving the friends of a human. You can also make
+use of inheritance in this case. The ``Human`` class and a ``Droid`` class could inherit
+from a ``Character`` class and use its methods as resolvers for common fields.
diff --git a/docs/usage/other.rst b/docs/usage/other.rst
new file mode 100644
index 0000000..fc58b3c
--- /dev/null
+++ b/docs/usage/other.rst
@@ -0,0 +1,25 @@
+Subscriptions
+-------------
+
+.. currentmodule:: graphql.subscription
+
+Sometimes you need to not only query data from a server, but you also want to push data
+from the server to the client. GraphQL-core 3 has you also covered here, because it
+implements the "Subscribe" algorithm described in the GraphQL spec. To execute a GraphQL
+subscription, you must use the :func:`subscribe` method from the
+:mod:`graphql.subscription` module. Instead of a single ``ExecutionResult``, this
+function returns an asynchronous iterator yielding a stream of those, unless there was
+an immediate error. Of course you will then also need to maintain a persistent channel
+to the client (often realized via WebSockets) to push these results back.
+
+
+Other Usages
+------------
+
+GraphQL-core 3 provides many more low-level functions that can be used to work with
+GraphQL schemas and queries. We encourage you to explore the contents of the various
+:ref:`sub-packages`, particularly :mod:`graphql.utilities`, and to look into the source
+code and tests of `GraphQL-core 3`_ in order to find all the functionality that is
+provided and understand it in detail.
+
+.. _GraphQL-core 3: https://github.com/graphql-python/graphql-core
diff --git a/docs/usage/parser.rst b/docs/usage/parser.rst
new file mode 100644
index 0000000..8335d7c
--- /dev/null
+++ b/docs/usage/parser.rst
@@ -0,0 +1,74 @@
+Parsing GraphQL Queries and Schema Notation
+-------------------------------------------
+
+.. currentmodule:: graphql.language
+
+When executing GraphQL queries, the first step that happens under the hood is parsing
+the query. But GraphQL-core 3 also exposes the parser for direct usage via the
+:func:`graphql.language.parse` function. When you pass this function a GraphQL source
+code, it will be parsed and returned as a Document, i.e. an abstract syntax tree (AST)
+of :class:`graphql.language.Node` objects. The root node will be a
+:class:`graphql.language.DocumentNode`, with child nodes of different kinds
+corresponding to the GraphQL source. The nodes also carry information on the location in
+the source code that they correspond to.
+
+Here is an example::
+
+    from graphql import parse
+
+    document = parse("""
+        type Query {
+          me: User
+        }
+
+        type User {
+          id: ID
+          name: String
+        }
+    """)
+
+You can also leave out the information on the location in the source code when creating
+the AST document::
+
+    document = parse(..., no_location=True)
+
+This will give the same result as manually creating the AST document::
+
+    from graphql.language.ast import *
+
+    document = DocumentNode(definitions=[
+        ObjectTypeDefinitionNode(
+            name=NameNode(value='Query'),
+            fields=[
+                FieldDefinitionNode(
+                    name=NameNode(value='me'),
+                    type=NamedTypeNode(name=NameNode(value='User')),
+                    arguments=[], directives=[])
+                ], directives=[], interfaces=[]),
+        ObjectTypeDefinitionNode(
+            name=NameNode(value='User'),
+            fields=[
+                FieldDefinitionNode(
+                    name=NameNode(value='id'),
+                    type=NamedTypeNode(
+                        name=NameNode(value='ID')),
+                    arguments=[], directives=[]),
+                FieldDefinitionNode(
+                    name=NameNode(value='name'),
+                    type=NamedTypeNode(
+                        name=NameNode(value='String')),
+                    arguments=[], directives=[]),
+                ], directives=[], interfaces=[]),
+        ])
+
+
+When parsing with ``no_location=False`` (the default), the AST nodes will also have a
+``loc`` attribute carrying the information on the source code location corresponding
+to the AST nodes.
+
+When there is a syntax error in the GraphQL source code, then the :func:`parse` function
+will raise a :exc:`graphql.error.GraphQLSyntaxError`.
+
+The parser can not only be used to parse GraphQL queries, but also to parse the GraphQL
+schema definition language. This will result in another way of representing a GraphQL
+schema, as an AST document.
diff --git a/docs/usage/queries.rst b/docs/usage/queries.rst
new file mode 100644
index 0000000..623fd25
--- /dev/null
+++ b/docs/usage/queries.rst
@@ -0,0 +1,129 @@
+Executing Queries
+-----------------
+
+.. currentmodule:: graphql.execution
+
+Now that we have defined the schema and breathed life into it with our resolver
+functions, we can execute arbitrary query against the schema.
+
+The :mod:`graphql` package provides the :func:`graphql.graphql` function to execute
+queries. This is the main feature of GraphQL-core.
+
+Note however that this function is actually a coroutine intended to be used in
+asynchronous code running in an event loop.
+
+Here is one way to use it::
+
+    import asyncio
+    from graphql import graphql
+
+    async def query_artoo():
+        result = await graphql(schema, """
+        {
+          droid(id: "2001") {
+            name
+            primaryFunction
+          }
+        }
+        """)
+        print(result)
+
+    asyncio.get_event_loop().run_until_complete(query_artoo())
+
+In our query, we asked for the droid with the id 2001, which is R2-D2, and its primary
+function, Astromech. When everything has been implemented correctly as shown above, you
+should get the expected result::
+
+    ExecutionResult(
+        data={'droid': {'name': 'R2-D2', 'primaryFunction': 'Astromech'}},
+        errors=None)
+
+The :class:`ExecutionResult` has a ``data`` attribute with the actual result, and an
+``errors`` attribute with a list of errors if there were any.
+
+If all your resolvers work synchronously, as in our case, you can also use the
+:func:`graphql.graphql_sync` function to query the result in ordinary synchronous code::
+
+    from graphql import graphql_sync
+
+    result = graphql_sync(schema, """
+      query FetchHuman($id: String!) {
+        human(id: $id) {
+          name
+          homePlanet
+        }
+      }
+      """, variable_values={'id': '1000'})
+    print(result)
+
+Here we asked for the human with the id 1000, Luke Skywalker, and his home planet,
+Tatooine. So the output of the code above is::
+
+    ExecutionResult(
+        data={'human': {'name': 'Luke Skywalker', 'homePlanet': 'Tatooine'}},
+        errors=None)
+
+Let's see what happens when we make a mistake in the query, by querying a non-existing
+``homeTown`` field::
+
+    result = graphql_sync(schema, """
+        {
+          human(id: "1000") {
+            name
+            homePlace
+          }
+        }
+        """)
+    print(result)
+
+You will get the following result as output::
+
+    ExecutionResult(data=None, errors=[GraphQLError(
+        "Cannot query field 'homePlace' on type 'Human'. Did you mean 'homePlanet'?",
+        locations=[SourceLocation(line=5, column=9)])])
+
+This is very helpful. Not only do we get the exact location of the mistake in the query,
+but also a suggestion for correcting the bad field name.
+
+GraphQL also allows to request the meta field ``__typename``. We can use this to verify
+that the hero of "The Empire Strikes Back" episode is Luke Skywalker and that he is in
+fact a human::
+
+    result = graphql_sync(schema, """
+        {
+          hero(episode: EMPIRE) {
+            __typename
+            name
+          }
+        }
+        """)
+    print(result)
+
+This gives the following output::
+
+    ExecutionResult(
+        data={'hero': {'__typename': 'Human', 'name': 'Luke Skywalker'}},
+        errors=None)
+
+Finally, let's see what happens when we try to access the secret backstory of our hero::
+
+    result = graphql_sync(schema, """
+        {
+          hero(episode: EMPIRE) {
+            name
+            secretBackstory
+          }
+        }
+        """)
+    print(result)
+
+While we get the name of the hero, the secret backstory fields remains empty, since its
+resolver function raises an error. However, we get the error that has been raised by the
+resolver in the ``errors`` attribute of the result::
+
+    ExecutionResult(
+        data={'hero': {'name': 'Luke Skywalker', 'secretBackstory': None}},
+        errors=[GraphQLError('secretBackstory is secret.',
+                locations=[SourceLocation(line=5, column=9)],
+                path=['hero', 'secretBackstory'])])
+
diff --git a/docs/usage/resolvers.rst b/docs/usage/resolvers.rst
new file mode 100644
index 0000000..d75d75b
--- /dev/null
+++ b/docs/usage/resolvers.rst
@@ -0,0 +1,97 @@
+Implementing the Resolver Functions
+-----------------------------------
+
+Before we can execute queries against our schema, we also need to define the data (the
+humans and droids appearing in the Star Wars trilogy) and implement resolver functions
+that fetch the data (at the beginning of our schema module, because we are referencing
+them later)::
+
+    luke = dict(
+        id='1000', name='Luke Skywalker', homePlanet='Tatooine',
+        friends=['1002', '1003', '2000', '2001'], appearsIn=[4, 5, 6])
+
+    vader = dict(
+        id='1001', name='Darth Vader', homePlanet='Tatooine',
+        friends=['1004'], appearsIn=[4, 5, 6])
+
+    han = dict(
+        id='1002', name='Han Solo', homePlanet=None,
+        friends=['1000', '1003', '2001'], appearsIn=[4, 5, 6])
+
+    leia = dict(
+        id='1003', name='Leia Organa', homePlanet='Alderaan',
+        friends=['1000', '1002', '2000', '2001'], appearsIn=[4, 5, 6])
+
+    tarkin = dict(
+        id='1004', name='Wilhuff Tarkin', homePlanet=None,
+        friends=['1001'], appearsIn=[4])
+
+    human_data = {
+        '1000': luke, '1001': vader, '1002': han, '1003': leia, '1004': tarkin}
+
+    threepio = dict(
+        id='2000', name='C-3PO', primaryFunction='Protocol',
+        friends=['1000', '1002', '1003', '2001'], appearsIn=[4, 5, 6])
+
+    artoo = dict(
+        id='2001', name='R2-D2', primaryFunction='Astromech',
+        friends=['1000', '1002', '1003'], appearsIn=[4, 5, 6])
+
+    droid_data = {
+        '2000': threepio, '2001': artoo}
+
+
+    def get_character_type(character, _info, _type):
+            return 'Droid' if character['id'] in droid_data else 'Human'
+
+
+    def get_character(id):
+        """Helper function to get a character by ID."""
+        return human_data.get(id) or droid_data.get(id)
+
+
+    def get_friends(character, _info):
+        """Allows us to query for a character's friends."""
+        return map(get_character, character.friends)
+
+
+    def get_hero(root, _info, episode):
+        """Allows us to fetch the undisputed hero of the trilogy, R2-D2."""
+        if episode == 5:
+            return luke  # Luke is the hero of Episode V
+        return artoo  # Artoo is the hero otherwise
+
+
+    def get_human(root, _info, id):
+        """Allows us to query for the human with the given id."""
+        return human_data.get(id)
+
+
+    def get_droid(root, _info, id):
+        """Allows us to query for the droid with the given id."""
+        return droid_data.get(id)
+
+
+    def get_secret_backstory(_character, _info):
+        """Raise an error when attempting to get the secret backstory."""
+        raise RuntimeError('secretBackstory is secret.')
+
+
+Note that the resolver functions get the current object as first argument. For a field
+on the root Query type this is often not used, but a root object can also be defined
+when executing the query. As the second argument, they get an object containing
+execution information, as defined in the :class:`graphql.type.GraphQLResolveInfo` class.
+This object also has a ``context`` attribute that can be used to provide every resolver
+with contextual information like the currently logged in user, or a database session.
+In our simple example we don't authenticate users and use static data instead of a
+database, so we don't make use of it here. In addition to these two arguments,
+resolver functions optionally get the defined for the field in the schema, using the
+same names (the names are not translated from GraphQL naming conventions to Python
+naming conventions).
+
+Also note that you don't need to provide resolvers for simple attribute access or for
+fetching items from Python dictionaries.
+
+Finally, note that our data uses the internal values of the ``Episode`` enum that we
+have defined above, not the descriptive enum names that are used externally. For
+example, ``NEWHOPE`` ("A New Hope") has internally the actual episode number 4 as value.
diff --git a/docs/usage/schema.rst b/docs/usage/schema.rst
new file mode 100644
index 0000000..4a7dbf6
--- /dev/null
+++ b/docs/usage/schema.rst
@@ -0,0 +1,195 @@
+Building a Type Schema
+----------------------
+
+.. currentmodule:: graphql.type
+
+Using the classes in the :mod:`graphql.type` sub-package as building blocks, you can
+build a complete GraphQL type schema.
+
+Let's take the following schema as an example, which will allow us to query our favorite
+heroes from the Star Wars trilogy::
+
+    enum Episode { NEWHOPE, EMPIRE, JEDI }
+
+    interface Character {
+      id: String!
+      name: String
+      friends: [Character]
+      appearsIn: [Episode]
+    }
+
+    type Human implements Character {
+      id: String!
+      name: String
+      friends: [Character]
+      appearsIn: [Episode]
+      homePlanet: String
+    }
+
+    type Droid implements Character {
+      id: String!
+      name: String
+      friends: [Character]
+      appearsIn: [Episode]
+      primaryFunction: String
+    }
+
+    type Query {
+      hero(episode: Episode): Character
+      human(id: String!): Human
+      droid(id: String!): Droid
+    }
+
+We have been using the so called GraphQL schema definition language (SDL) here to
+describe the schema. While it is also possible to build a schema directly from this
+notation using GraphQL-core 3, let's first create that schema manually by assembling
+the types defined here using Python classes, adding resolver functions written in Python
+for querying the data.
+
+First, we need to import all the building blocks from the :mod:`graphql.type`
+sub-package. Note that you don't need to import from the sub-packages, since nearly
+everything is also available directly in the top :mod:`graphql` package::
+
+    from graphql import (
+        GraphQLArgument, GraphQLEnumType, GraphQLEnumValue,
+        GraphQLField, GraphQLInterfaceType, GraphQLList, GraphQLNonNull,
+        GraphQLObjectType, GraphQLSchema, GraphQLString)
+
+Next, we need to build the enum type ``Episode``::
+
+    episode_enum = GraphQLEnumType('Episode', {
+        'NEWHOPE': GraphQLEnumValue(4, description='Released in 1977.'),
+        'EMPIRE': GraphQLEnumValue(5, description='Released in 1980.'),
+        'JEDI': GraphQLEnumValue(6, description='Released in 1983.')
+        }, description='One of the films in the Star Wars Trilogy')
+
+If you don't need the descriptions for the enum values, you can also define the enum
+type like this using an underlying Python ``Enum`` type::
+
+    from enum import Enum
+
+    class EpisodeEnum(Enum):
+        NEWHOPE = 4
+        EMPIRE = 5
+        JEDI = 6
+
+    episode_enum = GraphQLEnumType(
+        'Episode', EpisodeEnum,
+        description='One of the films in the Star Wars Trilogy')
+
+You can also use a Python dictionary instead of a Python ``Enum`` type to define the
+GraphQL enum type::
+
+    episode_enum = GraphQLEnumType(
+        'Episode', {'NEWHOPE': 4, 'EMPIRE': 5, 'JEDI': 6},
+        description='One of the films in the Star Wars Trilogy')
+
+Our schema also contains a ``Character`` interface. Here is how we build it::
+
+    character_interface = GraphQLInterfaceType('Character', lambda: {
+        'id': GraphQLField(
+            GraphQLNonNull(GraphQLString),
+            description='The id of the character.'),
+        'name': GraphQLField(
+            GraphQLString,
+            description='The name of the character.'),
+        'friends': GraphQLField(
+            GraphQLList(character_interface),
+            description='The friends of the character,'
+                        ' or an empty list if they have none.'),
+        'appearsIn': GraphQLField(
+            GraphQLList(episode_enum),
+            description='Which movies they appear in.'),
+        'secretBackstory': GraphQLField(
+            GraphQLString,
+            description='All secrets about their past.')},
+        resolve_type=get_character_type,
+        description='A character in the Star Wars Trilogy')
+
+Note that we did not pass the dictionary of fields to the ``GraphQLInterfaceType``
+directly, but using a lambda function (a so-called "thunk"). This is necessary because
+the fields are referring back to the character interface that we are just defining.
+Whenever you have such recursive definitions in GraphQL-core, you need to use thunks.
+Otherwise, you can pass everything directly.
+
+Characters in the Star Wars trilogy are either humans or droids. So we define a
+``Human`` and a ``Droid`` type, which both implement the ``Character`` interface::
+
+    human_type = GraphQLObjectType('Human', lambda: {
+        'id': GraphQLField(
+            GraphQLNonNull(GraphQLString),
+            description='The id of the human.'),
+        'name': GraphQLField(
+            GraphQLString,
+            description='The name of the human.'),
+        'friends': GraphQLField(
+            GraphQLList(character_interface),
+            description='The friends of the human,'
+                        ' or an empty list if they have none.',
+            resolve=get_friends),
+        'appearsIn': GraphQLField(
+            GraphQLList(episode_enum),
+            description='Which movies they appear in.'),
+        'homePlanet': GraphQLField(
+            GraphQLString,
+            description='The home planet of the human, or null if unknown.'),
+        'secretBackstory': GraphQLField(
+            GraphQLString,
+            resolve=get_secret_backstory,
+            description='Where are they from'
+                        ' and how they came to be who they are.')},
+        interfaces=[character_interface],
+        description='A humanoid creature in the Star Wars universe.')
+
+    droid_type = GraphQLObjectType('Droid', lambda: {
+        'id': GraphQLField(
+            GraphQLNonNull(GraphQLString),
+            description='The id of the droid.'),
+        'name': GraphQLField(
+            GraphQLString,
+            description='The name of the droid.'),
+        'friends': GraphQLField(
+            GraphQLList(character_interface),
+            description='The friends of the droid,'
+                        ' or an empty list if they have none.',
+            resolve=get_friends,
+        ),
+        'appearsIn': GraphQLField(
+            GraphQLList(episode_enum),
+            description='Which movies they appear in.'),
+        'secretBackstory': GraphQLField(
+            GraphQLString,
+            resolve=get_secret_backstory,
+            description='Construction date and the name of the designer.'),
+        'primaryFunction': GraphQLField(
+            GraphQLString,
+            description='The primary function of the droid.')
+        },
+        interfaces=[character_interface],
+        description='A mechanical creature in the Star Wars universe.')
+
+Now that we have defined all used result types, we can construct the ``Query`` type for
+our schema::
+
+    query_type = GraphQLObjectType('Query', lambda: {
+        'hero': GraphQLField(character_interface, args={
+            'episode': GraphQLArgument(episode_enum, description=(
+                'If omitted, returns the hero of the whole saga.'
+                ' If provided, returns the hero of that particular episode.'))},
+            resolve=get_hero),
+        'human': GraphQLField(human_type, args={
+            'id': GraphQLArgument(
+                GraphQLNonNull(GraphQLString), description='id of the human')},
+            resolve=get_human),
+        'droid': GraphQLField(droid_type, args={
+            'id': GraphQLArgument(
+                GraphQLNonNull(GraphQLString), description='id of the droid')},
+            resolve=get_droid)})
+
+
+Using our query type we can define our schema::
+
+    schema = GraphQLSchema(query_type)
+
+Note that you can also pass a mutation type and a subscription type as additional
+arguments to the ``GraphQLSchema``.
diff --git a/docs/usage/sdl.rst b/docs/usage/sdl.rst
new file mode 100644
index 0000000..1227c52
--- /dev/null
+++ b/docs/usage/sdl.rst
@@ -0,0 +1,85 @@
+Using the Schema Definition Language
+------------------------------------
+
+Above we defined the GraphQL schema as Python code, using the ``GraphQLSchema`` class
+and other classes representing the various GraphQL types.
+
+GraphQL-core 3 also provides a language-agnostic way of defining a GraphQL schema
+using the GraphQL schema definition language (SDL) which is also part of the GraphQL
+specification. To do this, we simply feed the SDL as a string to the
+:func:`graphql.utilities.build_schema` function::
+
+    from graphql import build_schema
+
+    schema = build_schema("""
+
+        enum Episode { NEWHOPE, EMPIRE, JEDI }
+
+        interface Character {
+          id: String!
+          name: String
+          friends: [Character]
+          appearsIn: [Episode]
+        }
+
+        type Human implements Character {
+          id: String!
+          name: String
+          friends: [Character]
+          appearsIn: [Episode]
+          homePlanet: String
+        }
+
+        type Droid implements Character {
+          id: String!
+          name: String
+          friends: [Character]
+          appearsIn: [Episode]
+          primaryFunction: String
+        }
+
+        type Query {
+          hero(episode: Episode): Character
+          human(id: String!): Human
+          droid(id: String!): Droid
+        }
+        """)
+
+The result is a ``GraphQLSchema`` object just like the one we defined above, except for
+the resolver functions which cannot be defined in the SDL.
+
+We would need to manually attach these functions to the schema, like so::
+
+    schema.query_type.fields['hero'].resolve = get_hero
+    schema.get_type('Character').resolve_type = get_character_type
+
+Another problem is that the SDL does not define the server side values of the
+``Episode`` enum type which are returned by the resolver functions and which are
+different from the names used for the episode.
+
+So we would also need to manually define these values, like so::
+
+    for name, value in schema.get_type('Episode').values.items():
+        value.value = EpisodeEnum[name].value
+
+This would allow us to query the schema built from SDL just like the manually assembled
+schema::
+
+    from graphql import graphql_sync
+
+    result = graphql_sync(schema, """
+        {
+          hero(episode: EMPIRE) {
+            name
+            appearsIn
+          }
+        }
+        """)
+    print(result)
+
+And we would get the expected result::
+
+    ExecutionResult(
+        data={'hero': {'name': 'Luke Skywalker',
+                       'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI']}},
+        errors=None)
diff --git a/docs/usage/validator.rst b/docs/usage/validator.rst
new file mode 100644
index 0000000..dc696d2
--- /dev/null
+++ b/docs/usage/validator.rst
@@ -0,0 +1,43 @@
+Validating GraphQL Queries
+--------------------------
+
+.. currentmodule:: graphql.validation
+
+When executing GraphQL queries, the second step that happens under the hood after
+parsing the source code is a validation against the given schema using the rules of the
+GraphQL specification. You can also run the validation step manually by calling the
+:func:`graphql.validation.validate` function, passing the schema and the AST document::
+
+    from graphql import parse, validate
+
+    errors = validate(schema, parse("""
+        {
+          human(id: NEWHOPE) {
+            name
+            homePlace
+            friends
+          }
+        }
+        """))
+
+As a result, you will get a complete list of all errors that the validators has found.
+In this case, we will get::
+
+    [GraphQLError(
+        'String cannot represent a non string value: NEWHOPE',
+        locations=[SourceLocation(line=3, column=17)]),
+     GraphQLError(
+        "Cannot query field 'homePlace' on type 'Human'."
+         " Did you mean 'homePlanet'?",
+         locations=[SourceLocation(line=5, column=9)]),
+     GraphQLError(
+        "Field 'friends' of type '[Character]' must have a selection of subfields."
+         "  Did you mean 'friends { ... }'?",
+         locations=[SourceLocation(line=6, column=9)])]
+
+These rules are available in the :data:`specified_rules` list and implemented in the
+``graphql.validation.rules`` subpackage. Instead of the default rules,
+you can also use a subset or create custom rules. The rules are
+based on the :class:`graphql.validation.ValidationRule` class which is based on the
+:class:`graphql.language.Visitor` class which provides a way of walking through an AST
+document using the visitor pattern.
diff --git a/graphql/__init__.py b/graphql/__init__.py
deleted file mode 100644
index 902800b..0000000
--- a/graphql/__init__.py
+++ /dev/null
@@ -1,267 +0,0 @@
-"""
-GraphQL.js provides a reference implementation for the GraphQL specification
-but is also a useful utility for operating on GraphQL files and building
-sophisticated tools.
-
-This primary module exports a general purpose function for fulfilling all
-steps of the GraphQL specification in a single operation, but also includes
-utilities for every part of the GraphQL specification:
-
-  - Parsing the GraphQL language.
-  - Building a GraphQL type schema.
-  - Validating a GraphQL request against a type schema.
-  - Executing a GraphQL request against a type schema.
-
-This also includes utility functions for operating on GraphQL types and
-GraphQL documents to facilitate building tools.
-
-You may also import from each sub-directory directly. For example, the
-following two import statements are equivalent:
-
-    from graphql import parse
-    from graphql.language.base import parse
-"""
-from .pyutils.version import get_version
-
-# The primary entry point into fulfilling a GraphQL request.
-from .graphql import graphql
-
-# Create and operate on GraphQL type definitions and schema.
-from .type import (  # no import order
-    GraphQLSchema,
-    # Definitions
-    GraphQLScalarType,
-    GraphQLObjectType,
-    GraphQLInterfaceType,
-    GraphQLUnionType,
-    GraphQLEnumType,
-    GraphQLEnumValue,
-    GraphQLInputObjectType,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLField,
-    GraphQLInputObjectField,
-    GraphQLArgument,
-    # "Enum" of Type Kinds
-    TypeKind,
-    # "Enum" of Directive locations
-    DirectiveLocation,
-    # Scalars
-    GraphQLInt,
-    GraphQLFloat,
-    GraphQLString,
-    GraphQLBoolean,
-    GraphQLID,
-    # Directive definition
-    GraphQLDirective,
-    # Built-in directives defined by the Spec
-    specified_directives,
-    GraphQLSkipDirective,
-    GraphQLIncludeDirective,
-    GraphQLDeprecatedDirective,
-    # Constant Deprecation Reason
-    DEFAULT_DEPRECATION_REASON,
-    # GraphQL Types for introspection.
-    __Schema,
-    __Directive,
-    __DirectiveLocation,
-    __Type,
-    __Field,
-    __InputValue,
-    __EnumValue,
-    __TypeKind,
-    # Meta-field definitions.
-    SchemaMetaFieldDef,
-    TypeMetaFieldDef,
-    TypeNameMetaFieldDef,
-    # Predicates
-    is_type,
-    is_input_type,
-    is_output_type,
-    is_leaf_type,
-    is_composite_type,
-    is_abstract_type,
-    # Un-modifiers
-    get_nullable_type,
-    get_named_type,
-)
-
-# Parse and operate on GraphQL language source files.
-from .language.base import (  # no import order
-    Source,
-    get_location,
-    # Parse
-    parse,
-    parse_value,
-    # Print
-    print_ast,
-    # Visit
-    visit,
-    ParallelVisitor,
-    TypeInfoVisitor,
-    BREAK,
-)
-
-# Execute GraphQL queries.
-from .execution import (  # no import order
-    execute,
-    subscribe,
-    ResolveInfo,
-    MiddlewareManager,
-    middlewares,
-)
-
-# Validate GraphQL queries.
-from .validation import validate, specified_rules  # no import order
-
-# Create and format GraphQL errors.
-from .error import GraphQLError, format_error
-
-# Utilities for operating on GraphQL type schema and parsed sources.
-from .utils.base import (
-    # The GraphQL query recommended for a full schema introspection.
-    introspection_query,
-    # Gets the target Operation from a Document
-    get_operation_ast,
-    # Build a GraphQLSchema from an introspection result.
-    build_client_schema,
-    # Build a GraphQLSchema from a parsed GraphQL Schema language AST.
-    build_ast_schema,
-    # Extends an existing GraphQLSchema from a parsed GraphQL Schema
-    # language AST.
-    extend_schema,
-    # Print a GraphQLSchema to GraphQL Schema language.
-    print_schema,
-    # Create a GraphQLType from a GraphQL language AST.
-    type_from_ast,
-    # Create a JavaScript value from a GraphQL language AST.
-    value_from_ast,
-    # Create a GraphQL language AST from a JavaScript value.
-    ast_from_value,
-    # A helper to use within recursive-descent visitors which need to be aware of
-    # the GraphQL type system.
-    TypeInfo,
-    # Determine if JavaScript values adhere to a GraphQL type.
-    is_valid_value,
-    # Determine if AST values adhere to a GraphQL type.
-    is_valid_literal_value,
-    # Concatenates multiple AST together.
-    concat_ast,
-    # Comparators for types
-    is_equal_type,
-    is_type_sub_type_of,
-    do_types_overlap,
-    # Asserts a string is a valid GraphQL name.
-    assert_valid_name,
-    # Undefined const
-    Undefined,
-)
-
-# Utilities for dynamic execution engines
-from .backend import (
-    GraphQLBackend,
-    GraphQLDocument,
-    GraphQLCoreBackend,
-    GraphQLDeciderBackend,
-    GraphQLCachedBackend,
-    get_default_backend,
-    set_default_backend,
-)
-
-VERSION = (2, 2, 1, "final", 0)
-__version__ = get_version(VERSION)
-
-
-__all__ = (
-    "__version__",
-    "graphql",
-    "GraphQLBoolean",
-    "GraphQLEnumType",
-    "GraphQLEnumValue",
-    "GraphQLFloat",
-    "GraphQLID",
-    "GraphQLInputObjectType",
-    "GraphQLInt",
-    "GraphQLInterfaceType",
-    "GraphQLList",
-    "GraphQLNonNull",
-    "GraphQLField",
-    "GraphQLInputObjectField",
-    "GraphQLArgument",
-    "GraphQLObjectType",
-    "GraphQLScalarType",
-    "GraphQLSchema",
-    "GraphQLString",
-    "GraphQLUnionType",
-    "GraphQLDirective",
-    "specified_directives",
-    "GraphQLSkipDirective",
-    "GraphQLIncludeDirective",
-    "GraphQLDeprecatedDirective",
-    "DEFAULT_DEPRECATION_REASON",
-    "TypeKind",
-    "DirectiveLocation",
-    "__Schema",
-    "__Directive",
-    "__DirectiveLocation",
-    "__Type",
-    "__Field",
-    "__InputValue",
-    "__EnumValue",
-    "__TypeKind",
-    "SchemaMetaFieldDef",
-    "TypeMetaFieldDef",
-    "TypeNameMetaFieldDef",
-    "get_named_type",
-    "get_nullable_type",
-    "is_abstract_type",
-    "is_composite_type",
-    "is_input_type",
-    "is_leaf_type",
-    "is_output_type",
-    "is_type",
-    "BREAK",
-    "ParallelVisitor",
-    "Source",
-    "TypeInfoVisitor",
-    "get_location",
-    "parse",
-    "parse_value",
-    "print_ast",
-    "visit",
-    "execute",
-    "subscribe",
-    "ResolveInfo",
-    "MiddlewareManager",
-    "middlewares",
-    "specified_rules",
-    "validate",
-    "GraphQLError",
-    "format_error",
-    "TypeInfo",
-    "assert_valid_name",
-    "ast_from_value",
-    "build_ast_schema",
-    "build_client_schema",
-    "concat_ast",
-    "do_types_overlap",
-    "extend_schema",
-    "get_operation_ast",
-    "introspection_query",
-    "is_equal_type",
-    "is_type_sub_type_of",
-    "is_valid_literal_value",
-    "is_valid_value",
-    "print_schema",
-    "type_from_ast",
-    "value_from_ast",
-    "get_version",
-    "Undefined",
-    "GraphQLBackend",
-    "GraphQLDocument",
-    "GraphQLCoreBackend",
-    "GraphQLDeciderBackend",
-    "GraphQLCachedBackend",
-    "get_default_backend",
-    "set_default_backend",
-)
diff --git a/graphql/backend/__init__.py b/graphql/backend/__init__.py
deleted file mode 100644
index faeb003..0000000
--- a/graphql/backend/__init__.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module provides a dynamic way of using different
-engines for a GraphQL schema query resolution.
-"""
-
-from .base import GraphQLBackend, GraphQLDocument
-from .core import GraphQLCoreBackend
-from .decider import GraphQLDeciderBackend
-from .cache import GraphQLCachedBackend
-
-
-_default_backend = None
-
-
-def get_default_backend():
-    # type: () -> GraphQLCoreBackend
-    global _default_backend
-    if _default_backend is None:
-        _default_backend = GraphQLCoreBackend()
-    return _default_backend
-
-
-def set_default_backend(backend):
-    # type: (GraphQLCoreBackend) -> None
-    global _default_backend
-    assert isinstance(
-        backend, GraphQLBackend
-    ), "backend must be an instance of GraphQLBackend."
-    _default_backend = backend
-
-
-__all__ = [
-    "GraphQLBackend",
-    "GraphQLDocument",
-    "GraphQLCoreBackend",
-    "GraphQLDeciderBackend",
-    "GraphQLCachedBackend",
-    "get_default_backend",
-    "set_default_backend",
-]
diff --git a/graphql/backend/base.py b/graphql/backend/base.py
deleted file mode 100644
index 6573d3a..0000000
--- a/graphql/backend/base.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from ..pyutils.cached_property import cached_property
-from ..language import ast
-
-from abc import ABCMeta, abstractmethod
-import six
-
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Dict, Optional, Union, Callable
-    from ..language.ast import Document
-    from ..type.schema import GraphQLSchema
-
-
-class GraphQLBackend(six.with_metaclass(ABCMeta)):
-    @abstractmethod
-    def document_from_string(self, schema, request_string):
-        raise NotImplementedError(
-            "document_from_string method not implemented in {}.".format(self.__class__)
-        )
-
-
-class GraphQLDocument(object):
-    def __init__(self, schema, document_string, document_ast, execute):
-        # type: (GraphQLSchema, str, Document, Callable) -> None
-        self.schema = schema
-        self.document_string = document_string
-        self.document_ast = document_ast
-        self.execute = execute
-
-    @cached_property
-    def operations_map(self):
-        # type: () -> Dict[Union[str, None], str]
-        """
-        returns a Mapping of operation names and it's associated types.
-        E.g. {'myQuery': 'query', 'myMutation': 'mutation'}
-        """
-        document_ast = self.document_ast
-        operations = {}  # type: Dict[Union[str, None], str]
-        for definition in document_ast.definitions:
-            if isinstance(definition, ast.OperationDefinition):
-                if definition.name:
-                    operations[definition.name.value] = definition.operation
-                else:
-                    operations[None] = definition.operation
-
-        return operations
-
-    def get_operation_type(self, operation_name):
-        # type: (Optional[str]) -> Optional[str]
-        """
-        Returns the operation type ('query', 'mutation', 'subscription' or None)
-        for the given operation_name.
-        If no operation_name is provided (and only one operation exists) it will return the
-        operation type for that operation
-        """
-        operations_map = self.operations_map
-        if not operation_name and len(operations_map) == 1:
-            return next(iter(operations_map.values()))
-        return operations_map.get(operation_name)
diff --git a/graphql/backend/cache.py b/graphql/backend/cache.py
deleted file mode 100644
index f35a45c..0000000
--- a/graphql/backend/cache.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from hashlib import sha1
-
-from six import string_types
-from ..type import GraphQLSchema
-
-from .base import GraphQLBackend
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Dict, Optional, Hashable
-    from .base import GraphQLDocument
-
-_cached_schemas = {}  # type: Dict[GraphQLSchema, str]
-
-_cached_queries = {}  # type: Dict[str, str]
-
-
-def get_unique_schema_id(schema):
-    # type: (GraphQLSchema) -> str
-    """Get a unique id given a GraphQLSchema"""
-    assert isinstance(schema, GraphQLSchema), (
-        "Must receive a GraphQLSchema as schema. Received {}"
-    ).format(repr(schema))
-
-    if schema not in _cached_schemas:
-        _cached_schemas[schema] = sha1(str(schema).encode("utf-8")).hexdigest()
-    return _cached_schemas[schema]
-
-
-def get_unique_document_id(query_str):
-    # type: (str) -> str
-    """Get a unique id given a query_string"""
-    assert isinstance(query_str, string_types), (
-        "Must receive a string as query_str. Received {}"
-    ).format(repr(query_str))
-
-    if query_str not in _cached_queries:
-        _cached_queries[query_str] = sha1(str(query_str).encode("utf-8")).hexdigest()
-    return _cached_queries[query_str]
-
-
-class GraphQLCachedBackend(GraphQLBackend):
-    """GraphQLCachedBackend will cache the document response from the backend
-    given a key for that document"""
-
-    def __init__(
-        self,
-        backend,  # type: GraphQLBackend
-        cache_map=None,  # type: Optional[Dict[Hashable, GraphQLDocument]]
-        use_consistent_hash=False,  # type: bool
-    ):
-        # type: (...) -> None
-        assert isinstance(
-            backend, GraphQLBackend
-        ), "Provided backend must be an instance of GraphQLBackend"
-        if cache_map is None:
-            cache_map = {}
-        self.backend = backend
-        self.cache_map = cache_map
-        self.use_consistent_hash = use_consistent_hash
-
-    def get_key_for_schema_and_document_string(self, schema, request_string):
-        # type: (GraphQLSchema, str) -> int
-        """This method returns a unique key given a schema and a request_string"""
-        if self.use_consistent_hash:
-            schema_id = get_unique_schema_id(schema)
-            document_id = get_unique_document_id(request_string)
-            return hash((schema_id, document_id))
-        return hash((schema, request_string))
-
-    def document_from_string(self, schema, request_string):
-        # type: (GraphQLSchema, str) -> Optional[GraphQLDocument]
-        """This method returns a GraphQLQuery (from cache if present)"""
-        key = self.get_key_for_schema_and_document_string(schema, request_string)
-        if key not in self.cache_map:
-            self.cache_map[key] = self.backend.document_from_string(
-                schema, request_string
-            )
-
-        return self.cache_map[key]
diff --git a/graphql/backend/compiled.py b/graphql/backend/compiled.py
deleted file mode 100644
index e3805cd..0000000
--- a/graphql/backend/compiled.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from six import string_types
-from .base import GraphQLDocument
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..type.schema import GraphQLSchema
-    from typing import Any, Optional, Dict, Callable, Union
-
-
-class GraphQLCompiledDocument(GraphQLDocument):
-    @classmethod
-    def from_code(
-        cls,
-        schema,  # type: GraphQLSchema
-        code,  # type: Union[str, Any]
-        uptodate=None,  # type: Optional[bool]
-        extra_namespace=None,  # type: Optional[Dict[str, Any]]
-    ):
-        # type: (...) -> GraphQLCompiledDocument
-        """Creates a GraphQLDocument object from compiled code and the globals.  This
-        is used by the loaders and schema to create a document object.
-        """
-        if isinstance(code, string_types):
-            filename = "<document>"
-            code = compile(code, filename, "exec")
-        namespace = {"__file__": code.co_filename}
-        exec(code, namespace)
-        if extra_namespace:
-            namespace.update(extra_namespace)
-        rv = cls._from_namespace(schema, namespace)
-        # rv._uptodate = uptodate
-        return rv
-
-    @classmethod
-    def from_module_dict(cls, schema, module_dict):
-        # type: (GraphQLSchema, Dict[str, Any]) -> GraphQLCompiledDocument
-        """Creates a template object from a module.  This is used by the
-        module loader to create a document object.
-        """
-        return cls._from_namespace(schema, module_dict)
-
-    @classmethod
-    def _from_namespace(cls, schema, namespace):
-        # type: (GraphQLSchema, Dict[str, Any]) -> GraphQLCompiledDocument
-        document_string = namespace.get("document_string", "")  # type: str
-        document_ast = namespace.get("document_ast")  # type: ignore
-        execute = namespace["execute"]  # type: Callable
-
-        namespace["schema"] = schema
-        return cls(  # type: ignore
-            schema=schema,
-            document_string=document_string,
-            document_ast=document_ast,
-            execute=execute,
-        )
diff --git a/graphql/backend/core.py b/graphql/backend/core.py
deleted file mode 100644
index 41aea2d..0000000
--- a/graphql/backend/core.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from functools import partial
-from six import string_types
-
-from ..execution import execute, ExecutionResult
-from ..language.base import parse, print_ast
-from ..language import ast
-from ..validation import validate
-
-from .base import GraphQLBackend, GraphQLDocument
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Optional, Union
-    from ..language.ast import Document
-    from ..type.schema import GraphQLSchema
-    from rx import Observable
-
-
-def execute_and_validate(
-    schema,  # type: GraphQLSchema
-    document_ast,  # type: Document
-    *args,  # type: Any
-    **kwargs  # type: Any
-):
-    # type: (...) -> Union[ExecutionResult, Observable]
-    do_validation = kwargs.get("validate", True)
-    if do_validation:
-        validation_errors = validate(schema, document_ast)
-        if validation_errors:
-            return ExecutionResult(errors=validation_errors, invalid=True)
-
-    return execute(schema, document_ast, *args, **kwargs)
-
-
-class GraphQLCoreBackend(GraphQLBackend):
-    """GraphQLCoreBackend will return a document using the default
-    graphql executor"""
-
-    def __init__(self, executor=None):
-        # type: (Optional[Any]) -> None
-        self.execute_params = {"executor": executor}
-
-    def document_from_string(self, schema, document_string):
-        # type: (GraphQLSchema, Union[Document, str]) -> GraphQLDocument
-        if isinstance(document_string, ast.Document):
-            document_ast = document_string
-            document_string = print_ast(document_ast)
-        else:
-            assert isinstance(
-                document_string, string_types
-            ), "The query must be a string"
-            document_ast = parse(document_string)
-        return GraphQLDocument(
-            schema=schema,
-            document_string=document_string,
-            document_ast=document_ast,
-            execute=partial(
-                execute_and_validate, schema, document_ast, **self.execute_params
-            ),
-        )
diff --git a/graphql/backend/decider.py b/graphql/backend/decider.py
deleted file mode 100644
index 5fdd39b..0000000
--- a/graphql/backend/decider.py
+++ /dev/null
@@ -1,211 +0,0 @@
-import atexit
-import logging
-import threading
-import os
-from time import sleep, time
-
-
-from .base import GraphQLBackend, GraphQLDocument
-from .cache import GraphQLCachedBackend
-from ..pyutils.compat import Queue, check_threads
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import List, Union, Optional, Hashable, Dict, Tuple, Type
-    from ..type.schema import GraphQLSchema
-
-
-DEFAULT_TIMEOUT = 10
-
-logger = logging.getLogger("graphql.errors")
-
-
-# Code shamelessly taken from
-# https://github.com/getsentry/raven-python/blob/master/raven/transport/threaded.py
-# Why to create when we can take something that works?
-# Attributions to the Sentry team :)
-class AsyncWorker(object):
-    _terminator = object()
-
-    def __init__(self, shutdown_timeout=DEFAULT_TIMEOUT):
-        check_threads()
-        self._queue = Queue(-1)
-        self._lock = threading.Lock()
-        self._thread = None
-        self._thread_for_pid = None
-        self.options = {"shutdown_timeout": shutdown_timeout}
-        self.start()
-
-    def is_alive(self):
-        if self._thread_for_pid != os.getpid():
-            return False
-        return self._thread and self._thread.is_alive()
-
-    def _ensure_thread(self):
-        if self.is_alive():
-            return
-        self.start()
-
-    def main_thread_terminated(self):
-        with self._lock:
-            if not self.is_alive():
-                # thread not started or already stopped - nothing to do
-                return
-
-            # wake the processing thread up
-            self._queue.put_nowait(self._terminator)
-
-            timeout = self.options["shutdown_timeout"]
-
-            # wait briefly, initially
-            initial_timeout = min(0.1, timeout)
-
-            if not self._timed_queue_join(initial_timeout):
-                # if that didn't work, wait a bit longer
-                # NB that size is an approximation, because other threads may
-                # add or remove items
-                size = self._queue.qsize()
-
-                print("GraphQL is attempting to retrieve %i pending documents" % size)
-                print("Waiting up to %s seconds" % timeout)
-
-                if os.name == "nt":
-                    print("Press Ctrl-Break to quit")
-                else:
-                    print("Press Ctrl-C to quit")
-
-                self._timed_queue_join(timeout - initial_timeout)
-
-            self._thread = None
-
-    def _timed_queue_join(self, timeout):
-        """
-        implementation of Queue.join which takes a 'timeout' argument
-        returns true on success, false on timeout
-        """
-        deadline = time() + timeout
-        queue = self._queue
-
-        queue.all_tasks_done.acquire()
-        try:
-            while queue.unfinished_tasks:
-                delay = deadline - time()
-                if delay <= 0:
-                    # timed out
-                    return False
-
-                queue.all_tasks_done.wait(timeout=delay)
-
-            return True
-
-        finally:
-            queue.all_tasks_done.release()
-
-    def start(self):
-        """
-        Starts the task thread.
-        """
-        self._lock.acquire()
-        try:
-            if not self.is_alive():
-                self._thread = threading.Thread(
-                    target=self._target, name="graphql.AsyncWorker"
-                )
-                self._thread.setDaemon(True)
-                self._thread.start()
-                self._thread_for_pid = os.getpid()
-        finally:
-            self._lock.release()
-            atexit.register(self.main_thread_terminated)
-
-    def stop(self, timeout=None):
-        """
-        Stops the task thread. Synchronous!
-        """
-        with self._lock:
-            if self._thread:
-                self._queue.put_nowait(self._terminator)
-                self._thread.join(timeout=timeout)
-                self._thread = None
-                self._thread_for_pid = None
-
-    def queue(self, callback, *args, **kwargs):
-        self._ensure_thread()
-        self._queue.put_nowait((callback, args, kwargs))
-
-    def _target(self):
-        while True:
-            record = self._queue.get()
-            try:
-                if record is self._terminator:
-                    break
-                callback, args, kwargs = record
-                try:
-                    callback(*args, **kwargs)
-                except Exception:
-                    logger.error("Failed processing job", exc_info=True)
-            finally:
-                self._queue.task_done()
-
-            sleep(0)
-
-
-class GraphQLDeciderBackend(GraphQLCachedBackend):
-    """GraphQLDeciderBackend will offload the document generation to the
-    main backend in a new thread, serving meanwhile the document from the fallback
-    backend"""
-
-    _worker = None
-    fallback_backend = None  # type: GraphQLBackend
-    # _in_queue = object()
-
-    def __init__(
-        self,
-        backend,  # type: Union[List[GraphQLBackend], Tuple[GraphQLBackend, GraphQLBackend], GraphQLBackend]
-        fallback_backend=None,  # type: Optional[GraphQLBackend]
-        cache_map=None,  # type: Optional[Dict[Hashable, GraphQLDocument]]
-        use_consistent_hash=False,  # type: bool
-        worker_class=AsyncWorker,  # type: Type[AsyncWorker]
-    ):
-        # type: (...) -> None
-        if not backend:
-            raise Exception("Need to provide backends to decide into.")
-        if isinstance(backend, (list, tuple)):
-            if fallback_backend:
-                raise Exception("Can't set a fallback backend and backends as array")
-            if len(backend) != 2:
-                raise Exception("Only two backends are supported for now")
-            backend, fallback_backend = backend[0], backend[1]  # type: ignore
-        else:
-            if not fallback_backend:
-                raise Exception("Need to provide a fallback backend")
-
-        self.fallback_backend = fallback_backend  # type: ignore
-        self.worker_class = worker_class
-        super(GraphQLDeciderBackend, self).__init__(
-            backend, cache_map=cache_map, use_consistent_hash=use_consistent_hash
-        )
-
-    def queue_backend(self, key, schema, request_string):
-        # type: (Hashable, GraphQLSchema, str) -> None
-        self.cache_map[key] = self.backend.document_from_string(schema, request_string)
-
-    def get_worker(self):
-        # type: () -> AsyncWorker
-        if self._worker is None or not self._worker.is_alive():
-            self._worker = self.worker_class()
-        return self._worker
-
-    def document_from_string(self, schema, request_string):
-        # type: (GraphQLSchema, str) -> GraphQLDocument
-        """This method returns a GraphQLQuery (from cache if present)"""
-        key = self.get_key_for_schema_and_document_string(schema, request_string)
-        if key not in self.cache_map:
-            # We return from the fallback
-            self.cache_map[key] = self.fallback_backend.document_from_string(
-                schema, request_string
-            )
-            # We ensure the main backend response is in the queue
-            self.get_worker().queue(self.queue_backend, key, schema, request_string)
-
-        return self.cache_map[key]
diff --git a/graphql/backend/quiver_cloud.py b/graphql/backend/quiver_cloud.py
deleted file mode 100644
index 2c6796b..0000000
--- a/graphql/backend/quiver_cloud.py
+++ /dev/null
@@ -1,105 +0,0 @@
-try:
-    import requests
-except ImportError:
-    raise ImportError(
-        "requests package is required for Quiver Cloud backend.\n"
-        "You can install it using: pip install requests"
-    )
-
-from ..utils.schema_printer import print_schema
-
-from .base import GraphQLBackend
-from .compiled import GraphQLCompiledDocument
-
-from six.moves.urllib.parse import urlparse
-
-GRAPHQL_QUERY = """
-mutation($schemaDsl: String!, $query: String!, $pythonOptions: PythonOptions) {
-  generateCode(
-    schemaDsl: $schemaDsl
-    query: $query,
-    language: PYTHON,
-    pythonOptions: $pythonOptions
-  ) {
-    code
-    compilationTime
-    errors {
-      type
-    }
-  }
-}
-"""
-
-
-class GraphQLQuiverCloudBackend(GraphQLBackend):
-    def __init__(self, dsn, python_options=None, **options):
-        super(GraphQLQuiverCloudBackend, self).__init__(**options)
-        try:
-            url = urlparse(dsn.strip())
-        except Exception:
-            raise Exception("Received wrong url {}".format(dsn))
-
-        netloc = url.hostname
-        if url.port:
-            netloc += ":%s" % url.port
-
-        path_bits = url.path.rsplit("/", 1)
-        if len(path_bits) > 1:
-            path = path_bits[0]
-        else:
-            path = ""
-
-        self.api_url = "{}://{}{}".format(url.scheme.rsplit("+", 1)[-1], netloc, path)
-        self.public_key = url.username
-        self.secret_key = url.password
-        self.extra_namespace = {}
-        if python_options is None:
-            python_options = {"asyncFramework": "PROMISE"}
-        wait_for_promises = python_options.pop("wait_for_promises", None)
-        if wait_for_promises:
-            assert callable(wait_for_promises), "wait_for_promises must be callable."
-            self.extra_namespace["wait_for_promises"] = wait_for_promises
-        self.python_options = python_options
-
-    def make_post_request(self, url, auth, json_payload):
-        """This function executes the request with the provided
-        json payload and return the json response"""
-        response = requests.post(url, auth=auth, json=json_payload)
-        return response.json()
-
-    def generate_source(self, schema, query):
-        variables = {
-            "schemaDsl": print_schema(schema),
-            "query": query,
-            "pythonOptions": self.python_options,
-        }
-
-        json_response = self.make_post_request(
-            "{}/graphql".format(self.api_url),
-            auth=(self.public_key, self.secret_key),
-            json_payload={"query": GRAPHQL_QUERY, "variables": variables},
-        )
-
-        errors = json_response.get("errors")
-        if errors:
-            raise Exception(errors[0].get("message"))
-        data = json_response.get("data", {})
-        code_generation = data.get("generateCode", {})
-        code = code_generation.get("code")
-        if not code:
-            raise Exception("Cant get the code. Received json from Quiver Cloud")
-        code = str(code)
-        return code
-
-    def document_from_string(self, schema, request_string):
-        source = self.generate_source(schema, request_string)
-        filename = "<document>"
-        code = compile(source, filename, "exec")
-
-        def uptodate():
-            return True
-
-        document = GraphQLCompiledDocument.from_code(
-            schema, code, uptodate, self.extra_namespace
-        )
-        return document
diff --git a/graphql/backend/tests/__init__.py b/graphql/backend/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/backend/tests/schema.py b/graphql/backend/tests/schema.py
deleted file mode 100644
index 00a7f93..0000000
--- a/graphql/backend/tests/schema.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
-
-
-Query = GraphQLObjectType(
-    "Query", lambda: {"hello": GraphQLField(GraphQLString, resolver=lambda *_: "World")}
-)
-
-schema = GraphQLSchema(Query)
diff --git a/graphql/backend/tests/test_base.py b/graphql/backend/tests/test_base.py
deleted file mode 100644
index c9a8dfd..0000000
--- a/graphql/backend/tests/test_base.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import pytest
-from .. import get_default_backend, set_default_backend, GraphQLCoreBackend
-
-
-def test_get_default_backend_returns_core_by_default():
-    # type: () -> None
-    backend = get_default_backend()
-    assert isinstance(backend, GraphQLCoreBackend)
-
-
-def test_set_default_backend():
-    # type: () -> None
-    default_backend = get_default_backend()
-    new_backend = GraphQLCoreBackend()
-    assert new_backend != default_backend
-    set_default_backend(new_backend)
-    assert get_default_backend() == new_backend
-
-
-def test_set_default_backend_fails_if_invalid_backend():
-    # type: () -> None
-    default_backend = get_default_backend()
-    with pytest.raises(Exception) as exc_info:
-        set_default_backend(object())
-    assert str(exc_info.value) == "backend must be an instance of GraphQLBackend."
-    assert get_default_backend() == default_backend
diff --git a/graphql/backend/tests/test_cache.py b/graphql/backend/tests/test_cache.py
deleted file mode 100644
index a20a18c..0000000
--- a/graphql/backend/tests/test_cache.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""Tests for `graphql.backend.cache` module."""
-
-import pytest
-
-from ..core import GraphQLCoreBackend
-from ..cache import GraphQLCachedBackend
-from graphql.execution.executors.sync import SyncExecutor
-from .schema import schema
-
-
-def test_cached_backend():
-    # type: () -> None
-    cached_backend = GraphQLCachedBackend(GraphQLCoreBackend())
-    document1 = cached_backend.document_from_string(schema, "{ hello }")
-    document2 = cached_backend.document_from_string(schema, "{ hello }")
-    assert document1 == document2
-
-
-def test_cached_backend_with_use_consistent_hash():
-    # type: () -> None
-    cached_backend = GraphQLCachedBackend(
-        GraphQLCoreBackend(), use_consistent_hash=True
-    )
-    document1 = cached_backend.document_from_string(schema, "{ hello }")
-    document2 = cached_backend.document_from_string(schema, "{ hello }")
-    assert document1 == document2
diff --git a/graphql/backend/tests/test_compileddocument.py b/graphql/backend/tests/test_compileddocument.py
deleted file mode 100644
index 787089a..0000000
--- a/graphql/backend/tests/test_compileddocument.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from ...language.base import parse
-from ...utils.ast_to_code import ast_to_code
-from ..compiled import GraphQLCompiledDocument
-from .schema import schema
-
-
-def test_compileddocument_from_module_dict():
-    # type: () -> None
-    document_string = "{ hello }"
-    document_ast = parse(document_string)
-    document = GraphQLCompiledDocument.from_module_dict(
-        schema,
-        {
-            "document_string": document_string,
-            "document_ast": document_ast,
-            "execute": lambda *_: True,
-        },
-    )
-    assert document.operations_map == {None: "query"}
-    assert document.document_string == document_string
-    assert document.document_ast == document_ast
-    assert document.schema == schema
-    assert document.execute()
-
-
-def test_compileddocument_from_code():
-    # type: () -> None
-    document_string = "{ hello }"
-    document_ast = parse(document_string)
-    code = '''
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from graphql.language import ast
-from graphql.language.parser import Loc
-from graphql.language.source import Source
-
-
-schema = None
-document_string = """{document_string}"""
-source = Source(document_string)
-
-
-def loc(start, end):
-    return Loc(start, end, source)
-
-document_ast = {document_ast}
-
-def execute(*_):
-    return True
-'''.format(
-        document_string=document_string, document_ast=ast_to_code(document_ast)
-    )
-    document = GraphQLCompiledDocument.from_code(schema, code)
-    assert document.operations_map == {None: "query"}
-    assert document.document_string == document_string
-    assert document.document_ast == document_ast
-    assert document.schema == schema
-    assert document.execute()
diff --git a/graphql/backend/tests/test_core.py b/graphql/backend/tests/test_core.py
deleted file mode 100644
index 257eb64..0000000
--- a/graphql/backend/tests/test_core.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""Tests for `graphql.backend.core` module."""
-
-import pytest
-from graphql.execution.executors.sync import SyncExecutor
-
-from ..base import GraphQLBackend, GraphQLDocument
-from ..core import GraphQLCoreBackend
-from .schema import schema
-
-if False:
-    from typing import Any
-
-
-def test_core_backend():
-    # type: () -> None
-    """Sample pytest test function with the pytest fixture as an argument."""
-    backend = GraphQLCoreBackend()
-    assert isinstance(backend, GraphQLBackend)
-    document = backend.document_from_string(schema, "{ hello }")
-    assert isinstance(document, GraphQLDocument)
-    result = document.execute()
-    assert not result.errors
-    assert result.data == {"hello": "World"}
-
-
-def test_backend_is_not_cached_by_default():
-    # type: () -> None
-    """Sample pytest test function with the pytest fixture as an argument."""
-    backend = GraphQLCoreBackend()
-    document1 = backend.document_from_string(schema, "{ hello }")
-    document2 = backend.document_from_string(schema, "{ hello }")
-    assert document1 != document2
-
-
-class BaseExecutor(SyncExecutor):
-    executed = False
-
-    def execute(self, *args, **kwargs):
-        # type: (*Any, **Any) -> str
-        self.executed = True
-        return super(BaseExecutor, self).execute(*args, **kwargs)
-
-
-def test_backend_can_execute_custom_executor():
-    # type: () -> None
-    executor = BaseExecutor()
-    backend = GraphQLCoreBackend(executor=executor)
-    document1 = backend.document_from_string(schema, "{ hello }")
-    result = document1.execute()
-    assert not result.errors
-    assert result.data == {"hello": "World"}
-    assert executor.executed
diff --git a/graphql/backend/tests/test_decider.py b/graphql/backend/tests/test_decider.py
deleted file mode 100644
index 32dccae..0000000
--- a/graphql/backend/tests/test_decider.py
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""Tests for `graphql.backend.decider` module."""
-
-import pytest
-from threading import Event
-
-from ..base import GraphQLBackend, GraphQLDocument
-from ..core import GraphQLCoreBackend
-from ..cache import GraphQLCachedBackend
-from ..decider import GraphQLDeciderBackend
-
-from .schema import schema
-
-if False:
-    from typing import Any
-
-
-class FakeBackend(GraphQLBackend):
-    def __init__(self, name, raises=False):
-        # type: (str, bool) -> None
-        self.raises = raises
-        self.name = name
-        self.event = Event()
-
-    @property
-    def reached(self):
-        return self.event.is_set()
-
-    def document_from_string(self, *args, **kwargs):
-        # type: (*Any, **Any) -> str
-        self.event.set()
-        if self.raises:
-            raise Exception("Backend failed")
-        return self.name
-
-    def wait(self):
-        return self.event.wait()
-
-    def reset(self):
-        # type: () -> None
-        self.event = Event()
-
-
-def test_decider_backend_healthy_backend():
-    # type: () -> None
-    backend1 = FakeBackend(name="main")
-    backend2 = FakeBackend(name="fallback")
-    decider_backend = GraphQLDeciderBackend(backend1, backend2)
-
-    document = decider_backend.document_from_string(schema, "{ hello }")
-    assert not backend1.reached
-    assert backend2.reached
-    assert document == "fallback"
-
-    backend1.wait()
-    backend1.reset()
-    backend2.reset()
-    document = decider_backend.document_from_string(schema, "{ hello }")
-    assert not backend1.reached
-    assert not backend2.reached
-    assert document == "main"
-
-
-def test_decider_backend_unhealthy_backend():
-    # type: () -> None
-    backend1 = FakeBackend(name="main", raises=True)
-    backend2 = FakeBackend(name="fallback")
-    decider_backend = GraphQLDeciderBackend(backend1, backend2)
-
-    document = decider_backend.document_from_string(schema, "{ hello }")
-    assert not backend1.reached
-    assert backend2.reached
-    assert document == "fallback"
-
-    backend1.wait()
-    backend1.reset()
-    backend2.reset()
-    document = decider_backend.document_from_string(schema, "{ hello }")
-
-    assert document == "fallback"
-    assert not backend1.reached
-    assert not backend2.reached
-
-
-def test_decider_old_syntax():
-    # type: () -> None
-    backend1 = FakeBackend(name="main", raises=True)
-    backend2 = FakeBackend(name="fallback")
-    decider_backend = GraphQLDeciderBackend([backend1, backend2])
-    assert decider_backend.backend is backend1
-    assert decider_backend.fallback_backend is backend2
-
-
-# def test_decider_backend_dont_use_cache():
-#     # type: () -> None
-#     backend1 = FakeBackend()
-#     backend2 = FakeBackend()
-#     decider_backend = GraphQLDeciderBackend([backend1, backend2])
-
-#     decider_backend.document_from_string(schema, "{ hello }")
-#     assert backend1.reached
-#     assert not backend2.reached
-
-#     backend1.reset()
-#     decider_backend.document_from_string(schema, "{ hello }")
-#     assert backend1.reached
-
-
-# def test_decider_backend_use_cache_if_provided():
-#     # type: () -> None
-#     backend1 = FakeBackend()
-#     backend2 = FakeBackend()
-#     decider_backend = GraphQLDeciderBackend(
-#         [GraphQLCachedBackend(backend1), GraphQLCachedBackend(backend2)]
-#     )
-
-#     decider_backend.document_from_string(schema, "{ hello }")
-#     assert backend1.reached
-#     assert not backend2.reached
-
-#     backend1.reset()
-#     decider_backend.document_from_string(schema, "{ hello }")
-#     assert not backend1.reached
diff --git a/graphql/backend/tests/test_document.py b/graphql/backend/tests/test_document.py
deleted file mode 100644
index e3b74c9..0000000
--- a/graphql/backend/tests/test_document.py
+++ /dev/null
@@ -1,83 +0,0 @@
-from ...language.base import parse
-from ..base import GraphQLDocument
-from .schema import schema
-from graphql.backend.base import GraphQLDocument
-
-
-def create_document(document_string):
-    # type: (str) -> GraphQLDocument
-    document_ast = parse(document_string)
-    return GraphQLDocument(
-        schema=schema,
-        document_string=document_string,
-        document_ast=document_ast,
-        execute=lambda *_: None,
-    )
-
-
-def test_document_operations_map_unnamed_operation():
-    # type: () -> None
-    document = create_document("{ hello }")
-    assert document.operations_map == {None: "query"}
-
-
-def test_document_operations_map_multiple_queries():
-    document = create_document(
-        """
-    query MyQuery1 { hello }
-    query MyQuery2 { hello }
-    """
-    )
-    assert document.operations_map == {"MyQuery1": "query", "MyQuery2": "query"}
-
-
-def test_document_operations_map_multiple_queries():
-    # type: () -> None
-    document = create_document(
-        """
-    query MyQuery { hello }
-    mutation MyMutation { hello }
-    subscription MySubscription { hello }
-    """
-    )
-    assert document.operations_map == {
-        "MyQuery": "query",
-        "MyMutation": "mutation",
-        "MySubscription": "subscription",
-    }
-
-
-def test_document_get_operation_type_unnamed_operation():
-    # type: () -> None
-    document = create_document(
-        """
-    query { hello }
-    """
-    )
-    assert document.get_operation_type(None) == "query"
-    assert document.get_operation_type("Unknown") is None
-
-
-def test_document_get_operation_type_multiple_operations():
-    # type: () -> None
-    document = create_document(
-        """
-    query MyQuery { hello }
-    mutation MyMutation {hello}
-    """
-    )
-    assert document.get_operation_type(None) is None
-    assert document.get_operation_type("MyQuery") == "query"
-    assert document.get_operation_type("MyMutation") == "mutation"
-    assert document.get_operation_type("Unexistent") is None
-
-
-def test_document_get_operation_type_multiple_operations_empty_operation_name():
-    # type: () -> None
-    document = create_document(
-        """
-    query MyQuery { hello }
-    mutation {hello}
-    """
-    )
-    assert document.get_operation_type(None) is "mutation"
diff --git a/graphql/error/__init__.py b/graphql/error/__init__.py
deleted file mode 100644
index 7a62771..0000000
--- a/graphql/error/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .base import GraphQLError
-from .located_error import GraphQLLocatedError
-from .syntax_error import GraphQLSyntaxError
-from .format_error import format_error
-
-__all__ = ["GraphQLError", "GraphQLLocatedError", "GraphQLSyntaxError", "format_error"]
diff --git a/graphql/error/base.py b/graphql/error/base.py
deleted file mode 100644
index 0aae96b..0000000
--- a/graphql/error/base.py
+++ /dev/null
@@ -1,83 +0,0 @@
-import six
-from ..language.location import get_location
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..language.source import Source
-    from ..language.location import SourceLocation
-    from types import TracebackType
-    from typing import Dict, Optional, List, Any, Union
-
-
-class GraphQLError(Exception):
-    __slots__ = (
-        "message",
-        "nodes",
-        "stack",
-        "original_error",
-        "_source",
-        "_positions",
-        "_locations",
-        "path",
-        "extensions",
-    )
-
-    def __init__(
-        self,
-        message,  # type: str
-        nodes=None,  # type: Any
-        stack=None,  # type: Optional[TracebackType]
-        source=None,  # type: Optional[Any]
-        positions=None,  # type: Optional[Any]
-        locations=None,  # type: Optional[Any]
-        path=None,  # type: Union[List[Union[int, str]], List[str], None]
-        extensions=None,  # type: Optional[Dict[str, Any]]
-    ):
-        # type: (...) -> None
-        super(GraphQLError, self).__init__(message)
-        self.message = message
-        self.nodes = nodes
-        self.stack = stack
-        self._source = source
-        self._positions = positions
-        self._locations = locations
-        self.path = path
-        self.extensions = extensions
-        return None
-
-    @property
-    def source(self):
-        # type: () -> Optional[Source]
-        if self._source:
-            return self._source
-        if self.nodes:
-            node = self.nodes[0]
-            return node and node.loc and node.loc.source
-        return None
-
-    @property
-    def positions(self):
-        # type: () -> Optional[List[int]]
-        if self._positions:
-            return self._positions
-        if self.nodes is not None:
-            node_positions = [node.loc and node.loc.start for node in self.nodes]
-            if any(node_positions):
-                return node_positions
-        return None
-
-    def reraise(self):
-        # type: () -> None
-        if self.stack:
-            six.reraise(type(self), self, self.stack)
-        else:
-            raise self
-
-    @property
-    def locations(self):
-        # type: () -> Optional[List[SourceLocation]]
-        if not self._locations:
-            source = self.source
-            if self.positions and source:
-                self._locations = [get_location(source, pos) for pos in self.positions]
-        return self._locations
diff --git a/graphql/error/format_error.py b/graphql/error/format_error.py
deleted file mode 100644
index adafd85..0000000
--- a/graphql/error/format_error.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from .base import GraphQLError
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Dict
-
-
-def format_error(error):
-    # type: (Exception) -> Dict[str, Any]
-    # Protect against UnicodeEncodeError when run in py2 (#216)
-    try:
-        message = str(error)
-    except UnicodeEncodeError:
-        message = error.message.encode("utf-8")  # type: ignore
-    formatted_error = {"message": message}  # type: Dict[str, Any]
-    if isinstance(error, GraphQLError):
-        if error.locations is not None:
-            formatted_error["locations"] = [
-                {"line": loc.line, "column": loc.column} for loc in error.locations
-            ]
-        if error.path is not None:
-            formatted_error["path"] = error.path
-
-        if error.extensions is not None:
-            formatted_error["extensions"] = error.extensions
-
-    return formatted_error
diff --git a/graphql/error/located_error.py b/graphql/error/located_error.py
deleted file mode 100644
index 3fe55a4..0000000
--- a/graphql/error/located_error.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import sys
-
-from .base import GraphQLError
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..language.ast import Field
-    from typing import List, Union
-
-__all__ = ["GraphQLLocatedError"]
-
-
-class GraphQLLocatedError(GraphQLError):
-    def __init__(
-        self,
-        nodes,  # type: List[Field]
-        original_error=None,  # type: Exception
-        path=None,  # type: Union[List[Union[int, str]], List[str]]
-    ):
-        # type: (...) -> None
-        if original_error:
-            try:
-                message = str(original_error)
-            except UnicodeEncodeError:
-                message = original_error.message.encode("utf-8")  # type: ignore
-        else:
-            message = "An unknown error occurred."
-
-        stack = (
-            original_error
-            and (
-                getattr(original_error, "stack", None)
-                # unfortunately, this is only available in Python 3:
-                or getattr(original_error, "__traceback__", None)
-            )
-            or sys.exc_info()[2]
-        )
-
-        extensions = (
-            getattr(original_error, "extensions", None) if original_error else None
-        )
-        super(GraphQLLocatedError, self).__init__(
-            message=message, nodes=nodes, stack=stack, path=path, extensions=extensions
-        )
-        self.original_error = original_error
diff --git a/graphql/error/syntax_error.py b/graphql/error/syntax_error.py
deleted file mode 100644
index d38adc1..0000000
--- a/graphql/error/syntax_error.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from ..language.location import get_location
-from .base import GraphQLError
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..language.source import Source
-    from ..language.location import SourceLocation
-
-__all__ = ["GraphQLSyntaxError"]
-
-
-class GraphQLSyntaxError(GraphQLError):
-    def __init__(self, source, position, description):
-        # type: (Source, int, str) -> None
-        location = get_location(source, position)
-        super(GraphQLSyntaxError, self).__init__(
-            message=u"Syntax Error {} ({}:{}) {}\n\n{}".format(
-                source.name,
-                location.line,
-                location.column,
-                description,
-                highlight_source_at_location(source, location),
-            ),
-            source=source,
-            positions=[position],
-        )
-
-
-def highlight_source_at_location(source, location):
-    # type: (Source, SourceLocation) -> str
-    line = location.line
-    lines = source.body.splitlines()
-    pad_len = len(str(line + 1))
-    result = u""
-    format = (u"{:>" + str(pad_len) + "}: {}\n").format
-    if line >= 2:
-        result += format(line - 1, lines[line - 2])
-    if line <= len(lines):
-        result += format(line, lines[line - 1])
-        result += " " * (1 + pad_len + location.column) + "^\n"
-    if line < len(lines):
-        result += format(line + 1, lines[line])
-    return result
diff --git a/graphql/error/tests/__init__.py b/graphql/error/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py
deleted file mode 100644
index 3ddc091..0000000
--- a/graphql/error/tests/test_base.py
+++ /dev/null
@@ -1,101 +0,0 @@
-import sys
-
-import pytest
-import traceback
-
-from promise import Promise
-
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from graphql.execution.base import ResolveInfo
-    from typing import Any
-    from typing import Optional
-
-
-def test_raise():
-    # type: () -> None
-    ast = parse("query Example { a }")
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> None
-        raise Exception("Failed")
-
-    Type = GraphQLObjectType(
-        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)}
-    )
-
-    result = execute(GraphQLSchema(Type), ast)
-    assert str(result.errors[0]) == "Failed"
-
-
-def test_reraise():
-    # type: () -> None
-    ast = parse("query Example { a }")
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> None
-        raise Exception("Failed")
-
-    Type = GraphQLObjectType(
-        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)}
-    )
-
-    result = execute(GraphQLSchema(Type), ast)
-    with pytest.raises(Exception) as exc_info:
-        result.errors[0].reraise()
-
-    extracted = traceback.extract_tb(exc_info.tb)
-    formatted_tb = [row[2:] for row in extracted]
-    formatted_tb = [tb for tb in formatted_tb if tb[0] != "reraise"]
-
-    assert formatted_tb == [
-        ("test_reraise", "result.errors[0].reraise()"),
-        (
-            "resolve_or_error",
-            "return executor.execute(resolve_fn, source, info, **args)",
-        ),
-        ("execute", "return fn(*args, **kwargs)"),
-        ("resolver", 'raise Exception("Failed")'),
-    ]
-
-    assert str(exc_info.value) == "Failed"
-
-
-@pytest.mark.skipif(sys.version_info < (3,), reason="this works only with Python 3")
-def test_reraise_from_promise():
-    # type: () -> None
-    ast = parse("query Example { a }")
-
-    def fail():
-        raise Exception("Failed")
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> None
-        return Promise(lambda resolve, reject: resolve(fail()))
-
-    Type = GraphQLObjectType(
-        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)}
-    )
-
-    result = execute(GraphQLSchema(Type), ast)
-    with pytest.raises(Exception) as exc_info:
-        result.errors[0].reraise()
-
-    extracted = traceback.extract_tb(exc_info.tb)
-    formatted_tb = [row[2:] for row in extracted]
-    formatted_tb = [tb for tb in formatted_tb if tb[0] != "reraise"]
-
-    print(formatted_tb)
-
-    assert formatted_tb == [
-        ("test_reraise_from_promise", "result.errors[0].reraise()"),
-        ("_resolve_from_executor", "executor(resolve, reject)"),
-        ("<lambda>", "return Promise(lambda resolve, reject: resolve(fail()))"),
-        ("fail", 'raise Exception("Failed")'),
-    ]
-
-    assert str(exc_info.value) == "Failed"
diff --git a/graphql/execution/__init__.py b/graphql/execution/__init__.py
deleted file mode 100644
index d6c2a7f..0000000
--- a/graphql/execution/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Terminology
-
-"Definitions" are the generic name for top-level statements in the document.
-Examples of this include:
-1) Operations (such as a query)
-2) Fragments
-
-"Operations" are a generic name for requests in the document.
-Examples of this include:
-1) query,
-2) mutation
-
-"Selections" are the statements that can appear legally and at
-single level of the query. These include:
-1) field references e.g "a"
-2) fragment "spreads" e.g. "...c"
-3) inline fragment "spreads" e.g. "...on Type { a }"
-"""
-from .executor import execute, subscribe
-from .base import ExecutionResult, ResolveInfo
-from .middleware import middlewares, MiddlewareManager
-
-
-__all__ = [
-    "execute",
-    "subscribe",
-    "ExecutionResult",
-    "ResolveInfo",
-    "MiddlewareManager",
-    "middlewares",
-]
diff --git a/graphql/execution/base.py b/graphql/execution/base.py
deleted file mode 100644
index d71151a..0000000
--- a/graphql/execution/base.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# We keep the following imports to preserve compatibility
-from .utils import (
-    ExecutionContext,
-    SubscriberExecutionContext,
-    get_operation_root_type,
-    collect_fields,
-    should_include_node,
-    does_fragment_condition_match,
-    get_field_entry_key,
-    default_resolve_fn,
-    get_field_def,
-)
-from ..pyutils.ordereddict import OrderedDict
-from ..error.format_error import format_error as default_format_error
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Optional, Dict, List, Union, Callable, Type
-    from ..language.ast import Field, OperationDefinition
-    from ..type.definition import GraphQLList, GraphQLObjectType, GraphQLScalarType
-    from ..type.schema import GraphQLSchema
-
-
-class ExecutionResult(object):
-    """The result of execution. `data` is the result of executing the
-    query, `errors` is null if no errors occurred, and is a
-    non-empty array if an error occurred."""
-
-    __slots__ = "data", "errors", "invalid", "extensions"
-
-    def __init__(self, data=None, errors=None, invalid=False, extensions=None):
-        # type: (Optional[Dict], Optional[List[Exception]], bool, Optional[Any]) -> None
-        self.data = data
-        self.errors = errors
-        self.extensions = extensions or dict()
-
-        if invalid:
-            assert data is None
-
-        self.invalid = invalid
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ExecutionResult)
-            and self.data == other.data
-            and self.errors == other.errors
-            and self.invalid == other.invalid
-        )
-
-    def to_dict(self, format_error=None, dict_class=OrderedDict):
-        # type: (Optional[Callable[[Exception], Dict]], Type[Dict]) -> Dict[str, Any]
-        if format_error is None:
-            format_error = default_format_error
-
-        response = dict_class()
-        if self.errors:
-            response["errors"] = [format_error(e) for e in self.errors]
-
-        if not self.invalid:
-            response["data"] = self.data
-
-        return response
-
-
-class ResolveInfo(object):
-    __slots__ = (
-        "field_name",
-        "field_asts",
-        "return_type",
-        "parent_type",
-        "schema",
-        "fragments",
-        "root_value",
-        "operation",
-        "variable_values",
-        "context",
-        "path",
-    )
-
-    def __init__(
-        self,
-        field_name,  # type: str
-        field_asts,  # type: List[Field]
-        return_type,  # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType]
-        parent_type,  # type: GraphQLObjectType
-        schema,  # type: GraphQLSchema
-        fragments,  # type: Dict
-        root_value,  # type: Optional[type]
-        operation,  # type: OperationDefinition
-        variable_values,  # type: Dict
-        context,  # type: Optional[Any]
-        path=None,  # type: Union[List[Union[int, str]], List[str]]
-    ):
-        # type: (...) -> None
-        self.field_name = field_name
-        self.field_asts = field_asts
-        self.return_type = return_type
-        self.parent_type = parent_type
-        self.schema = schema
-        self.fragments = fragments
-        self.root_value = root_value
-        self.operation = operation
-        self.variable_values = variable_values
-        self.context = context
-        self.path = path
-
-
-__all__ = [
-    "ExecutionResult",
-    "ResolveInfo",
-    "ExecutionContext",
-    "SubscriberExecutionContext",
-    "get_operation_root_type",
-    "collect_fields",
-    "should_include_node",
-    "does_fragment_condition_match",
-    "get_field_entry_key",
-    "default_resolve_fn",
-    "get_field_def",
-]
diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py
deleted file mode 100644
index e77050e..0000000
--- a/graphql/execution/executor.py
+++ /dev/null
@@ -1,741 +0,0 @@
-import collections
-
-try:
-    from collections.abc import Iterable
-except ImportError:  # Python < 3.3
-    from collections import Iterable
-import functools
-import logging
-import sys
-import warnings
-from rx import Observable
-
-from six import string_types
-from promise import Promise, promise_for_dict, is_thenable
-
-from ..error import GraphQLError, GraphQLLocatedError
-from ..pyutils.default_ordered_dict import DefaultOrderedDict
-from ..pyutils.ordereddict import OrderedDict
-from ..utils.undefined import Undefined
-from ..type import (
-    GraphQLEnumType,
-    GraphQLInterfaceType,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLScalarType,
-    GraphQLSchema,
-    GraphQLUnionType,
-)
-from .base import (
-    ExecutionContext,
-    ExecutionResult,
-    ResolveInfo,
-    collect_fields,
-    default_resolve_fn,
-    get_field_def,
-    get_operation_root_type,
-    SubscriberExecutionContext,
-)
-from .executors.sync import SyncExecutor
-from .middleware import MiddlewareManager
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Optional, Union, Dict, List, Callable
-    from ..language.ast import Document, OperationDefinition, Field
-
-logger = logging.getLogger(__name__)
-
-
-def subscribe(*args, **kwargs):
-    # type: (*Any, **Any) -> Union[ExecutionResult, Observable]
-    allow_subscriptions = kwargs.pop("allow_subscriptions", True)
-    return execute(  # type: ignore
-        *args, allow_subscriptions=allow_subscriptions, **kwargs
-    )
-
-
-def execute(
-    schema,  # type: GraphQLSchema
-    document_ast,  # type: Document
-    root=None,  # type: Any
-    context=None,  # type: Optional[Any]
-    variables=None,  # type: Optional[Any]
-    operation_name=None,  # type: Optional[str]
-    executor=None,  # type: Any
-    return_promise=False,  # type: bool
-    middleware=None,  # type: Optional[Any]
-    allow_subscriptions=False,  # type: bool
-    **options  # type: Any
-):
-    # type: (...) -> Union[ExecutionResult, Promise[ExecutionResult]]
-
-    if root is None and "root_value" in options:
-        warnings.warn(
-            "root_value has been deprecated. Please use root=... instead.",
-            category=DeprecationWarning,
-            stacklevel=2,
-        )
-        root = options["root_value"]
-    if context is None and "context_value" in options:
-        warnings.warn(
-            "context_value has been deprecated. Please use context=... instead.",
-            category=DeprecationWarning,
-            stacklevel=2,
-        )
-        context = options["context_value"]
-    if variables is None and "variable_values" in options:
-        warnings.warn(
-            "variable_values has been deprecated. Please use variables=... instead.",
-            category=DeprecationWarning,
-            stacklevel=2,
-        )
-        variables = options["variable_values"]
-    assert schema, "Must provide schema"
-    assert isinstance(schema, GraphQLSchema), (
-        "Schema must be an instance of GraphQLSchema. Also ensure that there are "
-        + "not multiple versions of GraphQL installed in your node_modules directory."
-    )
-
-    if middleware:
-        if not isinstance(middleware, MiddlewareManager):
-            middleware = MiddlewareManager(*middleware)
-
-        assert isinstance(middleware, MiddlewareManager), (
-            "middlewares have to be an instance"
-            ' of MiddlewareManager. Received "{}".'.format(middleware)
-        )
-
-    if executor is None:
-        executor = SyncExecutor()
-
-    exe_context = ExecutionContext(
-        schema,
-        document_ast,
-        root,
-        context,
-        variables or {},
-        operation_name,
-        executor,
-        middleware,
-        allow_subscriptions,
-    )
-
-    def promise_executor(v):
-        # type: (Optional[Any]) -> Union[Dict, Promise[Dict], Observable]
-        return execute_operation(exe_context, exe_context.operation, root)
-
-    def on_rejected(error):
-        # type: (Exception) -> None
-        exe_context.errors.append(error)
-        return None
-
-    def on_resolve(data):
-        # type: (Union[None, Dict, Observable]) -> Union[ExecutionResult, Observable]
-        if isinstance(data, Observable):
-            return data
-
-        if not exe_context.errors:
-            return ExecutionResult(data=data)
-
-        return ExecutionResult(data=data, errors=exe_context.errors)
-
-    promise = (
-        Promise.resolve(None).then(promise_executor).catch(on_rejected).then(on_resolve)
-    )
-
-    if not return_promise:
-        exe_context.executor.wait_until_finished()
-        return promise.get()
-    else:
-        clean = getattr(exe_context.executor, "clean", None)
-        if clean:
-            clean()
-
-    return promise
-
-
-def execute_operation(
-    exe_context,  # type: ExecutionContext
-    operation,  # type: OperationDefinition
-    root_value,  # type: Any
-):
-    # type: (...) -> Union[Dict, Promise[Dict]]
-    type = get_operation_root_type(exe_context.schema, operation)
-    fields = collect_fields(
-        exe_context, type, operation.selection_set, DefaultOrderedDict(list), set()
-    )
-
-    if operation.operation == "mutation":
-        return execute_fields_serially(exe_context, type, root_value, [], fields)
-
-    if operation.operation == "subscription":
-        if not exe_context.allow_subscriptions:
-            raise Exception(
-                "Subscriptions are not allowed. "
-                "You will need to either use the subscribe function "
-                "or pass allow_subscriptions=True"
-            )
-        return subscribe_fields(exe_context, type, root_value, fields)
-
-    return execute_fields(exe_context, type, root_value, fields, [], None)
-
-
-def execute_fields_serially(
-    exe_context,  # type: ExecutionContext
-    parent_type,  # type: GraphQLObjectType
-    source_value,  # type: Any
-    path,  # type: List
-    fields,  # type: DefaultOrderedDict
-):
-    # type: (...) -> Promise
-    def execute_field_callback(results, response_name):
-        # type: (Dict, str) -> Union[Dict, Promise[Dict]]
-        field_asts = fields[response_name]
-        result = resolve_field(
-            exe_context,
-            parent_type,
-            source_value,
-            field_asts,
-            None,
-            path + [response_name],
-        )
-        if result is Undefined:
-            return results
-
-        if is_thenable(result):
-
-            def collect_result(resolved_result):
-                # type: (Dict) -> Dict
-                results[response_name] = resolved_result
-                return results
-
-            return result.then(collect_result, None)
-
-        results[response_name] = result
-        return results
-
-    def execute_field(prev_promise, response_name):
-        # type: (Promise, str) -> Promise
-        return prev_promise.then(
-            lambda results: execute_field_callback(results, response_name)
-        )
-
-    return functools.reduce(
-        execute_field, fields.keys(), Promise.resolve(collections.OrderedDict())
-    )
-
-
-def execute_fields(
-    exe_context,  # type: ExecutionContext
-    parent_type,  # type: GraphQLObjectType
-    source_value,  # type: Any
-    fields,  # type: DefaultOrderedDict
-    path,  # type: List[Union[int, str]]
-    info,  # type: Optional[ResolveInfo]
-):
-    # type: (...) -> Union[Dict, Promise[Dict]]
-    contains_promise = False
-
-    final_results = OrderedDict()
-
-    for response_name, field_asts in fields.items():
-        result = resolve_field(
-            exe_context,
-            parent_type,
-            source_value,
-            field_asts,
-            info,
-            path + [response_name],
-        )
-        if result is Undefined:
-            continue
-
-        final_results[response_name] = result
-        if is_thenable(result):
-            contains_promise = True
-
-    if not contains_promise:
-        return final_results
-
-    return promise_for_dict(final_results)
-
-
-def subscribe_fields(
-    exe_context,  # type: ExecutionContext
-    parent_type,  # type: GraphQLObjectType
-    source_value,  # type: Any
-    fields,  # type: DefaultOrderedDict
-):
-    # type: (...) -> Observable
-    subscriber_exe_context = SubscriberExecutionContext(exe_context)
-
-    def on_error(error):
-        subscriber_exe_context.report_error(error)
-
-    def map_result(data):
-        # type: (Dict[str, Any]) -> ExecutionResult
-        if subscriber_exe_context.errors:
-            result = ExecutionResult(data=data, errors=subscriber_exe_context.errors)
-        else:
-            result = ExecutionResult(data=data)
-        subscriber_exe_context.reset()
-        return result
-
-    observables = []  # type: List[Observable]
-
-    # assert len(fields) == 1, "Can only subscribe one element at a time."
-
-    for response_name, field_asts in fields.items():
-        result = subscribe_field(
-            subscriber_exe_context,
-            parent_type,
-            source_value,
-            field_asts,
-            [response_name],
-        )
-        if result is Undefined:
-            continue
-
-        def catch_error(error):
-            subscriber_exe_context.errors.append(error)
-            return Observable.just(None)
-
-        # Map observable results
-        observable = result.catch_exception(catch_error).map(
-            lambda data: map_result({response_name: data})
-        )
-        return observable
-        observables.append(observable)
-
-    return Observable.merge(observables)
-
-
-def resolve_field(
-    exe_context,  # type: ExecutionContext
-    parent_type,  # type: GraphQLObjectType
-    source,  # type: Any
-    field_asts,  # type: List[Field]
-    parent_info,  # type: Optional[ResolveInfo]
-    field_path,  # type: List[Union[int, str]]
-):
-    # type: (...) -> Any
-    field_ast = field_asts[0]
-    field_name = field_ast.name.value
-
-    field_def = get_field_def(exe_context.schema, parent_type, field_name)
-    if not field_def:
-        return Undefined
-
-    return_type = field_def.type
-    resolve_fn = field_def.resolver or default_resolve_fn
-
-    # We wrap the resolve_fn from the middleware
-    resolve_fn_middleware = exe_context.get_field_resolver(resolve_fn)
-
-    # Build a dict of arguments from the field.arguments AST, using the variables scope to
-    # fulfill any variable references.
-    args = exe_context.get_argument_values(field_def, field_ast)
-
-    # The resolve function's optional third argument is a context value that
-    # is provided to every resolve function within an execution. It is commonly
-    # used to represent an authenticated user, or request-specific caches.
-    context = exe_context.context_value
-
-    # The resolve function's optional third argument is a collection of
-    # information about the current execution state.
-    info = ResolveInfo(
-        field_name,
-        field_asts,
-        return_type,
-        parent_type,
-        schema=exe_context.schema,
-        fragments=exe_context.fragments,
-        root_value=exe_context.root_value,
-        operation=exe_context.operation,
-        variable_values=exe_context.variable_values,
-        context=context,
-        path=field_path,
-    )
-
-    executor = exe_context.executor
-    result = resolve_or_error(resolve_fn_middleware, source, info, args, executor)
-
-    return complete_value_catching_error(
-        exe_context, return_type, field_asts, info, field_path, result
-    )
-
-
-def subscribe_field(
-    exe_context,  # type: SubscriberExecutionContext
-    parent_type,  # type: GraphQLObjectType
-    source,  # type: Any
-    field_asts,  # type: List[Field]
-    path,  # type: List[str]
-):
-    # type: (...) -> Observable
-    field_ast = field_asts[0]
-    field_name = field_ast.name.value
-
-    field_def = get_field_def(exe_context.schema, parent_type, field_name)
-    if not field_def:
-        return Undefined
-
-    return_type = field_def.type
-    resolve_fn = field_def.resolver or default_resolve_fn
-
-    # We wrap the resolve_fn from the middleware
-    resolve_fn_middleware = exe_context.get_field_resolver(resolve_fn)
-
-    # Build a dict of arguments from the field.arguments AST, using the variables scope to
-    # fulfill any variable references.
-    args = exe_context.get_argument_values(field_def, field_ast)
-
-    # The resolve function's optional third argument is a context value that
-    # is provided to every resolve function within an execution. It is commonly
-    # used to represent an authenticated user, or request-specific caches.
-    context = exe_context.context_value
-
-    # The resolve function's optional third argument is a collection of
-    # information about the current execution state.
-    info = ResolveInfo(
-        field_name,
-        field_asts,
-        return_type,
-        parent_type,
-        schema=exe_context.schema,
-        fragments=exe_context.fragments,
-        root_value=exe_context.root_value,
-        operation=exe_context.operation,
-        variable_values=exe_context.variable_values,
-        context=context,
-        path=path,
-    )
-
-    executor = exe_context.executor
-    result = resolve_or_error(resolve_fn_middleware, source, info, args, executor)
-
-    if isinstance(result, Exception):
-        raise result
-
-    if not isinstance(result, Observable):
-        raise GraphQLError(
-            "Subscription must return Async Iterable or Observable. Received: {}".format(
-                repr(result)
-            )
-        )
-
-    return result.map(
-        functools.partial(
-            complete_value_catching_error,
-            exe_context,
-            return_type,
-            field_asts,
-            info,
-            path,
-        )
-    )
-
-
-def resolve_or_error(
-    resolve_fn,  # type: Callable
-    source,  # type: Any
-    info,  # type: ResolveInfo
-    args,  # type: Dict
-    executor,  # type: Any
-):
-    # type: (...) -> Any
-    try:
-        return executor.execute(resolve_fn, source, info, **args)
-    except Exception as e:
-        logger.exception(
-            "An error occurred while resolving field {}.{}".format(
-                info.parent_type.name, info.field_name
-            )
-        )
-        e.stack = sys.exc_info()[2]  # type: ignore
-        return e
-
-
-def complete_value_catching_error(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: Any
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Any
-    # If the field type is non-nullable, then it is resolved without any
-    # protection from errors.
-    if isinstance(return_type, GraphQLNonNull):
-        return complete_value(exe_context, return_type, field_asts, info, path, result)
-
-    # Otherwise, error protection is applied, logging the error and
-    # resolving a null value for this field if one is encountered.
-    try:
-        completed = complete_value(
-            exe_context, return_type, field_asts, info, path, result
-        )
-        if is_thenable(completed):
-
-            def handle_error(error):
-                # type: (Union[GraphQLError, GraphQLLocatedError]) -> Optional[Any]
-                traceback = completed._traceback  # type: ignore
-                exe_context.report_error(error, traceback)
-                return None
-
-            return completed.catch(handle_error)
-
-        return completed
-    except Exception as e:
-        traceback = sys.exc_info()[2]
-        exe_context.report_error(e, traceback)
-        return None
-
-
-def complete_value(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: Any
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Any
-    """
-    Implements the instructions for completeValue as defined in the
-    "Field entries" section of the spec.
-
-    If the field type is Non-Null, then this recursively completes the value for the inner type. It throws a field
-    error if that completion returns null, as per the "Nullability" section of the spec.
-
-    If the field type is a List, then this recursively completes the value for the inner type on each item in the
-    list.
-
-    If the field type is a Scalar or Enum, ensures the completed value is a legal value of the type by calling the
-    `serialize` method of GraphQL type definition.
-
-    If the field is an abstract type, determine the runtime type of the value and then complete based on that type.
-
-    Otherwise, the field type expects a sub-selection set, and will complete the value by evaluating all
-    sub-selections.
-    """
-    # If field type is NonNull, complete for inner type, and throw field error
-    # if result is null.
-    if is_thenable(result):
-        return Promise.resolve(result).then(
-            lambda resolved: complete_value(
-                exe_context, return_type, field_asts, info, path, resolved
-            ),
-            lambda error: Promise.rejected(
-                GraphQLLocatedError(field_asts, original_error=error, path=path)
-            ),
-        )
-
-    # print return_type, type(result)
-    if isinstance(result, Exception):
-        raise GraphQLLocatedError(field_asts, original_error=result, path=path)
-
-    if isinstance(return_type, GraphQLNonNull):
-        return complete_nonnull_value(
-            exe_context, return_type, field_asts, info, path, result
-        )
-
-    # If result is null-like, return null.
-    if result is None:
-        return None
-
-    # If field type is List, complete each item in the list with the inner type
-    if isinstance(return_type, GraphQLList):
-        return complete_list_value(
-            exe_context, return_type, field_asts, info, path, result
-        )
-
-    # If field type is Scalar or Enum, serialize to a valid value, returning
-    # null if coercion is not possible.
-    if isinstance(return_type, (GraphQLScalarType, GraphQLEnumType)):
-        return complete_leaf_value(return_type, path, result)
-
-    if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
-        return complete_abstract_value(
-            exe_context, return_type, field_asts, info, path, result
-        )
-
-    if isinstance(return_type, GraphQLObjectType):
-        return complete_object_value(
-            exe_context, return_type, field_asts, info, path, result
-        )
-
-    assert False, u'Cannot complete value of unexpected type "{}".'.format(return_type)
-
-
-def complete_list_value(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: GraphQLList
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> List[Any]
-    """
-    Complete a list value by completing each item in the list with the inner type
-    """
-    assert isinstance(result, Iterable), (
-        "User Error: expected iterable, but did not find one " + "for field {}.{}."
-    ).format(info.parent_type, info.field_name)
-
-    item_type = return_type.of_type
-    completed_results = []
-    contains_promise = False
-
-    index = 0
-    for item in result:
-        completed_item = complete_value_catching_error(
-            exe_context, item_type, field_asts, info, path + [index], item
-        )
-        if not contains_promise and is_thenable(completed_item):
-            contains_promise = True
-
-        completed_results.append(completed_item)
-        index += 1
-
-    return Promise.all(completed_results) if contains_promise else completed_results
-
-
-def complete_leaf_value(
-    return_type,  # type: Union[GraphQLEnumType, GraphQLScalarType]
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Union[int, str, float, bool]
-    """
-    Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible.
-    """
-    assert hasattr(return_type, "serialize"), "Missing serialize method on type"
-    serialized_result = return_type.serialize(result)
-
-    if serialized_result is None:
-        raise GraphQLError(
-            ('Expected a value of type "{}" but ' + "received: {}").format(
-                return_type, result
-            ),
-            path=path,
-        )
-    return serialized_result
-
-
-def complete_abstract_value(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: Union[GraphQLInterfaceType, GraphQLUnionType]
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Dict[str, Any]
-    """
-    Complete an value of an abstract type by determining the runtime type of that value, then completing based
-    on that type.
-    """
-    runtime_type = None  # type: Union[str, GraphQLObjectType, None]
-
-    # Field type must be Object, Interface or Union and expect sub-selections.
-    if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
-        if return_type.resolve_type:
-            runtime_type = return_type.resolve_type(result, info)
-        else:
-            runtime_type = get_default_resolve_type_fn(result, info, return_type)
-
-    if isinstance(runtime_type, string_types):
-        runtime_type = info.schema.get_type(runtime_type)  # type: ignore
-
-    if not isinstance(runtime_type, GraphQLObjectType):
-        raise GraphQLError(
-            (
-                "Abstract type {} must resolve to an Object type at runtime "
-                + 'for field {}.{} with value "{}", received "{}".'
-            ).format(
-                return_type, info.parent_type, info.field_name, result, runtime_type
-            ),
-            field_asts,
-        )
-
-    if not exe_context.schema.is_possible_type(return_type, runtime_type):
-        raise GraphQLError(
-            u'Runtime Object type "{}" is not a possible type for "{}".'.format(
-                runtime_type, return_type
-            ),
-            field_asts,
-        )
-
-    return complete_object_value(
-        exe_context, runtime_type, field_asts, info, path, result
-    )
-
-
-def get_default_resolve_type_fn(
-    value,  # type: Any
-    info,  # type: ResolveInfo
-    abstract_type,  # type: Union[GraphQLInterfaceType, GraphQLUnionType]
-):
-    # type: (...) -> Optional[GraphQLObjectType]
-    possible_types = info.schema.get_possible_types(abstract_type)
-    for type in possible_types:
-        if callable(type.is_type_of) and type.is_type_of(value, info):
-            return type
-    return None
-
-
-def complete_object_value(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: GraphQLObjectType
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Dict[str, Any]
-    """
-    Complete an Object value by evaluating all sub-selections.
-    """
-    if return_type.is_type_of and not return_type.is_type_of(result, info):
-        raise GraphQLError(
-            u'Expected value of type "{}" but got: {}.'.format(
-                return_type, type(result).__name__
-            ),
-            field_asts,
-        )
-
-    # Collect sub-fields to execute to complete this value.
-    subfield_asts = exe_context.get_sub_fields(return_type, field_asts)
-    return execute_fields(exe_context, return_type, result, subfield_asts, path, info)
-
-
-def complete_nonnull_value(
-    exe_context,  # type: ExecutionContext
-    return_type,  # type: GraphQLNonNull
-    field_asts,  # type: List[Field]
-    info,  # type: ResolveInfo
-    path,  # type: List[Union[int, str]]
-    result,  # type: Any
-):
-    # type: (...) -> Any
-    """
-    Complete a NonNull value by completing the inner type
-    """
-    completed = complete_value(
-        exe_context, return_type.of_type, field_asts, info, path, result
-    )
-    if completed is None:
-        raise GraphQLError(
-            "Cannot return null for non-nullable field {}.{}.".format(
-                info.parent_type, info.field_name
-            ),
-            field_asts,
-            path=path,
-        )
-
-    return completed
diff --git a/graphql/execution/executors/__init__.py b/graphql/execution/executors/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/execution/executors/asyncio.py b/graphql/execution/executors/asyncio.py
deleted file mode 100644
index 7e01403..0000000
--- a/graphql/execution/executors/asyncio.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from __future__ import absolute_import
-
-from asyncio import Future, get_event_loop, iscoroutine, wait
-
-from promise import Promise
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from asyncio.unix_events import _UnixSelectorEventLoop
-    from typing import Optional, Any, Callable, List
-
-try:
-    from asyncio import ensure_future
-except ImportError:
-    # ensure_future is only implemented in Python 3.4.4+
-    def ensure_future(coro_or_future, loop=None):  # type: ignore
-        """Wrap a coroutine or an awaitable in a future.
-
-        If the argument is a Future, it is returned directly.
-        """
-        if isinstance(coro_or_future, Future):
-            if loop is not None and loop is not coro_or_future._loop:
-                raise ValueError("loop argument must agree with Future")
-            return coro_or_future
-        elif iscoroutine(coro_or_future):
-            if loop is None:
-                loop = get_event_loop()
-            task = loop.create_task(coro_or_future)
-            if task._source_traceback:
-                del task._source_traceback[-1]
-            return task
-        else:
-            raise TypeError("A Future, a coroutine or an awaitable is required")
-
-
-try:
-    from .asyncio_utils import asyncgen_to_observable, isasyncgen
-except Exception:
-
-    def isasyncgen(object):  # type: ignore
-        False
-
-    def asyncgen_to_observable(asyncgen, loop=None):
-        pass
-
-
-class AsyncioExecutor(object):
-    def __init__(self, loop=None):
-        # type: (Optional[_UnixSelectorEventLoop]) -> None
-        if loop is None:
-            loop = get_event_loop()
-        self.loop = loop
-        self.futures = []  # type: List[Future]
-
-    def wait_until_finished(self):
-        # type: () -> None
-        # if there are futures to wait for
-        while self.futures:
-            # wait for the futures to finish
-            futures = self.futures
-            self.futures = []
-            self.loop.run_until_complete(wait(futures))
-
-    def clean(self):
-        self.futures = []
-
-    def execute(self, fn, *args, **kwargs):
-        # type: (Callable, *Any, **Any) -> Any
-        result = fn(*args, **kwargs)
-        if isinstance(result, Future) or iscoroutine(result):
-            future = ensure_future(result, loop=self.loop)
-            self.futures.append(future)
-            return Promise.resolve(future)
-        elif isasyncgen(result):
-            return asyncgen_to_observable(result, loop=self.loop)
-        return result
diff --git a/graphql/execution/executors/asyncio_utils.py b/graphql/execution/executors/asyncio_utils.py
deleted file mode 100644
index 17ec5c7..0000000
--- a/graphql/execution/executors/asyncio_utils.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from inspect import isasyncgen  # type: ignore
-from asyncio import ensure_future, wait, CancelledError
-from rx import AnonymousObservable
-
-
-def asyncgen_to_observable(asyncgen, loop=None):
-    def emit(observer):
-        task = ensure_future(iterate_asyncgen(asyncgen, observer), loop=loop)
-
-        def dispose():
-            async def await_task():
-                await task
-
-            task.cancel()
-            ensure_future(await_task(), loop=loop)
-
-        return dispose
-
-    return AnonymousObservable(emit)
-
-
-async def iterate_asyncgen(asyncgen, observer):
-    try:
-        async for item in asyncgen:
-            observer.on_next(item)
-        observer.on_completed()
-    except CancelledError:
-        pass
-    except Exception as e:
-        observer.on_error(e)
diff --git a/graphql/execution/executors/gevent.py b/graphql/execution/executors/gevent.py
deleted file mode 100644
index 4bc5ac4..0000000
--- a/graphql/execution/executors/gevent.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import absolute_import
-
-import gevent
-from promise import Promise
-
-from .utils import process
-
-
-class GeventExecutor(object):
-    def __init__(self):
-        self.jobs = []
-
-    def wait_until_finished(self):
-        # gevent.joinall(self.jobs)
-        while self.jobs:
-            jobs = self.jobs
-            self.jobs = []
-            [j.join() for j in jobs]
-
-    def clean(self):
-        self.jobs = []
-
-    def execute(self, fn, *args, **kwargs):
-        promise = Promise()
-        job = gevent.spawn(process, promise, fn, args, kwargs)
-        self.jobs.append(job)
-        return promise
diff --git a/graphql/execution/executors/process.py b/graphql/execution/executors/process.py
deleted file mode 100644
index 948279a..0000000
--- a/graphql/execution/executors/process.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from multiprocessing import Process, Queue
-
-from promise import Promise
-
-from .utils import process
-
-
-def queue_process(q):
-    promise, fn, args, kwargs = q.get()
-    process(promise, fn, args, kwargs)
-
-
-class ProcessExecutor(object):
-    def __init__(self):
-        self.processes = []
-        self.q = Queue()
-
-    def wait_until_finished(self):
-        while self.processes:
-            processes = self.processes
-            self.processes = []
-            [_process.join() for _process in processes]
-        self.q.close()
-        self.q.join_thread()
-
-    def clean(self):
-        self.processes = []
-
-    def execute(self, fn, *args, **kwargs):
-        promise = Promise()
-
-        self.q.put([promise, fn, args, kwargs], False)
-        _process = Process(target=queue_process, args=(self.q))
-        _process.start()
-        self.processes.append(_process)
-        return promise
diff --git a/graphql/execution/executors/sync.py b/graphql/execution/executors/sync.py
deleted file mode 100644
index c45d8a8..0000000
--- a/graphql/execution/executors/sync.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Callable
-
-
-class SyncExecutor(object):
-    def wait_until_finished(self):
-        # type: () -> None
-        pass
-
-    def clean(self):
-        pass
-
-    def execute(self, fn, *args, **kwargs):
-        # type: (Callable, *Any, **Any) -> Any
-        return fn(*args, **kwargs)
diff --git a/graphql/execution/executors/thread.py b/graphql/execution/executors/thread.py
deleted file mode 100644
index f540a1a..0000000
--- a/graphql/execution/executors/thread.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from multiprocessing.pool import ThreadPool
-from threading import Thread
-
-from promise import Promise
-from .utils import process
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Callable, List
-
-
-class ThreadExecutor(object):
-
-    pool = None
-
-    def __init__(self, pool=False):
-        # type: (bool) -> None
-        self.threads = []  # type: List[Thread]
-        if pool:
-            self.execute = self.execute_in_pool
-            self.pool = ThreadPool(processes=pool)
-        else:
-            self.execute = self.execute_in_thread
-
-    def wait_until_finished(self):
-        # type: () -> None
-        while self.threads:
-            threads = self.threads
-            self.threads = []
-            for thread in threads:
-                thread.join()
-
-    def clean(self):
-        self.threads = []
-
-    def execute_in_thread(self, fn, *args, **kwargs):
-        # type: (Callable, *Any, **Any) -> Promise
-        promise = Promise()
-        thread = Thread(target=process, args=(promise, fn, args, kwargs))
-        thread.start()
-        self.threads.append(thread)
-        return promise
-
-    def execute_in_pool(self, fn, *args, **kwargs):
-        promise = Promise()
-        self.pool.map(lambda input: process(*input), [(promise, fn, args, kwargs)])
-        return promise
diff --git a/graphql/execution/executors/utils.py b/graphql/execution/executors/utils.py
deleted file mode 100644
index 869a81c..0000000
--- a/graphql/execution/executors/utils.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from sys import exc_info
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..base import ResolveInfo
-    from promise import Promise
-    from typing import Callable, Dict, Tuple, Any
-
-
-def process(
-    p,  # type: Promise
-    f,  # type: Callable
-    args,  # type: Tuple[Any, ResolveInfo]
-    kwargs,  # type: Dict[str, Any]
-):
-    # type: (...) -> None
-    try:
-        val = f(*args, **kwargs)
-        p.do_resolve(val)
-    except Exception as e:
-        traceback = exc_info()[2]
-        e.stack = traceback  # type: ignore
-        p.do_reject(e, traceback=traceback)
diff --git a/graphql/execution/middleware.py b/graphql/execution/middleware.py
deleted file mode 100644
index dd00fd4..0000000
--- a/graphql/execution/middleware.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import inspect
-from functools import partial
-from itertools import chain
-
-from promise import promisify
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, Callable, Iterator, Tuple, Dict, Iterable
-
-MIDDLEWARE_RESOLVER_FUNCTION = "resolve"
-
-
-class MiddlewareManager(object):
-    __slots__ = (
-        "middlewares",
-        "wrap_in_promise",
-        "_middleware_resolvers",
-        "_cached_resolvers",
-    )
-
-    def __init__(self, *middlewares, **kwargs):
-        # type: (*Callable, **bool) -> None
-        self.middlewares = middlewares
-        self.wrap_in_promise = kwargs.get("wrap_in_promise", True)
-        self._middleware_resolvers = (
-            list(get_middleware_resolvers(middlewares)) if middlewares else []
-        )
-        self._cached_resolvers = {}  # type: Dict[Callable, Callable]
-
-    def get_field_resolver(self, field_resolver):
-        # type: (Callable) -> Callable
-        if field_resolver not in self._cached_resolvers:
-            self._cached_resolvers[field_resolver] = middleware_chain(
-                field_resolver,
-                self._middleware_resolvers,
-                wrap_in_promise=self.wrap_in_promise,
-            )
-
-        return self._cached_resolvers[field_resolver]
-
-
-middlewares = MiddlewareManager
-
-
-def get_middleware_resolvers(middlewares):
-    # type: (Tuple[Any, ...]) -> Iterator[Callable]
-    for middleware in middlewares:
-        # If the middleware is a function instead of a class
-        if inspect.isfunction(middleware):
-            yield middleware
-        if not hasattr(middleware, MIDDLEWARE_RESOLVER_FUNCTION):
-            continue
-        yield getattr(middleware, MIDDLEWARE_RESOLVER_FUNCTION)
-
-
-def middleware_chain(func, middlewares, wrap_in_promise):
-    # type: (Callable, Iterable[Callable], bool) -> Callable
-    if not middlewares:
-        return func
-    if wrap_in_promise:
-        middlewares = chain((func, make_it_promise), middlewares)
-    else:
-        middlewares = chain((func,), middlewares)
-    last_func = None
-    for middleware in middlewares:
-        last_func = partial(middleware, last_func) if last_func else middleware
-
-    return last_func  # type: ignore
-
-
-@promisify
-def make_it_promise(next, *args, **kwargs):
-    # type: (Callable, *Any, **Any) -> Any
-    return next(*args, **kwargs)
diff --git a/graphql/execution/tests/__init__.py b/graphql/execution/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py
deleted file mode 100644
index ef3eacd..0000000
--- a/graphql/execution/tests/test_abstract.py
+++ /dev/null
@@ -1,390 +0,0 @@
-# type: ignore
-from graphql import graphql
-from graphql.type import GraphQLBoolean, GraphQLSchema, GraphQLString
-from graphql.type.definition import (
-    GraphQLField,
-    GraphQLInterfaceType,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLUnionType,
-)
-
-
-class Dog(object):
-    def __init__(self, name, woofs):
-        # type: (str, bool) -> None
-        self.name = name
-        self.woofs = woofs
-
-
-class Cat(object):
-    def __init__(self, name, meows):
-        # type: (str, bool) -> None
-        self.name = name
-        self.meows = meows
-
-
-class Human(object):
-    def __init__(self, name):
-        # type: (str) -> None
-        self.name = name
-
-
-def is_type_of(type):
-    # type: (type) -> Callable
-    return lambda obj, info: isinstance(obj, type)
-
-
-def make_type_resolver(types):
-    # type: (Callable) -> Callable
-    def resolve_type(obj, info):
-        # type: (Union[Cat, Dog, Human], ResolveInfo) -> GraphQLObjectType
-        if callable(types):
-            t = types()
-        else:
-            t = types
-
-        for klass, type in t:
-            if isinstance(obj, klass):
-                return type
-
-        return None
-
-    return resolve_type
-
-
-def test_is_type_of_used_to_resolve_runtime_type_for_interface():
-    # type: () -> None
-    PetType = GraphQLInterfaceType(
-        name="Pet", fields={"name": GraphQLField(GraphQLString)}
-    )
-
-    DogType = GraphQLObjectType(
-        name="Dog",
-        interfaces=[PetType],
-        is_type_of=is_type_of(Dog),
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "woofs": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    CatType = GraphQLObjectType(
-        name="Cat",
-        interfaces=[PetType],
-        is_type_of=is_type_of(Cat),
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "meows": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Query",
-            fields={
-                "pets": GraphQLField(
-                    GraphQLList(PetType),
-                    resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)],
-                )
-            },
-        ),
-        types=[CatType, DogType],
-    )
-
-    query = """
-    {
-        pets {
-            name
-            ... on Dog {
-                woofs
-            }
-            ... on Cat {
-                meows
-            }
-        }
-    }
-    """
-
-    result = graphql(schema, query)
-    assert not result.errors
-    assert result.data == {
-        "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}]
-    }
-
-
-def test_is_type_of_used_to_resolve_runtime_type_for_union():
-    # type: () -> None
-    DogType = GraphQLObjectType(
-        name="Dog",
-        is_type_of=is_type_of(Dog),
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "woofs": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    CatType = GraphQLObjectType(
-        name="Cat",
-        is_type_of=is_type_of(Cat),
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "meows": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    PetType = GraphQLUnionType(name="Pet", types=[CatType, DogType])
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Query",
-            fields={
-                "pets": GraphQLField(
-                    GraphQLList(PetType),
-                    resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)],
-                )
-            },
-        ),
-        types=[CatType, DogType],
-    )
-
-    query = """
-    {
-        pets {
-            ... on Dog {
-                name
-                woofs
-            }
-            ... on Cat {
-                name
-                meows
-            }
-        }
-    }
-    """
-
-    result = graphql(schema, query)
-    assert not result.errors
-    assert result.data == {
-        "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}]
-    }
-
-
-def test_resolve_type_on_interface_yields_useful_error():
-    # type: () -> None
-    PetType = GraphQLInterfaceType(
-        name="Pet",
-        fields={"name": GraphQLField(GraphQLString)},
-        resolve_type=make_type_resolver(
-            lambda: [(Dog, DogType), (Cat, CatType), (Human, HumanType)]
-        ),
-    )
-
-    DogType = GraphQLObjectType(
-        name="Dog",
-        interfaces=[PetType],
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "woofs": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    HumanType = GraphQLObjectType(
-        name="Human", fields={"name": GraphQLField(GraphQLString)}
-    )
-
-    CatType = GraphQLObjectType(
-        name="Cat",
-        interfaces=[PetType],
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "meows": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Query",
-            fields={
-                "pets": GraphQLField(
-                    GraphQLList(PetType),
-                    resolver=lambda *_: [
-                        Dog("Odie", True),
-                        Cat("Garfield", False),
-                        Human("Jon"),
-                    ],
-                )
-            },
-        ),
-        types=[DogType, CatType],
-    )
-
-    query = """
-    {
-        pets {
-            name
-            ... on Dog {
-                woofs
-            }
-            ... on Cat {
-                meows
-            }
-        }
-    }
-    """
-
-    result = graphql(schema, query)
-    assert (
-        result.errors[0].message
-        == 'Runtime Object type "Human" is not a possible type for "Pet".'
-    )
-    assert result.data == {
-        "pets": [
-            {"woofs": True, "name": "Odie"},
-            {"name": "Garfield", "meows": False},
-            None,
-        ]
-    }
-
-
-def test_resolve_type_on_union_yields_useful_error():
-    # type: () -> None
-    DogType = GraphQLObjectType(
-        name="Dog",
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "woofs": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    HumanType = GraphQLObjectType(
-        name="Human", fields={"name": GraphQLField(GraphQLString)}
-    )
-
-    CatType = GraphQLObjectType(
-        name="Cat",
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "meows": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    PetType = GraphQLUnionType(
-        name="Pet",
-        types=[DogType, CatType],
-        resolve_type=make_type_resolver(
-            lambda: [(Dog, DogType), (Cat, CatType), (Human, HumanType)]
-        ),
-    )
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Query",
-            fields={
-                "pets": GraphQLField(
-                    GraphQLList(PetType),
-                    resolver=lambda *_: [
-                        Dog("Odie", True),
-                        Cat("Garfield", False),
-                        Human("Jon"),
-                    ],
-                )
-            },
-        )
-    )
-
-    query = """
-    {
-        pets {
-            ... on Dog {
-                name
-                woofs
-            }
-            ... on Cat {
-                name
-                meows
-            }
-        }
-    }
-    """
-
-    result = graphql(schema, query)
-    assert (
-        result.errors[0].message
-        == 'Runtime Object type "Human" is not a possible type for "Pet".'
-    )
-    assert result.data == {
-        "pets": [
-            {"woofs": True, "name": "Odie"},
-            {"name": "Garfield", "meows": False},
-            None,
-        ]
-    }
-
-
-def test_resolve_type_can_use_type_string():
-    # type: () -> None
-
-    def type_string_resolver(obj, *_):
-        # type: (Union[Cat, Dog], *ResolveInfo) -> str
-        if isinstance(obj, Dog):
-            return "Dog"
-        if isinstance(obj, Cat):
-            return "Cat"
-
-    PetType = GraphQLInterfaceType(
-        name="Pet",
-        fields={"name": GraphQLField(GraphQLString)},
-        resolve_type=type_string_resolver,
-    )
-
-    DogType = GraphQLObjectType(
-        name="Dog",
-        interfaces=[PetType],
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "woofs": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    CatType = GraphQLObjectType(
-        name="Cat",
-        interfaces=[PetType],
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "meows": GraphQLField(GraphQLBoolean),
-        },
-    )
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Query",
-            fields={
-                "pets": GraphQLField(
-                    GraphQLList(PetType),
-                    resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)],
-                )
-            },
-        ),
-        types=[CatType, DogType],
-    )
-
-    query = """
-    {
-        pets {
-            name
-            ... on Dog {
-                woofs
-            }
-            ... on Cat {
-                meows
-            }
-        }
-    }
-    """
-
-    result = graphql(schema, query)
-    assert not result.errors
-    assert result.data == {
-        "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}]
-    }
diff --git a/graphql/execution/tests/test_benchmark.py b/graphql/execution/tests/test_benchmark.py
deleted file mode 100644
index 04b5108..0000000
--- a/graphql/execution/tests/test_benchmark.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# type: ignore
-from collections import namedtuple
-from functools import partial
-
-from graphql import (
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    Source,
-    execute,
-    parse,
-)
-
-# from graphql.execution import executor
-
-# executor.use_experimental_executor = True
-
-SIZE = 10000
-# set global fixtures
-Container = namedtuple("Container", "x y z o")
-big_int_list = [x for x in range(SIZE)]
-big_container_list = [Container(x=x, y=x, z=x, o=x) for x in range(SIZE)]
-
-ContainerType = GraphQLObjectType(
-    "Container",
-    fields={
-        "x": GraphQLField(GraphQLInt),
-        "y": GraphQLField(GraphQLInt),
-        "z": GraphQLField(GraphQLInt),
-        "o": GraphQLField(GraphQLInt),
-    },
-)
-
-
-def resolve_all_containers(root, info, **args):
-    return big_container_list
-
-
-def resolve_all_ints(root, info, **args):
-    return big_int_list
-
-
-def test_big_list_of_ints(benchmark):
-    Query = GraphQLObjectType(
-        "Query",
-        fields={
-            "allInts": GraphQLField(GraphQLList(GraphQLInt), resolver=resolve_all_ints)
-        },
-    )
-    schema = GraphQLSchema(Query)
-    source = Source("{ allInts }")
-    ast = parse(source)
-
-    @benchmark
-    def b():
-        return execute(schema, ast)
-
-
-def test_big_list_of_ints_serialize(benchmark):
-    from ..executor import complete_leaf_value
-
-    @benchmark
-    def serialize():
-        map(GraphQLInt.serialize, big_int_list)
-
-
-def test_big_list_objecttypes_with_one_int_field(benchmark):
-    Query = GraphQLObjectType(
-        "Query",
-        fields={
-            "allContainers": GraphQLField(
-                GraphQLList(ContainerType), resolver=resolve_all_containers
-            )
-        },
-    )
-    schema = GraphQLSchema(Query)
-    source = Source("{ allContainers { x } }")
-    ast = parse(source)
-
-    @benchmark
-    def b():
-        return execute(schema, ast)
-
-
-def test_big_list_objecttypes_with_two_int_fields(benchmark):
-    Query = GraphQLObjectType(
-        "Query",
-        fields={
-            "allContainers": GraphQLField(
-                GraphQLList(ContainerType), resolver=resolve_all_containers
-            )
-        },
-    )
-
-    schema = GraphQLSchema(Query)
-    source = Source("{ allContainers { x, y } }")
-    ast = parse(source)
-
-    @benchmark
-    def b():
-        return execute(schema, ast)
diff --git a/graphql/execution/tests/test_dataloader.py b/graphql/execution/tests/test_dataloader.py
deleted file mode 100644
index 88f292d..0000000
--- a/graphql/execution/tests/test_dataloader.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# type: ignore
-import pytest
-from promise import Promise
-from promise.dataloader import DataLoader
-
-from graphql import (
-    GraphQLObjectType,
-    GraphQLField,
-    GraphQLID,
-    GraphQLArgument,
-    GraphQLNonNull,
-    GraphQLSchema,
-    parse,
-    execute,
-)
-from graphql.execution.executors.sync import SyncExecutor
-from graphql.execution.executors.thread import ThreadExecutor
-
-
-@pytest.mark.parametrize(
-    "executor",
-    [
-        SyncExecutor(),
-        # ThreadExecutor(),
-    ],
-)
-def test_batches_correctly(executor):
-    # type: (SyncExecutor) -> None
-
-    Business = GraphQLObjectType(
-        "Business",
-        lambda: {
-            "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root)
-        },
-    )
-
-    Query = GraphQLObjectType(
-        "Query",
-        lambda: {
-            "getBusiness": GraphQLField(
-                Business,
-                args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
-                resolver=lambda root, info, **args: info.context.business_data_loader.load(
-                    args.get("id")
-                ),
-            )
-        },
-    )
-
-    schema = GraphQLSchema(query=Query)
-
-    doc = """
-{
-    business1: getBusiness(id: "1") {
-        id
-    }
-    business2: getBusiness(id: "2") {
-        id
-    }
-}
-    """
-    doc_ast = parse(doc)
-
-    load_calls = []
-
-    class BusinessDataLoader(DataLoader):
-        def batch_load_fn(self, keys):
-            # type: (List[str]) -> Promise
-            load_calls.append(keys)
-            return Promise.resolve(keys)
-
-    class Context(object):
-        business_data_loader = BusinessDataLoader()
-
-    result = execute(schema, doc_ast, None, context_value=Context(), executor=executor)
-    assert not result.errors
-    assert result.data == {"business1": {"id": "1"}, "business2": {"id": "2"}}
-    assert load_calls == [["1", "2"]]
-
-
-@pytest.mark.parametrize(
-    "executor",
-    [
-        SyncExecutor(),
-        # ThreadExecutor(),  # Fails on pypy :O
-    ],
-)
-def test_batches_multiple_together(executor):
-    # type: (SyncExecutor) -> None
-
-    Location = GraphQLObjectType(
-        "Location",
-        lambda: {
-            "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root)
-        },
-    )
-
-    Business = GraphQLObjectType(
-        "Business",
-        lambda: {
-            "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root),
-            "location": GraphQLField(
-                Location,
-                resolver=lambda root, info, **args: info.context.location_data_loader.load(
-                    "location-{}".format(root)
-                ),
-            ),
-        },
-    )
-
-    Query = GraphQLObjectType(
-        "Query",
-        lambda: {
-            "getBusiness": GraphQLField(
-                Business,
-                args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
-                resolver=lambda root, info, **args: info.context.business_data_loader.load(
-                    args.get("id")
-                ),
-            )
-        },
-    )
-
-    schema = GraphQLSchema(query=Query)
-
-    doc = """
-{
-    business1: getBusiness(id: "1") {
-        id
-        location {
-            id
-        }
-    }
-    business2: getBusiness(id: "2") {
-        id
-        location {
-            id
-        }
-    }
-}
-    """
-    doc_ast = parse(doc)
-
-    business_load_calls = []
-
-    class BusinessDataLoader(DataLoader):
-        def batch_load_fn(self, keys):
-            # type: (List[str]) -> Promise
-            business_load_calls.append(keys)
-            return Promise.resolve(keys)
-
-    location_load_calls = []
-
-    class LocationDataLoader(DataLoader):
-        def batch_load_fn(self, keys):
-            # type: (List[str]) -> Promise
-            location_load_calls.append(keys)
-            return Promise.resolve(keys)
-
-    class Context(object):
-        business_data_loader = BusinessDataLoader()
-        location_data_loader = LocationDataLoader()
-
-    result = execute(schema, doc_ast, None, context_value=Context(), executor=executor)
-    assert not result.errors
-    assert result.data == {
-        "business1": {"id": "1", "location": {"id": "location-1"}},
-        "business2": {"id": "2", "location": {"id": "location-2"}},
-    }
-    assert business_load_calls == [["1", "2"]]
-    assert location_load_calls == [["location-1", "location-2"]]
diff --git a/graphql/execution/tests/test_directives.py b/graphql/execution/tests/test_directives.py
deleted file mode 100644
index acc1ac1..0000000
--- a/graphql/execution/tests/test_directives.py
+++ /dev/null
@@ -1,277 +0,0 @@
-# type: ignore
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
-
-schema = GraphQLSchema(
-    query=GraphQLObjectType(
-        name="TestType",
-        fields={"a": GraphQLField(GraphQLString), "b": GraphQLField(GraphQLString)},
-    )
-)
-
-
-class Data(object):
-    a = "a"
-    b = "b"
-
-
-def execute_test_query(doc):
-    # type: (str) -> ExecutionResult
-    return execute(schema, parse(doc), Data)
-
-
-def test_basic_query_works():
-    # type: () -> None
-    result = execute_test_query("{ a, b }")
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_if_true_includes_scalar():
-    # type: () -> None
-    result = execute_test_query("{ a, b @include(if: true) }")
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_if_false_omits_on_scalar():
-    # type: () -> None
-    result = execute_test_query("{ a, b @include(if: false) }")
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_skip_false_includes_scalar():
-    # type: () -> None
-    result = execute_test_query("{ a, b @skip(if: false) }")
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_skip_true_omits_scalar():
-    # type: () -> None
-    result = execute_test_query("{ a, b @skip(if: true) }")
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_if_false_omits_fragment_spread():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ...Frag @include(if: false)
-        }
-        fragment Frag on TestType {
-          b
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_if_true_includes_fragment_spread():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ...Frag @include(if: true)
-        }
-        fragment Frag on TestType {
-          b
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_skip_false_includes_fragment_spread():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ...Frag @skip(if: false)
-        }
-        fragment Frag on TestType {
-          b
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_skip_true_omits_fragment_spread():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ...Frag @skip(if: true)
-        }
-        fragment Frag on TestType {
-          b
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_if_false_omits_inline_fragment():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... on TestType @include(if: false) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_if_true_includes_inline_fragment():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... on TestType @include(if: true) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_skip_false_includes_inline_fragment():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... on TestType @skip(if: false) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_skip_true_omits_inline_fragment():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... on TestType @skip(if: true) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_skip_true_omits_fragment():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ...Frag
-        }
-        fragment Frag on TestType @skip(if: true) {
-          b
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_skip_on_inline_anonymous_fragment_omits_field():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... @skip(if: true) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_skip_on_inline_anonymous_fragment_does_not_omit_field():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... @skip(if: false) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_include_on_inline_anonymous_fragment_omits_field():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... @include(if: false) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_include_on_inline_anonymous_fragment_does_not_omit_field():
-    # type: () -> None
-    q = """
-        query Q {
-          a
-          ... @include(if: true) {
-            b
-          }
-        }
-    """
-    result = execute_test_query(q)
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_works_directives_include_and_no_skip():
-    # type: () -> None
-    result = execute_test_query("{ a, b @include(if: true) @skip(if: false) }")
-    assert not result.errors
-    assert result.data == {"a": "a", "b": "b"}
-
-
-def test_works_directives_include_and_skip():
-    # type: () -> None
-    result = execute_test_query("{ a, b @include(if: true) @skip(if: true) }")
-    assert not result.errors
-    assert result.data == {"a": "a"}
-
-
-def test_works_directives_no_include_or_skip():
-    # type: () -> None
-    result = execute_test_query("{ a, b @include(if: false) @skip(if: false) }")
-    assert not result.errors
-    assert result.data == {"a": "a"}
diff --git a/graphql/execution/tests/test_execute_schema.py b/graphql/execution/tests/test_execute_schema.py
deleted file mode 100644
index 0c7e103..0000000
--- a/graphql/execution/tests/test_execute_schema.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# type: ignore
-
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLBoolean,
-    GraphQLField,
-    GraphQLID,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-)
-
-
-def test_executes_using_a_schema():
-    # type: () -> None
-    BlogImage = GraphQLObjectType(
-        "BlogImage",
-        {
-            "url": GraphQLField(GraphQLString),
-            "width": GraphQLField(GraphQLInt),
-            "height": GraphQLField(GraphQLInt),
-        },
-    )
-
-    BlogAuthor = GraphQLObjectType(
-        "Author",
-        lambda: {
-            "id": GraphQLField(GraphQLString),
-            "name": GraphQLField(GraphQLString),
-            "pic": GraphQLField(
-                BlogImage,
-                args={
-                    "width": GraphQLArgument(GraphQLInt),
-                    "height": GraphQLArgument(GraphQLInt),
-                },
-                resolver=lambda obj, info, **args: obj.pic(
-                    args["width"], args["height"]
-                ),
-            ),
-            "recentArticle": GraphQLField(BlogArticle),
-        },
-    )
-
-    BlogArticle = GraphQLObjectType(
-        "Article",
-        {
-            "id": GraphQLField(GraphQLNonNull(GraphQLString)),
-            "isPublished": GraphQLField(GraphQLBoolean),
-            "author": GraphQLField(BlogAuthor),
-            "title": GraphQLField(GraphQLString),
-            "body": GraphQLField(GraphQLString),
-            "keywords": GraphQLField(GraphQLList(GraphQLString)),
-        },
-    )
-
-    BlogQuery = GraphQLObjectType(
-        "Query",
-        {
-            "article": GraphQLField(
-                BlogArticle,
-                args={"id": GraphQLArgument(GraphQLID)},
-                resolver=lambda obj, info, **args: Article(args["id"]),
-            ),
-            "feed": GraphQLField(
-                GraphQLList(BlogArticle),
-                resolver=lambda *_: map(Article, range(1, 10 + 1)),
-            ),
-        },
-    )
-
-    BlogSchema = GraphQLSchema(BlogQuery)
-
-    class Article(object):
-        def __init__(self, id):
-            # type: (int) -> None
-            self.id = id
-            self.isPublished = True
-            self.author = Author()
-            self.title = "My Article {}".format(id)
-            self.body = "This is a post"
-            self.hidden = "This data is not exposed in the schema"
-            self.keywords = ["foo", "bar", 1, True, None]
-
-    class Author(object):
-        id = 123
-        name = "John Smith"
-
-        def pic(self, width, height):
-            # type: (int, int) -> Pic
-            return Pic(123, width, height)
-
-        @property
-        def recentArticle(self):
-            # type: () -> Article
-            return Article(1)
-
-    class Pic(object):
-        def __init__(self, uid, width, height):
-            # type: (int, int, int) -> None
-            self.url = "cdn://{}".format(uid)
-            self.width = str(width)
-            self.height = str(height)
-
-    request = """
-    {
-        feed {
-          id,
-          title
-        },
-        article(id: "1") {
-          ...articleFields,
-          author {
-            id,
-            name,
-            pic(width: 640, height: 480) {
-              url,
-              width,
-              height
-            },
-            recentArticle {
-              ...articleFields,
-              keywords
-            }
-          }
-        }
-      }
-      fragment articleFields on Article {
-        id,
-        isPublished,
-        title,
-        body,
-        hidden,
-        notdefined
-      }
-    """
-
-    # Note: this is intentionally not validating to ensure appropriate
-    # behavior occurs when executing an invalid query.
-    result = execute(BlogSchema, parse(request))
-    assert not result.errors
-    assert result.data == {
-        "feed": [
-            {"id": "1", "title": "My Article 1"},
-            {"id": "2", "title": "My Article 2"},
-            {"id": "3", "title": "My Article 3"},
-            {"id": "4", "title": "My Article 4"},
-            {"id": "5", "title": "My Article 5"},
-            {"id": "6", "title": "My Article 6"},
-            {"id": "7", "title": "My Article 7"},
-            {"id": "8", "title": "My Article 8"},
-            {"id": "9", "title": "My Article 9"},
-            {"id": "10", "title": "My Article 10"},
-        ],
-        "article": {
-            "id": "1",
-            "isPublished": True,
-            "title": "My Article 1",
-            "body": "This is a post",
-            "author": {
-                "id": "123",
-                "name": "John Smith",
-                "pic": {"url": "cdn://123", "width": 640, "height": 480},
-                "recentArticle": {
-                    "id": "1",
-                    "isPublished": True,
-                    "title": "My Article 1",
-                    "body": "This is a post",
-                    "keywords": ["foo", "bar", "1", "true", None],
-                },
-            },
-        },
-    }
diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py
deleted file mode 100644
index b4298e8..0000000
--- a/graphql/execution/tests/test_executor.py
+++ /dev/null
@@ -1,761 +0,0 @@
-# type: ignore
-import json
-
-from pytest import raises
-
-from graphql.error import GraphQLError
-from graphql.execution import MiddlewareManager, execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLBoolean,
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-    GraphQLNonNull,
-    GraphQLID,
-)
-from promise import Promise
-
-
-def test_executes_arbitary_code():
-    # type: () -> None
-    class Data(object):
-        a = "Apple"
-        b = "Banana"
-        c = "Cookie"
-        d = "Donut"
-        e = "Egg"
-        f = "Fish"
-
-        def pic(self, size=50):
-            # type: (int) -> str
-            return "Pic of size: {}".format(size)
-
-        def deep(self):
-            # type: () -> DeepData
-            return DeepData()
-
-        def promise(self):
-            # type: () -> Data
-            # FIXME: promise is unsupported
-            return Data()
-
-    class DeepData(object):
-        a = "Already Been Done"
-        b = "Boring"
-        c = ["Contrived", None, "Confusing"]
-
-        def deeper(self):
-            # type: () -> List[Optional[Data]]
-            return [Data(), None, Data()]
-
-    doc = """
-        query Example($size: Int) {
-            a,
-            b,
-            x: c
-            ...c
-            f
-            ...on DataType {
-                pic(size: $size)
-                promise {
-                    a
-                }
-            }
-            deep {
-                a
-                b
-                c
-                deeper {
-                    a
-                    b
-                }
-            }
-        }
-        fragment c on DataType {
-            d
-            e
-        }
-    """
-
-    ast = parse(doc)
-    expected = {
-        "a": "Apple",
-        "b": "Banana",
-        "x": "Cookie",
-        "d": "Donut",
-        "e": "Egg",
-        "f": "Fish",
-        "pic": "Pic of size: 100",
-        "promise": {"a": "Apple"},
-        "deep": {
-            "a": "Already Been Done",
-            "b": "Boring",
-            "c": ["Contrived", None, "Confusing"],
-            "deeper": [
-                {"a": "Apple", "b": "Banana"},
-                None,
-                {"a": "Apple", "b": "Banana"},
-            ],
-        },
-    }
-
-    DataType = GraphQLObjectType(
-        "DataType",
-        lambda: {
-            "a": GraphQLField(GraphQLString),
-            "b": GraphQLField(GraphQLString),
-            "c": GraphQLField(GraphQLString),
-            "d": GraphQLField(GraphQLString),
-            "e": GraphQLField(GraphQLString),
-            "f": GraphQLField(GraphQLString),
-            "pic": GraphQLField(
-                args={"size": GraphQLArgument(GraphQLInt)},
-                type=GraphQLString,
-                resolver=lambda obj, info, size: obj.pic(size),
-            ),
-            "deep": GraphQLField(DeepDataType),
-            "promise": GraphQLField(DataType),
-        },
-    )
-
-    DeepDataType = GraphQLObjectType(
-        "DeepDataType",
-        {
-            "a": GraphQLField(GraphQLString),
-            "b": GraphQLField(GraphQLString),
-            "c": GraphQLField(GraphQLList(GraphQLString)),
-            "deeper": GraphQLField(GraphQLList(DataType)),
-        },
-    )
-
-    schema = GraphQLSchema(query=DataType)
-
-    result = execute(
-        schema, ast, Data(), operation_name="Example", variable_values={"size": 100}
-    )
-    assert not result.errors
-    assert result.data == expected
-
-
-def test_merges_parallel_fragments():
-    # type: () -> None
-    ast = parse(
-        """
-        { a, deep {...FragOne, ...FragTwo} }
-
-        fragment FragOne on Type {
-            b
-            deep { b, deeper: deep { b } }
-        }
-
-        fragment FragTwo on Type {
-            c
-            deep { c, deeper: deep { c } }
-        }
-    """
-    )
-
-    Type = GraphQLObjectType(
-        "Type",
-        lambda: {
-            "a": GraphQLField(GraphQLString, resolver=lambda *_: "Apple"),
-            "b": GraphQLField(GraphQLString, resolver=lambda *_: "Banana"),
-            "c": GraphQLField(GraphQLString, resolver=lambda *_: "Cherry"),
-            "deep": GraphQLField(Type, resolver=lambda *_: {}),
-        },
-    )
-
-    schema = GraphQLSchema(query=Type)
-    result = execute(schema, ast)
-    assert not result.errors
-    assert result.data == {
-        "a": "Apple",
-        "deep": {
-            "b": "Banana",
-            "c": "Cherry",
-            "deep": {
-                "b": "Banana",
-                "c": "Cherry",
-                "deeper": {"b": "Banana", "c": "Cherry"},
-            },
-        },
-    }
-
-
-def test_threads_root_value_context_correctly():
-    # type: () -> None
-    doc = "query Example { a }"
-
-    class Data(object):
-        context_thing = "thing"
-
-    ast = parse(doc)
-
-    def resolver(root_value, *_):
-        # type: (Data, *ResolveInfo) -> None
-        assert root_value.context_thing == "thing"
-        resolver.got_here = True
-
-    resolver.got_here = False
-
-    Type = GraphQLObjectType(
-        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)}
-    )
-
-    result = execute(GraphQLSchema(Type), ast, Data(), operation_name="Example")
-    assert not result.errors
-    assert resolver.got_here
-
-
-def test_correctly_threads_arguments():
-    # type: () -> None
-    doc = """
-        query Example {
-            b(numArg: 123, stringArg: "foo")
-        }
-    """
-
-    def resolver(source, info, numArg, stringArg):
-        # type: (Optional[Any], ResolveInfo, int, str) -> None
-        assert numArg == 123
-        assert stringArg == "foo"
-        resolver.got_here = True
-
-    resolver.got_here = False
-
-    doc_ast = parse(doc)
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "b": GraphQLField(
-                GraphQLString,
-                args={
-                    "numArg": GraphQLArgument(GraphQLInt),
-                    "stringArg": GraphQLArgument(GraphQLString),
-                },
-                resolver=resolver,
-            )
-        },
-    )
-
-    result = execute(GraphQLSchema(Type), doc_ast, None, operation_name="Example")
-    assert not result.errors
-    assert resolver.got_here
-
-
-def test_nulls_out_error_subtrees():
-    # type: () -> None
-    doc = """{
-        ok,
-        error
-    }"""
-
-    class Data(object):
-        def ok(self):
-            # type: () -> str
-            return "ok"
-
-        def error(self):
-            # type: () -> NoReturn
-            raise Exception("Error getting error")
-
-    doc_ast = parse(doc)
-
-    Type = GraphQLObjectType(
-        "Type",
-        {"ok": GraphQLField(GraphQLString), "error": GraphQLField(GraphQLString)},
-    )
-
-    result = execute(GraphQLSchema(Type), doc_ast, Data())
-    assert result.data == {"ok": "ok", "error": None}
-    assert len(result.errors) == 1
-    assert result.errors[0].message == "Error getting error"
-    # TODO: check error location
-
-
-def test_uses_the_inline_operation_if_no_operation_name_is_provided():
-    # type: () -> None
-    doc = "{ a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Type), ast, Data())
-    assert not result.errors
-    assert result.data == {"a": "b"}
-
-
-def test_uses_the_only_operation_if_no_operation_name_is_provided():
-    # type: () -> None
-    doc = "query Example { a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Type), ast, Data())
-    assert not result.errors
-    assert result.data == {"a": "b"}
-
-
-def test_uses_the_named_operation_if_operation_name_is_provided():
-    # type: () -> None
-    doc = "query Example { first: a } query OtherExample { second: a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Type), ast, Data(), operation_name="OtherExample")
-    assert not result.errors
-    assert result.data == {"second": "b"}
-
-
-def test_raises_if_no_operation_is_provided():
-    # type: () -> None
-    doc = "fragment Example on Type { a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    with raises(GraphQLError) as excinfo:
-        execute(GraphQLSchema(Type), ast, Data())
-    assert "Must provide an operation." == str(excinfo.value)
-
-
-def test_raises_if_no_operation_name_is_provided_with_multiple_operations():
-    # type: () -> None
-    doc = "query Example { a } query OtherExample { a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    with raises(GraphQLError) as excinfo:
-        execute(GraphQLSchema(Type), ast, Data(), operation_name="UnknownExample")
-    assert 'Unknown operation named "UnknownExample".' == str(excinfo.value)
-
-
-def test_raises_if_unknown_operation_name_is_provided():
-    # type: () -> None
-    doc = "query Example { a } query OtherExample { a }"
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    with raises(GraphQLError) as excinfo:
-        execute(GraphQLSchema(Type), ast, Data())
-    assert "Must provide operation name if query contains multiple operations." == str(
-        excinfo.value
-    )
-
-
-def test_uses_the_query_schema_for_queries():
-    # type: () -> None
-    doc = "query Q { a } mutation M { c } subscription S { a }"
-
-    class Data(object):
-        a = "b"
-        c = "d"
-
-    ast = parse(doc)
-    Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)})
-    M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)})
-    S = GraphQLObjectType("S", {"a": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Q, M, S), ast, Data(), operation_name="Q")
-    assert not result.errors
-    assert result.data == {"a": "b"}
-
-
-def test_uses_the_mutation_schema_for_queries():
-    # type: () -> None
-    doc = "query Q { a } mutation M { c }"
-
-    class Data(object):
-        a = "b"
-        c = "d"
-
-    ast = parse(doc)
-    Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)})
-    M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Q, M), ast, Data(), operation_name="M")
-    assert not result.errors
-    assert result.data == {"c": "d"}
-
-
-def test_uses_the_subscription_schema_for_subscriptions():
-    # type: () -> None
-    from rx import Observable
-
-    doc = "query Q { a } subscription S { a }"
-
-    class Data(object):
-        a = "b"
-        c = "d"
-
-    ast = parse(doc)
-    Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)})
-    S = GraphQLObjectType(
-        "S",
-        {
-            "a": GraphQLField(
-                GraphQLString, resolver=lambda root, info: Observable.from_(["b"])
-            )
-        },
-    )
-    result = execute(
-        GraphQLSchema(Q, subscription=S),
-        ast,
-        Data(),
-        operation_name="S",
-        allow_subscriptions=True,
-    )
-    assert isinstance(result, Observable)
-    l = []
-    result.subscribe(l.append)
-    result = l[0]
-    assert not result.errors
-    assert result.data == {"a": "b"}
-
-
-def test_avoids_recursion():
-    # type: () -> None
-    doc = """
-        query Q {
-            a
-            ...Frag
-            ...Frag
-        }
-        fragment Frag on Type {
-            a,
-            ...Frag
-        }
-    """
-
-    class Data(object):
-        a = "b"
-
-    ast = parse(doc)
-    Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Type), ast, Data(), operation_name="Q")
-    assert not result.errors
-    assert result.data == {"a": "b"}
-
-
-def test_does_not_include_illegal_fields_in_output():
-    # type: () -> None
-    doc = "mutation M { thisIsIllegalDontIncludeMe }"
-    ast = parse(doc)
-    Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)})
-    M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)})
-    result = execute(GraphQLSchema(Q, M), ast)
-    assert not result.errors
-    assert result.data == {}
-
-
-def test_does_not_include_arguments_that_were_not_set():
-    # type: () -> None
-    schema = GraphQLSchema(
-        GraphQLObjectType(
-            "Type",
-            {
-                "field": GraphQLField(
-                    GraphQLString,
-                    resolver=lambda source, info, **args: args
-                    and json.dumps(args, sort_keys=True, separators=(",", ":")),
-                    args={
-                        "a": GraphQLArgument(GraphQLBoolean),
-                        "b": GraphQLArgument(GraphQLBoolean),
-                        "c": GraphQLArgument(GraphQLBoolean),
-                        "d": GraphQLArgument(GraphQLInt),
-                        "e": GraphQLArgument(GraphQLInt),
-                    },
-                )
-            },
-        )
-    )
-
-    ast = parse("{ field(a: true, c: false, e: 0) }")
-    result = execute(schema, ast)
-    assert result.data == {"field": '{"a":true,"c":false,"e":0}'}
-
-
-def test_fails_when_an_is_type_of_check_is_not_met():
-    # type: () -> None
-    class Special(object):
-        def __init__(self, value):
-            # type: (str) -> None
-            self.value = value
-
-    class NotSpecial(object):
-        def __init__(self, value):
-            # type: (str) -> None
-            self.value = value
-
-    SpecialType = GraphQLObjectType(
-        "SpecialType",
-        fields={"value": GraphQLField(GraphQLString)},
-        is_type_of=lambda obj, info: isinstance(obj, Special),
-    )
-
-    schema = GraphQLSchema(
-        GraphQLObjectType(
-            name="Query",
-            fields={
-                "specials": GraphQLField(
-                    GraphQLList(SpecialType), resolver=lambda root, *_: root["specials"]
-                )
-            },
-        )
-    )
-
-    query = parse("{ specials { value } }")
-    value = {"specials": [Special("foo"), NotSpecial("bar")]}
-
-    result = execute(schema, query, value)
-
-    assert result.data == {"specials": [{"value": "foo"}, None]}
-
-    assert 'Expected value of type "SpecialType" but got: NotSpecial.' in [
-        str(e) for e in result.errors
-    ]
-
-
-def test_fails_to_execute_a_query_containing_a_type_definition():
-    # type: () -> None
-    query = parse(
-        """
-    { foo }
-
-    type Query { foo: String }
-    """
-    )
-
-    schema = GraphQLSchema(
-        GraphQLObjectType(name="Query", fields={"foo": GraphQLField(GraphQLString)})
-    )
-
-    with raises(GraphQLError) as excinfo:
-        execute(schema, query)
-
-    assert (
-        excinfo.value.message
-        == "GraphQL cannot execute a request containing a ObjectTypeDefinition."
-    )
-
-
-def test_exceptions_are_reraised_if_specified(mocker):
-    # type: (MockFixture) -> None
-
-    logger = mocker.patch("graphql.execution.executor.logger")
-
-    query = parse(
-        """
-    { foo }
-    """
-    )
-
-    def resolver(*_):
-        # type: (*Any) -> NoReturn
-        raise Exception("UH OH!")
-
-    schema = GraphQLSchema(
-        GraphQLObjectType(
-            name="Query", fields={"foo": GraphQLField(GraphQLString, resolver=resolver)}
-        )
-    )
-
-    execute(schema, query)
-    logger.exception.assert_called_with(
-        "An error occurred while resolving field Query.foo"
-    )
-
-
-def test_executor_properly_propogates_path_data(mocker):
-    # type: (MockFixture) -> None
-    time_mock = mocker.patch("time.time")
-    time_mock.side_effect = range(0, 10000)
-
-    BlogImage = GraphQLObjectType(
-        "BlogImage",
-        {
-            "url": GraphQLField(GraphQLString),
-            "width": GraphQLField(GraphQLInt),
-            "height": GraphQLField(GraphQLInt),
-        },
-    )
-
-    BlogAuthor = GraphQLObjectType(
-        "Author",
-        lambda: {
-            "id": GraphQLField(GraphQLString),
-            "name": GraphQLField(GraphQLString),
-            "pic": GraphQLField(
-                BlogImage,
-                args={
-                    "width": GraphQLArgument(GraphQLInt),
-                    "height": GraphQLArgument(GraphQLInt),
-                },
-                resolver=lambda obj, info, **args: obj.pic(
-                    args["width"], args["height"]
-                ),
-            ),
-            "recentArticle": GraphQLField(BlogArticle),
-        },
-    )
-
-    BlogArticle = GraphQLObjectType(
-        "Article",
-        {
-            "id": GraphQLField(GraphQLNonNull(GraphQLString)),
-            "isPublished": GraphQLField(GraphQLBoolean),
-            "author": GraphQLField(BlogAuthor),
-            "title": GraphQLField(GraphQLString),
-            "body": GraphQLField(GraphQLString),
-            "keywords": GraphQLField(GraphQLList(GraphQLString)),
-        },
-    )
-
-    BlogQuery = GraphQLObjectType(
-        "Query",
-        {
-            "article": GraphQLField(
-                BlogArticle,
-                args={"id": GraphQLArgument(GraphQLID)},
-                resolver=lambda obj, info, **args: Article(args["id"]),
-            ),
-            "feed": GraphQLField(
-                GraphQLList(BlogArticle),
-                resolver=lambda *_: map(Article, range(1, 2 + 1)),
-            ),
-        },
-    )
-
-    BlogSchema = GraphQLSchema(BlogQuery)
-
-    class Article(object):
-        def __init__(self, id):
-            # type: (int) -> None
-            self.id = id
-            self.isPublished = True
-            self.author = Author()
-            self.title = "My Article {}".format(id)
-            self.body = "This is a post"
-            self.hidden = "This data is not exposed in the schema"
-            self.keywords = ["foo", "bar", 1, True, None]
-
-    class Author(object):
-        id = 123
-        name = "John Smith"
-
-        def pic(self, width, height):
-            return Pic(123, width, height)
-
-        @property
-        def recentArticle(self):
-            return Article(1)
-
-    class Pic(object):
-        def __init__(self, uid, width, height):
-            self.url = "cdn://{}".format(uid)
-            self.width = str(width)
-            self.height = str(height)
-
-    class PathCollectorMiddleware(object):
-        def __init__(self):
-            # type: () -> None
-            self.paths = []
-
-        def resolve(
-            self,
-            _next,  # type: Callable
-            root,  # type: Optional[Article]
-            info,  # type: ResolveInfo
-            *args,  # type: Any
-            **kwargs  # type: Any
-        ):
-            # type: (...) -> Promise
-            self.paths.append(info.path)
-            return _next(root, info, *args, **kwargs)
-
-    request = """
-    {
-        feed {
-          id
-          ...articleFields
-          author {
-            id
-            name
-            nameAlias: name
-          }
-        },
-    }
-    fragment articleFields on Article {
-        title,
-        body,
-        hidden,
-    }
-    """
-
-    paths_middleware = PathCollectorMiddleware()
-
-    result = execute(BlogSchema, parse(request), middleware=(paths_middleware,))
-    assert not result.errors
-    assert result.data == {
-        "feed": [
-            {
-                "id": "1",
-                "title": "My Article 1",
-                "body": "This is a post",
-                "author": {
-                    "id": "123",
-                    "name": "John Smith",
-                    "nameAlias": "John Smith",
-                },
-            },
-            {
-                "id": "2",
-                "title": "My Article 2",
-                "body": "This is a post",
-                "author": {
-                    "id": "123",
-                    "name": "John Smith",
-                    "nameAlias": "John Smith",
-                },
-            },
-        ]
-    }
-
-    traversed_paths = paths_middleware.paths
-    assert traversed_paths == [
-        ["feed"],
-        ["feed", 0, "id"],
-        ["feed", 0, "title"],
-        ["feed", 0, "body"],
-        ["feed", 0, "author"],
-        ["feed", 1, "id"],
-        ["feed", 1, "title"],
-        ["feed", 1, "body"],
-        ["feed", 1, "author"],
-        ["feed", 0, "author", "id"],
-        ["feed", 0, "author", "name"],
-        ["feed", 0, "author", "nameAlias"],
-        ["feed", 1, "author", "id"],
-        ["feed", 1, "author", "name"],
-        ["feed", 1, "author", "nameAlias"],
-    ]
diff --git a/graphql/execution/tests/test_executor_asyncio.py b/graphql/execution/tests/test_executor_asyncio.py
deleted file mode 100644
index 714f59e..0000000
--- a/graphql/execution/tests/test_executor_asyncio.py
+++ /dev/null
@@ -1,122 +0,0 @@
-"""
-   isort:skip_file
-"""
-# type: ignore
-# flake8: noqa
-
-import pytest
-
-asyncio = pytest.importorskip("asyncio")
-
-from graphql.error import format_error
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
-
-from ..executors.asyncio import AsyncioExecutor
-from .test_mutations import assert_evaluate_mutations_serially
-
-
-def test_asyncio_executor():
-    # type: () -> None
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        asyncio.sleep(0.001)
-        return "hey"
-
-    @asyncio.coroutine
-    def resolver_2(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        asyncio.sleep(0.003)
-        return "hey2"
-
-    def resolver_3(contest, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        return "hey3"
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "a": GraphQLField(GraphQLString, resolver=resolver),
-            "b": GraphQLField(GraphQLString, resolver=resolver_2),
-            "c": GraphQLField(GraphQLString, resolver=resolver_3),
-        },
-    )
-
-    ast = parse("{ a b c }")
-    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor())
-    assert not result.errors
-    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
-
-
-def test_asyncio_executor_custom_loop():
-    # type: () -> None
-    loop = asyncio.get_event_loop()
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        asyncio.sleep(0.001, loop=loop)
-        return "hey"
-
-    @asyncio.coroutine
-    def resolver_2(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        asyncio.sleep(0.003, loop=loop)
-        return "hey2"
-
-    def resolver_3(contest, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        return "hey3"
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "a": GraphQLField(GraphQLString, resolver=resolver),
-            "b": GraphQLField(GraphQLString, resolver=resolver_2),
-            "c": GraphQLField(GraphQLString, resolver=resolver_3),
-        },
-    )
-
-    ast = parse("{ a b c }")
-    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop=loop))
-    assert not result.errors
-    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
-
-
-def test_asyncio_executor_with_error():
-    # type: () -> None
-    ast = parse("query Example { a, b }")
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> str
-        asyncio.sleep(0.001)
-        return "hey"
-
-    def resolver_2(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> NoReturn
-        asyncio.sleep(0.003)
-        raise Exception("resolver_2 failed!")
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "a": GraphQLField(GraphQLString, resolver=resolver),
-            "b": GraphQLField(GraphQLString, resolver=resolver_2),
-        },
-    )
-
-    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor())
-    formatted_errors = list(map(format_error, result.errors))
-    assert formatted_errors == [
-        {
-            "locations": [{"line": 1, "column": 20}],
-            "path": ["b"],
-            "message": "resolver_2 failed!",
-        }
-    ]
-    assert result.data == {"a": "hey", "b": None}
-
-
-def test_evaluates_mutations_serially():
-    # type: () -> None
-    assert_evaluate_mutations_serially(executor=AsyncioExecutor())
diff --git a/graphql/execution/tests/test_executor_gevent.py b/graphql/execution/tests/test_executor_gevent.py
deleted file mode 100644
index 9256a01..0000000
--- a/graphql/execution/tests/test_executor_gevent.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-   isort:skip_file
-"""
-# type: ignore
-# flake8: noqa
-
-import pytest
-
-gevent = pytest.importorskip("gevent")
-
-from graphql.error import format_error
-from graphql.execution import execute
-from graphql.language.location import SourceLocation
-from graphql.language.parser import parse
-from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
-
-from ..executors.gevent import GeventExecutor
-from .test_mutations import assert_evaluate_mutations_serially
-
-
-def test_gevent_executor():
-    def resolver(context, *_):
-        gevent.sleep(0.001)
-        return "hey"
-
-    def resolver_2(context, *_):
-        gevent.sleep(0.003)
-        return "hey2"
-
-    def resolver_3(contest, *_):
-        return "hey3"
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "a": GraphQLField(GraphQLString, resolver=resolver),
-            "b": GraphQLField(GraphQLString, resolver=resolver_2),
-            "c": GraphQLField(GraphQLString, resolver=resolver_3),
-        },
-    )
-
-    ast = parse("{ a b c }")
-    result = execute(GraphQLSchema(Type), ast, executor=GeventExecutor())
-    assert not result.errors
-    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
-
-
-def test_gevent_executor_with_error():
-    ast = parse("query Example { a, b }")
-
-    def resolver(context, *_):
-        gevent.sleep(0.001)
-        return "hey"
-
-    def resolver_2(context, *_):
-        gevent.sleep(0.003)
-        raise Exception("resolver_2 failed!")
-
-    Type = GraphQLObjectType(
-        "Type",
-        {
-            "a": GraphQLField(GraphQLString, resolver=resolver),
-            "b": GraphQLField(GraphQLString, resolver=resolver_2),
-        },
-    )
-
-    result = execute(GraphQLSchema(Type), ast, executor=GeventExecutor())
-    formatted_errors = list(map(format_error, result.errors))
-    assert formatted_errors == [
-        {
-            "locations": [{"line": 1, "column": 20}],
-            "path": ["b"],
-            "message": "resolver_2 failed!",
-        }
-    ]
-    assert result.data == {"a": "hey", "b": None}
-
-
-def test_evaluates_mutations_serially():
-    assert_evaluate_mutations_serially(executor=GeventExecutor())
diff --git a/graphql/execution/tests/test_executor_thread.py b/graphql/execution/tests/test_executor_thread.py
deleted file mode 100644
index ceaf8ce..0000000
--- a/graphql/execution/tests/test_executor_thread.py
+++ /dev/null
@@ -1,294 +0,0 @@
-# type: ignore
-from graphql.error import format_error
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-)
-
-from ..executors.thread import ThreadExecutor
-from .test_mutations import assert_evaluate_mutations_serially
-from .utils import rejected, resolved
-
-
-def test_executes_arbitary_code():
-    # type: () -> None
-    class Data(object):
-        a = "Apple"
-        b = "Banana"
-        c = "Cookie"
-        d = "Donut"
-        e = "Egg"
-
-        @property
-        def f(self):
-            # type: () -> Promise
-            return resolved("Fish")
-
-        def pic(self, size=50):
-            # type: (int) -> Promise
-            return resolved("Pic of size: {}".format(size))
-
-        def deep(self):
-            # type: () -> DeepData
-            return DeepData()
-
-        def promise(self):
-            # type: () -> Promise
-            return resolved(Data())
-
-    class DeepData(object):
-        a = "Already Been Done"
-        b = "Boring"
-        c = ["Contrived", None, resolved("Confusing")]
-
-        def deeper(self):
-            # type: () -> List[Union[None, Data, Promise]]
-            return [Data(), None, resolved(Data())]
-
-    ast = parse(
-        """
-        query Example($size: Int) {
-            a,
-            b,
-            x: c
-            ...c
-            f
-            ...on DataType {
-                pic(size: $size)
-                promise {
-                    a
-                }
-            }
-            deep {
-                a
-                b
-                c
-                deeper {
-                    a
-                    b
-                }
-            }
-        }
-        fragment c on DataType {
-            d
-            e
-        }
-    """
-    )
-
-    expected = {
-        "a": "Apple",
-        "b": "Banana",
-        "x": "Cookie",
-        "d": "Donut",
-        "e": "Egg",
-        "f": "Fish",
-        "pic": "Pic of size: 100",
-        "promise": {"a": "Apple"},
-        "deep": {
-            "a": "Already Been Done",
-            "b": "Boring",
-            "c": ["Contrived", None, "Confusing"],
-            "deeper": [
-                {"a": "Apple", "b": "Banana"},
-                None,
-                {"a": "Apple", "b": "Banana"},
-            ],
-        },
-    }
-
-    DataType = GraphQLObjectType(
-        "DataType",
-        lambda: {
-            "a": GraphQLField(GraphQLString),
-            "b": GraphQLField(GraphQLString),
-            "c": GraphQLField(GraphQLString),
-            "d": GraphQLField(GraphQLString),
-            "e": GraphQLField(GraphQLString),
-            "f": GraphQLField(GraphQLString),
-            "pic": GraphQLField(
-                args={"size": GraphQLArgument(GraphQLInt)},
-                type=GraphQLString,
-                resolver=lambda obj, info, **args: obj.pic(args["size"]),
-            ),
-            "deep": GraphQLField(DeepDataType),
-            "promise": GraphQLField(DataType),
-        },
-    )
-
-    DeepDataType = GraphQLObjectType(
-        "DeepDataType",
-        {
-            "a": GraphQLField(GraphQLString),
-            "b": GraphQLField(GraphQLString),
-            "c": GraphQLField(GraphQLList(GraphQLString)),
-            "deeper": GraphQLField(GraphQLList(DataType)),
-        },
-    )
-
-    schema = GraphQLSchema(query=DataType)
-
-    def handle_result(result):
-        # type: (ExecutionResult) -> None
-        assert not result.errors
-        assert result.data == expected
-
-    handle_result(
-        execute(
-            schema,
-            ast,
-            Data(),
-            variable_values={"size": 100},
-            operation_name="Example",
-            executor=ThreadExecutor(),
-        )
-    )
-    handle_result(
-        execute(
-            schema, ast, Data(), variable_values={"size": 100}, operation_name="Example"
-        )
-    )
-
-
-def test_synchronous_error_nulls_out_error_subtrees():
-    # type: () -> None
-    ast = parse(
-        """
-    {
-        sync
-        syncError
-        syncReturnError
-        syncReturnErrorList
-        asyncBasic
-        asyncReject
-        asyncEmptyReject
-        asyncReturnError
-    }
-    """
-    )
-
-    class Data:
-        def sync(self):
-            # type: () -> str
-            return "sync"
-
-        def syncError(self):
-            # type: () -> NoReturn
-            raise Exception("Error getting syncError")
-
-        def syncReturnError(self):
-            # type: () -> Exception
-            return Exception("Error getting syncReturnError")
-
-        def syncReturnErrorList(self):
-            # type: () -> List[Union[Exception, str]]
-            return [
-                "sync0",
-                Exception("Error getting syncReturnErrorList1"),
-                "sync2",
-                Exception("Error getting syncReturnErrorList3"),
-            ]
-
-        def asyncBasic(self):
-            # type: () -> Promise
-            return resolved("async")
-
-        def asyncReject(self):
-            # type: () -> Promise
-            return rejected(Exception("Error getting asyncReject"))
-
-        def asyncEmptyReject(self):
-            # type: () -> Promise
-            return rejected(Exception("An unknown error occurred."))
-
-        def asyncReturnError(self):
-            # type: () -> Promise
-            return resolved(Exception("Error getting asyncReturnError"))
-
-    schema = GraphQLSchema(
-        query=GraphQLObjectType(
-            name="Type",
-            fields={
-                "sync": GraphQLField(GraphQLString),
-                "syncError": GraphQLField(GraphQLString),
-                "syncReturnError": GraphQLField(GraphQLString),
-                "syncReturnErrorList": GraphQLField(GraphQLList(GraphQLString)),
-                "asyncBasic": GraphQLField(GraphQLString),
-                "asyncReject": GraphQLField(GraphQLString),
-                "asyncEmptyReject": GraphQLField(GraphQLString),
-                "asyncReturnError": GraphQLField(GraphQLString),
-            },
-        )
-    )
-
-    def sort_key(item):
-        # type: (Dict[str, Any]) -> Tuple[int, int]
-        locations = item["locations"][0]
-        return (locations["line"], locations["column"])
-
-    def handle_results(result):
-        # type: (ExecutionResult) -> None
-        assert result.data == {
-            "asyncBasic": "async",
-            "asyncEmptyReject": None,
-            "asyncReject": None,
-            "asyncReturnError": None,
-            "sync": "sync",
-            "syncError": None,
-            "syncReturnError": None,
-            "syncReturnErrorList": ["sync0", None, "sync2", None],
-        }
-        assert sorted(list(map(format_error, result.errors)), key=sort_key) == sorted(
-            [
-                {
-                    "locations": [{"line": 4, "column": 9}],
-                    "path": ["syncError"],
-                    "message": "Error getting syncError",
-                },
-                {
-                    "locations": [{"line": 5, "column": 9}],
-                    "path": ["syncReturnError"],
-                    "message": "Error getting syncReturnError",
-                },
-                {
-                    "locations": [{"line": 6, "column": 9}],
-                    "path": ["syncReturnErrorList", 1],
-                    "message": "Error getting syncReturnErrorList1",
-                },
-                {
-                    "locations": [{"line": 6, "column": 9}],
-                    "path": ["syncReturnErrorList", 3],
-                    "message": "Error getting syncReturnErrorList3",
-                },
-                {
-                    "locations": [{"line": 8, "column": 9}],
-                    "path": ["asyncReject"],
-                    "message": "Error getting asyncReject",
-                },
-                {
-                    "locations": [{"line": 9, "column": 9}],
-                    "path": ["asyncEmptyReject"],
-                    "message": "An unknown error occurred.",
-                },
-                {
-                    "locations": [{"line": 10, "column": 9}],
-                    "path": ["asyncReturnError"],
-                    "message": "Error getting asyncReturnError",
-                },
-            ],
-            key=sort_key,
-        )
-
-    handle_results(execute(schema, ast, Data(), executor=ThreadExecutor()))
-
-
-def test_evaluates_mutations_serially():
-    # type: () -> None
-    assert_evaluate_mutations_serially(executor=ThreadExecutor())
diff --git a/graphql/execution/tests/test_format_error.py b/graphql/execution/tests/test_format_error.py
deleted file mode 100644
index 67a75f4..0000000
--- a/graphql/execution/tests/test_format_error.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# coding: utf-8
-import pytest
-
-from graphql.error import GraphQLError, format_error
-
-
-@pytest.mark.parametrize(
-    "error",
-    [
-        GraphQLError("UNIÇODÉ!"),
-        GraphQLError("\xd0\xbe\xd1\x88\xd0\xb8\xd0\xb1\xd0\xba\xd0\xb0"),
-    ],
-)
-def test_unicode_format_error(error):
-    # type: (GraphQLError) -> None
-    assert isinstance(format_error(error), dict)
diff --git a/graphql/execution/tests/test_lists.py b/graphql/execution/tests/test_lists.py
deleted file mode 100644
index 3534a13..0000000
--- a/graphql/execution/tests/test_lists.py
+++ /dev/null
@@ -1,389 +0,0 @@
-# type: ignore
-from collections import namedtuple
-
-from graphql.error import format_error
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLSchema,
-)
-
-from .utils import rejected, resolved
-
-Data = namedtuple("Data", "test")
-ast = parse("{ nest { test } }")
-
-
-def check(test_data, expected):
-    def run_check(self):
-        # type: (Any) -> None
-        test_type = self.type
-
-        data = Data(test=test_data)
-        DataType = GraphQLObjectType(
-            name="DataType",
-            fields=lambda: {
-                "test": GraphQLField(test_type),
-                "nest": GraphQLField(DataType, resolver=lambda *_: data),
-            },
-        )
-
-        schema = GraphQLSchema(query=DataType)
-        response = execute(schema, ast, data)
-
-        if response.errors:
-            result = {
-                "data": response.data,
-                "errors": [format_error(e) for e in response.errors],
-            }
-        else:
-            result = {"data": response.data}
-
-        assert result == expected
-
-    return run_check
-
-
-class Test_ListOfT_Array_T:  # [T] Array<T>
-    type = GraphQLList(GraphQLInt)
-
-    test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check([1, None, 2], {"data": {"nest": {"test": [1, None, 2]}}})
-    test_returns_null = check(None, {"data": {"nest": {"test": None}}})
-
-
-class Test_ListOfT_Promise_Array_T:  # [T] Promise<Array<T>>
-    type = GraphQLList(GraphQLInt)
-
-    test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}}
-    )
-    test_returns_null = check(resolved(None), {"data": {"nest": {"test": None}}})
-    test_rejected = check(
-        lambda: rejected(Exception("bad")),
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class Test_ListOfT_Array_Promise_T:  # [T] Array<Promise<T>>
-    type = GraphQLList(GraphQLInt)
-
-    test_contains_values = check(
-        [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}}
-    )
-    test_contains_null = check(
-        [resolved(1), resolved(None), resolved(2)],
-        {"data": {"nest": {"test": [1, None, 2]}}},
-    )
-    test_contains_reject = check(
-        lambda: [resolved(1), rejected(Exception("bad")), resolved(2)],
-        {
-            "data": {"nest": {"test": [1, None, 2]}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class Test_NotNullListOfT_Array_T:  # [T]! Array<T>
-    type = GraphQLNonNull(GraphQLList(GraphQLInt))
-
-    test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}}
-    )
-    test_returns_null = check(
-        resolved(None),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-
-class Test_NotNullListOfT_Promise_Array_T:  # [T]! Promise<Array<T>>>
-    type = GraphQLNonNull(GraphQLList(GraphQLInt))
-
-    test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}}
-    )
-    test_returns_null = check(
-        resolved(None),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-    test_rejected = check(
-        lambda: rejected(Exception("bad")),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class Test_NotNullListOfT_Array_Promise_T:  # [T]! Promise<Array<T>>>
-    type = GraphQLNonNull(GraphQLList(GraphQLInt))
-    test_contains_values = check(
-        [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}}
-    )
-    test_contains_null = check(
-        [resolved(1), resolved(None), resolved(2)],
-        {"data": {"nest": {"test": [1, None, 2]}}},
-    )
-    test_contains_reject = check(
-        lambda: [resolved(1), rejected(Exception("bad")), resolved(2)],
-        {
-            "data": {"nest": {"test": [1, None, 2]}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class TestListOfNotNullT_Array_T:  # [T!] Array<T>
-    type = GraphQLList(GraphQLNonNull(GraphQLInt))
-
-    test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        [1, None, 2],
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-    test_returns_null = check(None, {"data": {"nest": {"test": None}}})
-
-
-class TestListOfNotNullT_Promise_Array_T:  # [T!] Promise<Array<T>>
-    type = GraphQLList(GraphQLNonNull(GraphQLInt))
-
-    test_contains_value = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        resolved([1, None, 2]),
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-    test_returns_null = check(resolved(None), {"data": {"nest": {"test": None}}})
-
-    test_rejected = check(
-        lambda: rejected(Exception("bad")),
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class TestListOfNotNullT_Array_Promise_T:  # [T!] Array<Promise<T>>
-    type = GraphQLList(GraphQLNonNull(GraphQLInt))
-
-    test_contains_values = check(
-        [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}}
-    )
-    test_contains_null = check(
-        [resolved(1), resolved(None), resolved(2)],
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-    test_contains_reject = check(
-        lambda: [resolved(1), rejected(Exception("bad")), resolved(2)],
-        {
-            "data": {"nest": {"test": None}},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class TestNotNullListOfNotNullT_Array_T:  # [T!]! Array<T>
-    type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt)))
-
-    test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        [1, None, 2],
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-    test_returns_null = check(
-        None,
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-
-class TestNotNullListOfNotNullT_Promise_Array_T:  # [T!]! Promise<Array<T>>
-    type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt)))
-
-    test_contains_value = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}})
-    test_contains_null = check(
-        resolved([1, None, 2]),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-    test_returns_null = check(
-        resolved(None),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-
-    test_rejected = check(
-        lambda: rejected(Exception("bad")),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test"],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
-
-
-class TestNotNullListOfNotNullT_Array_Promise_T:  # [T!]! Array<Promise<T>>
-    type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt)))
-
-    test_contains_values = check(
-        [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}}
-    )
-    test_contains_null = check(
-        [resolved(1), resolved(None), resolved(2)],
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "Cannot return null for non-nullable field DataType.test.",
-                }
-            ],
-        },
-    )
-    test_contains_reject = check(
-        lambda: [resolved(1), rejected(Exception("bad")), resolved(2)],
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 10, "line": 1}],
-                    "path": ["nest", "test", 1],
-                    "message": "bad",
-                }
-            ],
-        },
-    )
diff --git a/graphql/execution/tests/test_located_error.py b/graphql/execution/tests/test_located_error.py
deleted file mode 100644
index b5bec97..0000000
--- a/graphql/execution/tests/test_located_error.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# type: ignore
-# coding: utf-8
-
-from graphql import (
-    GraphQLField,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-    execute,
-    parse,
-)
-from graphql.error import GraphQLLocatedError
-
-
-def test_unicode_error_message():
-    # type: () -> None
-    ast = parse("query Example { unicode }")
-
-    def resolver(context, *_):
-        # type: (Optional[Any], *ResolveInfo) -> NoReturn
-        raise Exception(u"UNIÇODÉ!")
-
-    Type = GraphQLObjectType(
-        "Type", {"unicode": GraphQLField(GraphQLString, resolver=resolver)}
-    )
-
-    result = execute(GraphQLSchema(Type), ast)
-    assert isinstance(result.errors[0], GraphQLLocatedError)
diff --git a/graphql/execution/tests/test_middleware.py b/graphql/execution/tests/test_middleware.py
deleted file mode 100644
index 9715288..0000000
--- a/graphql/execution/tests/test_middleware.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# type: ignore
-from __future__ import print_function
-
-import json
-
-from pytest import raises
-from graphql.error import GraphQLError
-from graphql.execution import MiddlewareManager, execute
-from graphql.execution.middleware import get_middleware_resolvers, middleware_chain
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLBoolean,
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-    GraphQLNonNull,
-    GraphQLID,
-)
-from promise import Promise
-
-
-def test_middleware():
-    # type: () -> None
-    doc = """{
-        ok
-        not_ok
-    }"""
-
-    class Data(object):
-        def ok(self):
-            # type: () -> str
-            return "ok"
-
-        def not_ok(self):
-            # type: () -> str
-            return "not_ok"
-
-    doc_ast = parse(doc)
-
-    Type = GraphQLObjectType(
-        "Type",
-        {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)},
-    )
-
-    def reversed_middleware(next, *args, **kwargs):
-        # type: (Callable, *Any, **Any) -> Promise
-        p = next(*args, **kwargs)
-        return p.then(lambda x: x[::-1])
-
-    middlewares = MiddlewareManager(reversed_middleware)
-    result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares)
-    assert result.data == {"ok": "ko", "not_ok": "ko_ton"}
-
-
-def test_middleware_class():
-    # type: () -> None
-    doc = """{
-        ok
-        not_ok
-    }"""
-
-    class Data(object):
-        def ok(self):
-            # type: () -> str
-            return "ok"
-
-        def not_ok(self):
-            # type: () -> str
-            return "not_ok"
-
-    doc_ast = parse(doc)
-
-    Type = GraphQLObjectType(
-        "Type",
-        {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)},
-    )
-
-    class MyMiddleware(object):
-        def resolve(self, next, *args, **kwargs):
-            # type: (Callable, *Any, **Any) -> Promise
-            p = next(*args, **kwargs)
-            return p.then(lambda x: x[::-1])
-
-    middlewares = MiddlewareManager(MyMiddleware())
-    result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares)
-    assert result.data == {"ok": "ko", "not_ok": "ko_ton"}
-
-
-def test_middleware_skip_promise_wrap():
-    # type: () -> None
-    doc = """{
-        ok
-        not_ok
-    }"""
-
-    class Data(object):
-        def ok(self):
-            # type: () -> str
-            return "ok"
-
-        def not_ok(self):
-            # type: () -> str
-            return "not_ok"
-
-    doc_ast = parse(doc)
-
-    Type = GraphQLObjectType(
-        "Type",
-        {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)},
-    )
-
-    class MyPromiseMiddleware(object):
-        def resolve(self, next, *args, **kwargs):
-            # type: (Callable, *Any, **Any) -> Promise
-            return Promise.resolve(next(*args, **kwargs))
-
-    class MyEmptyMiddleware(object):
-        def resolve(self, next, *args, **kwargs):
-            # type: (Callable, *Any, **Any) -> str
-            return next(*args, **kwargs)
-
-    middlewares_with_promise = MiddlewareManager(
-        MyPromiseMiddleware(), wrap_in_promise=False
-    )
-    middlewares_without_promise = MiddlewareManager(
-        MyEmptyMiddleware(), wrap_in_promise=False
-    )
-
-    result1 = execute(
-        GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares_with_promise
-    )
-    result2 = execute(
-        GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares_without_promise
-    )
-    assert result1.data == result2.data and result1.data == {
-        "ok": "ok",
-        "not_ok": "not_ok",
-    }
-
-
-def test_middleware_chain(capsys):
-    # type: (Any) -> None
-    class CharPrintingMiddleware(object):
-        def __init__(self, char):
-            # type: (str) -> None
-            self.char = char
-
-        def resolve(self, next, *args, **kwargs):
-            # type: (Callable, *Any, **Any) -> str
-            print("resolve() called for middleware {}".format(self.char))
-            return next(*args, **kwargs).then(
-                lambda x: print("then() for {}".format(self.char))
-            )
-
-    middlewares = [
-        CharPrintingMiddleware("a"),
-        CharPrintingMiddleware("b"),
-        CharPrintingMiddleware("c"),
-    ]
-
-    middlewares_resolvers = get_middleware_resolvers(middlewares)
-
-    def func():
-        # type: () -> None
-        return
-
-    chain_iter = middleware_chain(func, middlewares_resolvers, wrap_in_promise=True)
-
-    assert_stdout(capsys, "")
-
-    chain_iter()
-
-    expected_stdout = (
-        "resolve() called for middleware c\n"
-        "resolve() called for middleware b\n"
-        "resolve() called for middleware a\n"
-        "then() for a\n"
-        "then() for b\n"
-        "then() for c\n"
-    )
-    assert_stdout(capsys, expected_stdout)
-
-
-def assert_stdout(capsys, expected_stdout):
-    # type: (Any, str) -> None
-    captured = capsys.readouterr()
-    assert captured.out == expected_stdout
diff --git a/graphql/execution/tests/test_mutations.py b/graphql/execution/tests/test_mutations.py
deleted file mode 100644
index d7ec17b..0000000
--- a/graphql/execution/tests/test_mutations.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# type: ignore
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLField,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-)
-
-# from graphql.execution.executors.asyncio import AsyncioExecutor
-# from graphql.execution.executors.thread import ThreadExecutor
-# from typing import Union
-
-
-class NumberHolder(object):
-    def __init__(self, n):
-        # type: (int) -> None
-        self.theNumber = n
-
-
-class Root(object):
-    def __init__(self, n):
-        # type: (int) -> None
-        self.numberHolder = NumberHolder(n)
-
-    def immediately_change_the_number(self, n):
-        # type: (int) -> NumberHolder
-        self.numberHolder.theNumber = n
-        return self.numberHolder
-
-    def promise_to_change_the_number(self, n):
-        # type: (int) -> NumberHolder
-        # TODO: async
-        return self.immediately_change_the_number(n)
-
-    def fail_to_change_the_number(self, n):
-        # type: (int) -> None
-        raise Exception("Cannot change the number")
-
-    def promise_and_fail_to_change_the_number(self, n):
-        # type: (int) -> None
-        # TODO: async
-        self.fail_to_change_the_number(n)
-
-
-NumberHolderType = GraphQLObjectType(
-    "NumberHolder", {"theNumber": GraphQLField(GraphQLInt)}
-)
-
-QueryType = GraphQLObjectType("Query", {"numberHolder": GraphQLField(NumberHolderType)})
-
-MutationType = GraphQLObjectType(
-    "Mutation",
-    {
-        "immediatelyChangeTheNumber": GraphQLField(
-            NumberHolderType,
-            args={"newNumber": GraphQLArgument(GraphQLInt)},
-            resolver=lambda obj, info, **args: obj.immediately_change_the_number(
-                args["newNumber"]
-            ),
-        ),
-        "promiseToChangeTheNumber": GraphQLField(
-            NumberHolderType,
-            args={"newNumber": GraphQLArgument(GraphQLInt)},
-            resolver=lambda obj, info, **args: obj.promise_to_change_the_number(
-                args["newNumber"]
-            ),
-        ),
-        "failToChangeTheNumber": GraphQLField(
-            NumberHolderType,
-            args={"newNumber": GraphQLArgument(GraphQLInt)},
-            resolver=lambda obj, info, **args: obj.fail_to_change_the_number(
-                args["newNumber"]
-            ),
-        ),
-        "promiseAndFailToChangeTheNumber": GraphQLField(
-            NumberHolderType,
-            args={"newNumber": GraphQLArgument(GraphQLInt)},
-            resolver=lambda obj, info, **args: obj.promise_and_fail_to_change_the_number(
-                args["newNumber"]
-            ),
-        ),
-    },
-)
-
-schema = GraphQLSchema(QueryType, MutationType)
-
-
-def assert_evaluate_mutations_serially(executor=None):
-    # type: (Union[None, AsyncioExecutor, ThreadExecutor]) -> None
-    doc = """mutation M {
-      first: immediatelyChangeTheNumber(newNumber: 1) {
-        theNumber
-      },
-      second: promiseToChangeTheNumber(newNumber: 2) {
-        theNumber
-      },
-      third: immediatelyChangeTheNumber(newNumber: 3) {
-        theNumber
-      }
-      fourth: promiseToChangeTheNumber(newNumber: 4) {
-        theNumber
-      },
-      fifth: immediatelyChangeTheNumber(newNumber: 5) {
-        theNumber
-      }
-    }"""
-    ast = parse(doc)
-    result = execute(schema, ast, Root(6), operation_name="M", executor=executor)
-    assert not result.errors
-    assert result.data == {
-        "first": {"theNumber": 1},
-        "second": {"theNumber": 2},
-        "third": {"theNumber": 3},
-        "fourth": {"theNumber": 4},
-        "fifth": {"theNumber": 5},
-    }
-
-
-def test_evaluates_mutations_serially():
-    # type: () -> None
-    assert_evaluate_mutations_serially()
-
-
-def test_evaluates_mutations_correctly_in_the_presense_of_a_failed_mutation():
-    # type: () -> None
-    doc = """mutation M {
-      first: immediatelyChangeTheNumber(newNumber: 1) {
-        theNumber
-      },
-      second: promiseToChangeTheNumber(newNumber: 2) {
-        theNumber
-      },
-      third: failToChangeTheNumber(newNumber: 3) {
-        theNumber
-      }
-      fourth: promiseToChangeTheNumber(newNumber: 4) {
-        theNumber
-      },
-      fifth: immediatelyChangeTheNumber(newNumber: 5) {
-        theNumber
-      }
-      sixth: promiseAndFailToChangeTheNumber(newNumber: 6) {
-        theNumber
-      }
-    }"""
-    ast = parse(doc)
-    result = execute(schema, ast, Root(6), operation_name="M")
-    assert result.data == {
-        "first": {"theNumber": 1},
-        "second": {"theNumber": 2},
-        "third": None,
-        "fourth": {"theNumber": 4},
-        "fifth": {"theNumber": 5},
-        "sixth": None,
-    }
-    assert len(result.errors) == 2
-    # TODO: check error location
-    assert result.errors[0].message == "Cannot change the number"
-    assert result.errors[1].message == "Cannot change the number"
diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py
deleted file mode 100644
index 6f8a372..0000000
--- a/graphql/execution/tests/test_nonnull.py
+++ /dev/null
@@ -1,895 +0,0 @@
-# type: ignore
-from graphql.error import format_error
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLField,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-)
-
-from .utils import rejected, resolved
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from promise import Promise
-    from typing import Any, Optional, Dict, Tuple, Union
-
-sync_error = Exception("sync")
-non_null_sync_error = Exception("nonNullSync")
-promise_error = Exception("promise")
-non_null_promise_error = Exception("nonNullPromise")
-
-
-class ThrowingData(object):
-    def sync(self):
-        # type: () -> None
-        raise sync_error
-
-    def nonNullSync(self):
-        # type: () -> None
-        raise non_null_sync_error
-
-    def promise(self):
-        # type: () -> Promise
-        return rejected(promise_error)
-
-    def nonNullPromise(self):
-        # type: () -> Promise
-        return rejected(non_null_promise_error)
-
-    def nest(self):
-        # type: () -> ThrowingData
-        return ThrowingData()
-
-    def nonNullNest(self):
-        # type: () -> ThrowingData
-        return ThrowingData()
-
-    def promiseNest(self):
-        # type: () -> Promise
-        return resolved(ThrowingData())
-
-    def nonNullPromiseNest(self):
-        # type: () -> Promise
-        return resolved(ThrowingData())
-
-
-class NullingData(object):
-    def sync(self):
-        # type: () -> Optional[Any]
-        return None
-
-    def nonNullSync(self):
-        # type: () -> Optional[Any]
-        return None
-
-    def promise(self):
-        # type: () -> Promise
-        return resolved(None)
-
-    def nonNullPromise(self):
-        # type: () -> Promise
-        return resolved(None)
-
-    def nest(self):
-        # type: () -> NullingData
-        return NullingData()
-
-    def nonNullNest(self):
-        # type: () -> NullingData
-        return NullingData()
-
-    def promiseNest(self):
-        # type: () -> Promise
-        return resolved(NullingData())
-
-    def nonNullPromiseNest(self):
-        # type: () -> Promise
-        return resolved(NullingData())
-
-
-DataType = GraphQLObjectType(
-    "DataType",
-    lambda: {
-        "sync": GraphQLField(GraphQLString),
-        "nonNullSync": GraphQLField(GraphQLNonNull(GraphQLString)),
-        "promise": GraphQLField(GraphQLString),
-        "nonNullPromise": GraphQLField(GraphQLNonNull(GraphQLString)),
-        "nest": GraphQLField(DataType),
-        "nonNullNest": GraphQLField(GraphQLNonNull(DataType)),
-        "promiseNest": GraphQLField(DataType),
-        "nonNullPromiseNest": GraphQLField(GraphQLNonNull(DataType)),
-    },
-)
-
-schema = GraphQLSchema(DataType)
-
-
-def order_errors(error):
-    # type: (Dict[str, Any]) -> Tuple[int, int]
-    locations = error["locations"]
-    return (locations[0]["column"], locations[0]["line"])
-
-
-def check(doc, data, expected):
-    # type: (str, Union[NullingData, ThrowingData], Dict[str, Any]) -> None
-    ast = parse(doc)
-    response = execute(schema, ast, data)
-
-    if response.errors:
-        result = {
-            "data": response.data,
-            "errors": [format_error(e) for e in response.errors],
-        }
-        if result["errors"] != expected["errors"]:
-            assert result["data"] == expected["data"]
-            # Sometimes the fields resolves asynchronously, so
-            # we need to check that the errors are the same, but might be
-            # raised in a different order.
-            assert sorted(result["errors"], key=order_errors) == sorted(
-                expected["errors"], key=order_errors
-            )
-        else:
-            assert result == expected
-    else:
-        result = {"data": response.data}
-
-        assert result == expected
-
-
-def test_nulls_a_nullable_field_that_throws_sync():
-    # type: () -> None
-    doc = """
-        query Q {
-            sync
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"sync": None},
-            "errors": [
-                {
-                    "locations": [{"column": 13, "line": 3}],
-                    "path": ["sync"],
-                    "message": str(sync_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_nullable_field_that_throws_in_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            promise
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"promise": None},
-            "errors": [
-                {
-                    "locations": [{"column": 13, "line": 3}],
-                    "path": ["promise"],
-                    "message": str(promise_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_throws():
-    # type: () -> None
-    doc = """
-        query Q {
-            nest {
-                nonNullSync,
-            }
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["nest", "nonNullSync"],
-                    "message": str(non_null_sync_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_throws_in_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            nest {
-                nonNullPromise,
-            }
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["nest", "nonNullPromise"],
-                    "message": str(non_null_promise_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_synchronously():
-    # type: () -> None
-    doc = """
-        query Q {
-            promiseNest {
-                nonNullSync,
-            }
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"promiseNest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["promiseNest", "nonNullSync"],
-                    "message": str(non_null_sync_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_in_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            promiseNest {
-                nonNullPromise,
-            }
-        }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {"promiseNest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["promiseNest", "nonNullPromise"],
-                    "message": str(non_null_promise_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_complex_tree_of_nullable_fields_that_throw():
-    # type: () -> None
-    doc = """
-      query Q {
-        nest {
-          sync
-          promise
-          nest {
-            sync
-            promise
-          }
-          promiseNest {
-            sync
-            promise
-          }
-        }
-        promiseNest {
-          sync
-          promise
-          nest {
-            sync
-            promise
-          }
-          promiseNest {
-            sync
-            promise
-          }
-        }
-      }
-    """
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {
-                "nest": {
-                    "nest": {"promise": None, "sync": None},
-                    "promise": None,
-                    "promiseNest": {"promise": None, "sync": None},
-                    "sync": None,
-                },
-                "promiseNest": {
-                    "nest": {"promise": None, "sync": None},
-                    "promise": None,
-                    "promiseNest": {"promise": None, "sync": None},
-                    "sync": None,
-                },
-            },
-            "errors": [
-                {
-                    "locations": [{"column": 11, "line": 4}],
-                    "path": ["nest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 11, "line": 5}],
-                    "path": ["nest", "promise"],
-                    "message": str(promise_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 7}],
-                    "path": ["nest", "nest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 8}],
-                    "path": ["nest", "nest", "promise"],
-                    "message": str(promise_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 11}],
-                    "path": ["nest", "promiseNest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 12}],
-                    "path": ["nest", "promiseNest", "promise"],
-                    "message": str(promise_error),
-                },
-                {
-                    "locations": [{"column": 11, "line": 16}],
-                    "path": ["promiseNest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 11, "line": 17}],
-                    "path": ["promiseNest", "promise"],
-                    "message": str(promise_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 19}],
-                    "path": ["promiseNest", "nest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 20}],
-                    "path": ["promiseNest", "nest", "promise"],
-                    "message": str(promise_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 23}],
-                    "path": ["promiseNest", "promiseNest", "sync"],
-                    "message": str(sync_error),
-                },
-                {
-                    "locations": [{"column": 13, "line": 24}],
-                    "path": ["promiseNest", "promiseNest", "promise"],
-                    "message": str(promise_error),
-                },
-            ],
-        },
-    )
-
-
-def test_nulls_the_first_nullable_object_after_a_field_throws_in_a_long_chain_of_fields_that_are_non_null():
-    # type: () -> None
-    doc = """
-    query Q {
-        nest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullSync
-                }
-              }
-            }
-          }
-        }
-        promiseNest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullSync
-                }
-              }
-            }
-          }
-        }
-        anotherNest: nest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullPromise
-                }
-              }
-            }
-          }
-        }
-        anotherPromiseNest: promiseNest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullPromise
-                }
-              }
-            }
-          }
-        }
-      }
-    """
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": {
-                "nest": None,
-                "promiseNest": None,
-                "anotherNest": None,
-                "anotherPromiseNest": None,
-            },
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 8}],
-                    "path": [
-                        "nest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullSync",
-                    ],
-                    "message": str(non_null_sync_error),
-                },
-                {
-                    "locations": [{"column": 19, "line": 19}],
-                    "path": [
-                        "promiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullSync",
-                    ],
-                    "message": str(non_null_sync_error),
-                },
-                {
-                    "locations": [{"column": 19, "line": 30}],
-                    "path": [
-                        "anotherNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullPromise",
-                    ],
-                    "message": str(non_null_promise_error),
-                },
-                {
-                    "locations": [{"column": 19, "line": 41}],
-                    "path": [
-                        "anotherPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullPromise",
-                    ],
-                    "message": str(non_null_promise_error),
-                },
-            ],
-        },
-    )
-
-
-def test_nulls_a_nullable_field_that_returns_null():
-    # type: () -> None
-    doc = """
-        query Q {
-            sync
-        }
-    """
-
-    check(doc, NullingData(), {"data": {"sync": None}})
-
-
-def test_nulls_a_nullable_field_that_returns_null_in_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            promise
-        }
-    """
-
-    check(doc, NullingData(), {"data": {"promise": None}})
-
-
-def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_returns_null_synchronously():
-    # type: () -> None
-    doc = """
-        query Q {
-            nest {
-                nonNullSync,
-            }
-        }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["nest", "nonNullSync"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullSync.",
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_returns_null_in_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            nest {
-                nonNullPromise,
-            }
-        }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {"nest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["nest", "nonNullPromise"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullPromise.",
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_synchronously():
-    # type: () -> None
-    doc = """
-        query Q {
-            promiseNest {
-                nonNullSync,
-            }
-        }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {"promiseNest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["promiseNest", "nonNullSync"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullSync.",
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_ina_a_promise():
-    # type: () -> None
-    doc = """
-        query Q {
-            promiseNest {
-                nonNullPromise
-            }
-        }
-    """
-
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {"promiseNest": None},
-            "errors": [
-                {
-                    "locations": [{"column": 17, "line": 4}],
-                    "path": ["promiseNest", "nonNullPromise"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullPromise.",
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_a_complex_tree_of_nullable_fields_that_returns_null():
-    # type: () -> None
-    doc = """
-      query Q {
-        nest {
-          sync
-          promise
-          nest {
-            sync
-            promise
-          }
-          promiseNest {
-            sync
-            promise
-          }
-        }
-        promiseNest {
-          sync
-          promise
-          nest {
-            sync
-            promise
-          }
-          promiseNest {
-            sync
-            promise
-          }
-        }
-      }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {
-                "nest": {
-                    "sync": None,
-                    "promise": None,
-                    "nest": {"sync": None, "promise": None},
-                    "promiseNest": {"sync": None, "promise": None},
-                },
-                "promiseNest": {
-                    "sync": None,
-                    "promise": None,
-                    "nest": {"sync": None, "promise": None},
-                    "promiseNest": {"sync": None, "promise": None},
-                },
-            }
-        },
-    )
-
-
-def test_nulls_the_first_nullable_object_after_a_field_returns_null_in_a_long_chain_of_fields_that_are_non_null():
-    # type: () -> None
-    doc = """
-      query Q {
-        nest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullSync
-                }
-              }
-            }
-          }
-        }
-        promiseNest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullSync
-                }
-              }
-            }
-          }
-        }
-        anotherNest: nest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullPromise
-                }
-              }
-            }
-          }
-        }
-        anotherPromiseNest: promiseNest {
-          nonNullNest {
-            nonNullPromiseNest {
-              nonNullNest {
-                nonNullPromiseNest {
-                  nonNullPromise
-                }
-              }
-            }
-          }
-        }
-      }
-    """
-
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": {
-                "nest": None,
-                "promiseNest": None,
-                "anotherNest": None,
-                "anotherPromiseNest": None,
-            },
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 8}],
-                    "path": [
-                        "nest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullSync",
-                    ],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullSync.",
-                },
-                {
-                    "locations": [{"column": 19, "line": 19}],
-                    "path": [
-                        "promiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullSync",
-                    ],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullSync.",
-                },
-                {
-                    "locations": [{"column": 19, "line": 30}],
-                    "path": [
-                        "anotherNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullPromise",
-                    ],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullPromise.",
-                },
-                {
-                    "locations": [{"column": 19, "line": 41}],
-                    "path": [
-                        "anotherPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullNest",
-                        "nonNullPromiseNest",
-                        "nonNullPromise",
-                    ],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullPromise.",
-                },
-            ],
-        },
-    )
-
-
-def test_nulls_the_top_level_if_sync_non_nullable_field_throws():
-    # type: () -> None
-    doc = """
-        query Q { nonNullSync }
-    """
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": None,
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 2}],
-                    "path": ["nonNullSync"],
-                    "message": str(non_null_sync_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_the_top_level_if_async_non_nullable_field_errors():
-    # type: () -> None
-    doc = """
-        query Q { nonNullPromise }
-    """
-
-    check(
-        doc,
-        ThrowingData(),
-        {
-            "data": None,
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 2}],
-                    "path": ["nonNullPromise"],
-                    "message": str(non_null_promise_error),
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_the_top_level_if_sync_non_nullable_field_returns_null():
-    # type: () -> None
-    doc = """
-        query Q { nonNullSync }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": None,
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 2}],
-                    "path": ["nonNullSync"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullSync.",
-                }
-            ],
-        },
-    )
-
-
-def test_nulls_the_top_level_if_async_non_nullable_field_resolves_null():
-    # type: () -> None
-    doc = """
-        query Q { nonNullPromise }
-    """
-    check(
-        doc,
-        NullingData(),
-        {
-            "data": None,
-            "errors": [
-                {
-                    "locations": [{"column": 19, "line": 2}],
-                    "path": ["nonNullPromise"],
-                    "message": "Cannot return null for non-nullable field DataType.nonNullPromise.",
-                }
-            ],
-        },
-    )
diff --git a/graphql/execution/tests/test_resolve.py b/graphql/execution/tests/test_resolve.py
deleted file mode 100644
index 8501558..0000000
--- a/graphql/execution/tests/test_resolve.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# type: ignore
-import json
-from collections import OrderedDict
-
-from graphql import graphql
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLField,
-    GraphQLInputObjectField,
-    GraphQLInputObjectType,
-    GraphQLInt,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-)
-from promise import Promise
-
-# from graphql.execution.base import ResolveInfo
-# from typing import Any
-# from typing import Optional
-# from promise.promise import Promise
-# from graphql.type.definition import GraphQLField
-# from graphql.type.schema import GraphQLSchema
-
-
-class CustomPromise(Promise):
-    @classmethod
-    def fulfilled(cls, x):
-        # type: (str) -> CustomPromise
-        p = cls()
-        p.fulfill(x)
-        return p
-
-    resolve = fulfilled
-
-    @classmethod
-    def rejected(cls, reason):
-        p = cls()
-        p.reject(reason)
-        return p
-
-
-def _test_schema(test_field):
-    # type: (GraphQLField) -> GraphQLSchema
-    return GraphQLSchema(
-        query=GraphQLObjectType(name="Query", fields={"test": test_field})
-    )
-
-
-def test_default_function_accesses_properties():
-    # type: () -> None
-    schema = _test_schema(GraphQLField(GraphQLString))
-
-    class source:
-        test = "testValue"
-
-    result = graphql(schema, "{ test }", source)
-    assert not result.errors
-    assert result.data == {"test": "testValue"}
-
-
-def test_default_function_calls_methods():
-    # type: () -> None
-    schema = _test_schema(GraphQLField(GraphQLString))
-
-    class source:
-        _secret = "testValue"
-
-        def test(self):
-            # type: () -> str
-            return self._secret
-
-    result = graphql(schema, "{ test }", source())
-    assert not result.errors
-    assert result.data == {"test": "testValue"}
-
-
-def test_uses_provided_resolve_function():
-    # type: () -> None
-    def resolver(source, info, **args):
-        # type: (Optional[str], ResolveInfo, **Any) -> str
-        return json.dumps([source, args], separators=(",", ":"))
-
-    schema = _test_schema(
-        GraphQLField(
-            GraphQLString,
-            args=OrderedDict(
-                [
-                    ("aStr", GraphQLArgument(GraphQLString)),
-                    ("aInt", GraphQLArgument(GraphQLInt)),
-                ]
-            ),
-            resolver=resolver,
-        )
-    )
-
-    result = graphql(schema, "{ test }", None)
-    assert not result.errors
-    assert result.data == {"test": "[null,{}]"}
-
-    result = graphql(schema, '{ test(aStr: "String!") }', "Source!")
-    assert not result.errors
-    assert result.data == {"test": '["Source!",{"aStr":"String!"}]'}
-
-    result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', "Source!")
-    assert not result.errors
-    assert result.data in [
-        {"test": '["Source!",{"aStr":"String!","aInt":-123}]'},
-        {"test": '["Source!",{"aInt":-123,"aStr":"String!"}]'},
-    ]
-
-
-def test_handles_resolved_promises():
-    # type: () -> None
-    def resolver(source, info, **args):
-        # type: (Optional[Any], ResolveInfo, **Any) -> Promise
-        return Promise.resolve("foo")
-
-    schema = _test_schema(GraphQLField(GraphQLString, resolver=resolver))
-
-    result = graphql(schema, "{ test }", None)
-    assert not result.errors
-    assert result.data == {"test": "foo"}
-
-
-def test_handles_resolved_custom_promises():
-    # type: () -> None
-    def resolver(source, info, **args):
-        # type: (Optional[Any], ResolveInfo, **Any) -> CustomPromise
-        return CustomPromise.resolve("custom_foo")
-
-    schema = _test_schema(GraphQLField(GraphQLString, resolver=resolver))
-
-    result = graphql(schema, "{ test }", None)
-    assert not result.errors
-    assert result.data == {"test": "custom_foo"}
-
-
-def test_maps_argument_out_names_well():
-    # type: () -> None
-    def resolver(source, info, **args):
-        # type: (Optional[str], ResolveInfo, **Any) -> str
-        return json.dumps([source, args], separators=(",", ":"))
-
-    schema = _test_schema(
-        GraphQLField(
-            GraphQLString,
-            args=OrderedDict(
-                [
-                    ("aStr", GraphQLArgument(GraphQLString, out_name="a_str")),
-                    ("aInt", GraphQLArgument(GraphQLInt, out_name="a_int")),
-                ]
-            ),
-            resolver=resolver,
-        )
-    )
-
-    result = graphql(schema, "{ test }", None)
-    assert not result.errors
-    assert result.data == {"test": "[null,{}]"}
-
-    result = graphql(schema, '{ test(aStr: "String!") }', "Source!")
-    assert not result.errors
-    assert result.data == {"test": '["Source!",{"a_str":"String!"}]'}
-
-    result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', "Source!")
-    assert not result.errors
-    assert result.data in [
-        {"test": '["Source!",{"a_str":"String!","a_int":-123}]'},
-        {"test": '["Source!",{"a_int":-123,"a_str":"String!"}]'},
-    ]
-
-
-def test_maps_argument_out_names_well_with_input():
-    # type: () -> None
-    def resolver(source, info, **args):
-        # type: (Optional[str], ResolveInfo, **Any) -> str
-        return json.dumps([source, args], separators=(",", ":"))
-
-    TestInputObject = GraphQLInputObjectType(
-        "TestInputObject",
-        lambda: OrderedDict(
-            [
-                (
-                    "inputOne",
-                    GraphQLInputObjectField(GraphQLString, out_name="input_one"),
-                ),
-                (
-                    "inputRecursive",
-                    GraphQLInputObjectField(
-                        TestInputObject, out_name="input_recursive"
-                    ),
-                ),
-            ]
-        ),
-    )
-
-    schema = _test_schema(
-        GraphQLField(
-            GraphQLString,
-            args=OrderedDict(
-                [("aInput", GraphQLArgument(TestInputObject, out_name="a_input"))]
-            ),
-            resolver=resolver,
-        )
-    )
-
-    result = graphql(schema, "{ test }", None)
-    assert not result.errors
-    assert result.data == {"test": "[null,{}]"}
-
-    result = graphql(schema, '{ test(aInput: {inputOne: "String!"} ) }', "Source!")
-    assert not result.errors
-    assert result.data == {"test": '["Source!",{"a_input":{"input_one":"String!"}}]'}
-
-    result = graphql(
-        schema,
-        '{ test(aInput: {inputRecursive:{inputOne: "SourceRecursive!"}} ) }',
-        "Source!",
-    )
-    assert not result.errors
-    assert result.data == {
-        "test": '["Source!",{"a_input":{"input_recursive":{"input_one":"SourceRecursive!"}}}]'
-    }
-
-
-def test_default_resolve_works_with_dicts():
-    schema = _test_schema(GraphQLField(GraphQLString))
-    result = graphql(schema, "{ test }", {"test": "testValue"})
-    assert not result.errors
-    assert result.data == {"test": "testValue"}
diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py
deleted file mode 100644
index 2fa039c..0000000
--- a/graphql/execution/tests/test_subscribe.py
+++ /dev/null
@@ -1,427 +0,0 @@
-# type: ignore
-from collections import OrderedDict, namedtuple
-from rx import Observable, Observer
-from rx.subjects import Subject
-from graphql import (
-    parse,
-    GraphQLObjectType,
-    GraphQLString,
-    GraphQLBoolean,
-    GraphQLInt,
-    GraphQLField,
-    GraphQLList,
-    GraphQLSchema,
-    graphql,
-    subscribe,
-)
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from graphql.execution.base import ResolveInfo
-    from rx import Observable
-    from typing import Optional, Union, Any, Callable, Tuple
-    from graphql.execution.base import ExecutionResult
-
-Email = namedtuple("Email", "from_,subject,message,unread")
-
-EmailType = GraphQLObjectType(
-    name="Email",
-    fields=OrderedDict(
-        [
-            ("from", GraphQLField(GraphQLString, resolver=lambda x, info: x.from_)),
-            ("subject", GraphQLField(GraphQLString)),
-            ("message", GraphQLField(GraphQLString)),
-            ("unread", GraphQLField(GraphQLBoolean)),
-        ]
-    ),
-)
-
-InboxType = GraphQLObjectType(
-    name="Inbox",
-    fields=OrderedDict(
-        [
-            (
-                "total",
-                GraphQLField(
-                    GraphQLInt, resolver=lambda inbox, context: len(inbox.emails)
-                ),
-            ),
-            (
-                "unread",
-                GraphQLField(
-                    GraphQLInt,
-                    resolver=lambda inbox, context: len(
-                        [e for e in inbox.emails if e.unread]
-                    ),
-                ),
-            ),
-            ("emails", GraphQLField(GraphQLList(EmailType))),
-        ]
-    ),
-)
-
-QueryType = GraphQLObjectType(
-    name="Query", fields=OrderedDict([("inbox", GraphQLField(InboxType))])
-)
-
-EmailEventType = GraphQLObjectType(
-    name="EmailEvent",
-    fields=OrderedDict(
-        [
-            ("email", GraphQLField(EmailType, resolver=lambda root, info: root[0])),
-            ("inbox", GraphQLField(InboxType, resolver=lambda root, info: root[1])),
-        ]
-    ),
-)
-
-
-def get_unbound_function(func):
-    # type: (Callable) -> Callable
-    if not getattr(func, "__self__", True):
-        return func.__func__
-    return func
-
-
-def email_schema_with_resolvers(resolve_fn=None):
-    # type: (Callable) -> GraphQLSchema
-    def default_resolver(root, info):
-        # type: (Any, ResolveInfo) -> Union[Observable, Subject]
-        func = getattr(root, "importantEmail", None)
-        if func:
-            func = get_unbound_function(func)
-            return func()
-        return Observable.empty()
-
-    return GraphQLSchema(
-        query=QueryType,
-        subscription=GraphQLObjectType(
-            name="Subscription",
-            fields=OrderedDict(
-                [
-                    (
-                        "importantEmail",
-                        GraphQLField(
-                            EmailEventType, resolver=resolve_fn or default_resolver
-                        ),
-                    )
-                ]
-            ),
-        ),
-    )
-
-
-email_schema = email_schema_with_resolvers()
-
-
-class MyObserver(Observer):
-    def on_next(self, value):
-        self.has_on_next = value
-
-    def on_error(self, err):
-        self.has_on_error = err
-
-    def on_completed(self):
-        self.has_on_completed = True
-
-
-def create_subscription(
-    stream,  # type: Subject
-    schema=email_schema,  # type: GraphQLSchema
-    ast=None,  # type: Optional[Any]
-    vars=None,  # type: Optional[Any]
-):
-    # type: (...) -> Tuple[Callable, Union[ExecutionResult, Observable]]
-    class Root(object):
-        class inbox(object):
-            emails = [
-                Email(
-                    from_="joe@graphql.org",
-                    subject="Hello",
-                    message="Hello World",
-                    unread=False,
-                )
-            ]
-
-        def importantEmail():
-            return stream
-
-    def send_important_email(new_email):
-        # type: (Email) -> None
-        Root.inbox.emails.append(new_email)
-        stream.on_next((new_email, Root.inbox))
-        # stream.on_completed()
-
-    default_ast = parse(
-        """
-    subscription {
-      importantEmail {
-        email {
-          from
-          subject
-        }
-        inbox {
-          unread
-          total
-        }
-      }
-    }
-  """
-    )
-
-    return (
-        send_important_email,
-        graphql(schema, ast or default_ast, Root, None, vars, allow_subscriptions=True),
-    )
-
-
-def test_accepts_an_object_with_named_properties_as_arguments():
-    # type: () -> None
-    document = parse(
-        """
-      subscription {
-        importantEmail
-      }
-  """
-    )
-    result = subscribe(email_schema, document, root_value=None)
-    assert isinstance(result, Observable)
-
-
-def test_accepts_multiple_subscription_fields_defined_in_schema():
-    # type: () -> None
-    SubscriptionTypeMultiple = GraphQLObjectType(
-        name="Subscription",
-        fields=OrderedDict(
-            [
-                ("importantEmail", GraphQLField(EmailEventType)),
-                ("nonImportantEmail", GraphQLField(EmailEventType)),
-            ]
-        ),
-    )
-    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionTypeMultiple)
-
-    stream = Subject()
-    send_important_email, subscription = create_subscription(stream, test_schema)
-
-    email = Email(
-        from_="yuzhi@graphql.org",
-        subject="Alright",
-        message="Tests are good",
-        unread=True,
-    )
-    l = []
-    stream.subscribe(l.append)
-    send_important_email(email)
-    assert l[0][0] == email
-
-
-def test_accepts_type_definition_with_sync_subscribe_function():
-    # type: () -> None
-    SubscriptionType = GraphQLObjectType(
-        name="Subscription",
-        fields=OrderedDict(
-            [
-                (
-                    "importantEmail",
-                    GraphQLField(
-                        EmailEventType, resolver=lambda *_: Observable.from_([None])
-                    ),
-                )
-            ]
-        ),
-    )
-    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType)
-
-    stream = Subject()
-    send_important_email, subscription = create_subscription(stream, test_schema)
-
-    email = Email(
-        from_="yuzhi@graphql.org",
-        subject="Alright",
-        message="Tests are good",
-        unread=True,
-    )
-    l = []
-    subscription.subscribe(l.append)
-    send_important_email(email)
-
-    assert l  # [0].data == {'importantEmail': None}
-
-
-def test_throws_an_error_if_subscribe_does_not_return_an_iterator():
-    # type: () -> None
-    SubscriptionType = GraphQLObjectType(
-        name="Subscription",
-        fields=OrderedDict(
-            [("importantEmail", GraphQLField(EmailEventType, resolver=lambda *_: None))]
-        ),
-    )
-    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType)
-
-    stream = Subject()
-    _, subscription = create_subscription(stream, test_schema)
-
-    assert (
-        str(subscription.errors[0])
-        == "Subscription must return Async Iterable or Observable. Received: None"
-    )
-
-
-def test_returns_an_error_if_subscribe_function_returns_error():
-    # type: () -> None
-    exc = Exception("Throw!")
-
-    def thrower(root, info):
-        # type: (Optional[Any], ResolveInfo) -> None
-        raise exc
-
-    erroring_email_schema = email_schema_with_resolvers(thrower)
-    result = subscribe(
-        erroring_email_schema,
-        parse(
-            """
-        subscription {
-          importantEmail
-        }
-    """
-        ),
-    )
-
-    assert result.errors == [exc]
-
-
-# Subscription Publish Phase
-def test_produces_a_payload_for_multiple_subscribe_in_same_subscription():
-    # type: () -> None
-    stream = Subject()
-    send_important_email, subscription1 = create_subscription(stream)
-    subscription2 = create_subscription(stream)[1]
-
-    payload1 = []
-    payload2 = []
-
-    subscription1.subscribe(payload1.append)
-    subscription2.subscribe(payload2.append)
-
-    email = Email(
-        from_="yuzhi@graphql.org",
-        subject="Alright",
-        message="Tests are good",
-        unread=True,
-    )
-
-    send_important_email(email)
-    expected_payload = {
-        "importantEmail": {
-            "email": {"from": "yuzhi@graphql.org", "subject": "Alright"},
-            "inbox": {"unread": 1, "total": 2},
-        }
-    }
-
-    assert payload1[0].data == expected_payload
-    assert payload2[0].data == expected_payload
-
-
-# Subscription Publish Phase
-def test_produces_a_payload_per_subscription_event():
-    # type: () -> None
-    stream = Subject()
-    send_important_email, subscription = create_subscription(stream)
-
-    payload = []
-
-    subscription.subscribe(payload.append)
-    send_important_email(
-        Email(
-            from_="yuzhi@graphql.org",
-            subject="Alright",
-            message="Tests are good",
-            unread=True,
-        )
-    )
-    expected_payload = {
-        "importantEmail": {
-            "email": {"from": "yuzhi@graphql.org", "subject": "Alright"},
-            "inbox": {"unread": 1, "total": 2},
-        }
-    }
-
-    assert len(payload) == 1
-    assert payload[0].data == expected_payload
-
-    send_important_email(
-        Email(
-            from_="hyo@graphql.org",
-            subject="Tools",
-            message="I <3 making things",
-            unread=True,
-        )
-    )
-    expected_payload = {
-        "importantEmail": {
-            "email": {"from": "hyo@graphql.org", "subject": "Tools"},
-            "inbox": {"unread": 2, "total": 3},
-        }
-    }
-
-    assert len(payload) == 2
-    assert payload[-1].data == expected_payload
-
-    # The client decides to disconnect
-    stream.on_completed()
-
-    send_important_email(
-        Email(
-            from_="adam@graphql.org",
-            subject="Important",
-            message="Read me please",
-            unread=True,
-        )
-    )
-
-    assert len(payload) == 2
-
-
-def test_event_order_is_correct_for_multiple_publishes():
-    # type: () -> None
-    stream = Subject()
-    send_important_email, subscription = create_subscription(stream)
-
-    payload = []
-
-    subscription.subscribe(payload.append)
-    send_important_email(
-        Email(
-            from_="yuzhi@graphql.org",
-            subject="Message",
-            message="Tests are good",
-            unread=True,
-        )
-    )
-    send_important_email(
-        Email(
-            from_="yuzhi@graphql.org",
-            subject="Message 2",
-            message="Tests are good 2",
-            unread=True,
-        )
-    )
-
-    expected_payload1 = {
-        "importantEmail": {
-            "email": {"from": "yuzhi@graphql.org", "subject": "Message"},
-            "inbox": {"unread": 1, "total": 2},
-        }
-    }
-
-    expected_payload2 = {
-        "importantEmail": {
-            "email": {"from": "yuzhi@graphql.org", "subject": "Message 2"},
-            "inbox": {"unread": 2, "total": 3},
-        }
-    }
-
-    assert len(payload) == 2
-    print(payload)
-    assert payload[0].data == expected_payload1
-    assert payload[1].data == expected_payload2
diff --git a/graphql/execution/tests/test_union_interface.py b/graphql/execution/tests/test_union_interface.py
deleted file mode 100644
index bd61ba3..0000000
--- a/graphql/execution/tests/test_union_interface.py
+++ /dev/null
@@ -1,376 +0,0 @@
-# type: ignore
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLBoolean,
-    GraphQLField,
-    GraphQLInterfaceType,
-    GraphQLList,
-    GraphQLObjectType,
-    GraphQLSchema,
-    GraphQLString,
-    GraphQLUnionType,
-)
-
-# from typing import List
-# from graphql.execution.base import ResolveInfo
-# from graphql.type.definition import GraphQLObjectType
-# from typing import Union
-
-
-class Dog(object):
-    def __init__(self, name, barks):
-        self.name = name
-        self.barks = barks
-
-
-class Cat(object):
-    def __init__(self, name, meows):
-        self.name = name
-        self.meows = meows
-
-
-class Person(object):
-    def __init__(self, name, pets, friends):
-        # type: (str, List, List[Person]) -> None
-        self.name = name
-        self.pets = pets
-        self.friends = friends
-
-
-NamedType = GraphQLInterfaceType("Named", {"name": GraphQLField(GraphQLString)})
-
-DogType = GraphQLObjectType(
-    name="Dog",
-    interfaces=[NamedType],
-    fields={"name": GraphQLField(GraphQLString), "barks": GraphQLField(GraphQLBoolean)},
-    is_type_of=lambda value, info: isinstance(value, Dog),
-)
-
-CatType = GraphQLObjectType(
-    name="Cat",
-    interfaces=[NamedType],
-    fields={"name": GraphQLField(GraphQLString), "meows": GraphQLField(GraphQLBoolean)},
-    is_type_of=lambda value, info: isinstance(value, Cat),
-)
-
-
-def resolve_pet_type(value, info):
-    # type: (Union[Cat, Dog], ResolveInfo) -> GraphQLObjectType
-    if isinstance(value, Dog):
-        return DogType
-    if isinstance(value, Cat):
-        return CatType
-
-
-PetType = GraphQLUnionType("Pet", [DogType, CatType], resolve_type=resolve_pet_type)
-
-PersonType = GraphQLObjectType(
-    name="Person",
-    interfaces=[NamedType],
-    fields={
-        "name": GraphQLField(GraphQLString),
-        "pets": GraphQLField(GraphQLList(PetType)),
-        "friends": GraphQLField(GraphQLList(NamedType)),
-    },
-    is_type_of=lambda value, info: isinstance(value, Person),
-)
-
-schema = GraphQLSchema(query=PersonType, types=[PetType])
-
-garfield = Cat("Garfield", False)
-odie = Dog("Odie", True)
-liz = Person("Liz", [], [])
-john = Person("John", [garfield, odie], [liz, odie])
-
-
-# Execute: Union and intersection types
-
-
-def test_can_introspect_on_union_and_intersection_types():
-    # type: () -> None
-    ast = parse(
-        """
-    {
-        Named: __type(name: "Named") {
-            kind
-            name
-            fields { name }
-            interfaces { name }
-            possibleTypes { name }
-            enumValues { name }
-            inputFields { name }
-        }
-        Pet: __type(name: "Pet") {
-            kind
-            name
-            fields { name }
-            interfaces { name }
-            possibleTypes { name }
-            enumValues { name }
-            inputFields { name }
-        }
-    }"""
-    )
-
-    result = execute(schema, ast)
-    assert not result.errors
-    assert result.data == {
-        "Named": {
-            "enumValues": None,
-            "name": "Named",
-            "kind": "INTERFACE",
-            "interfaces": None,
-            "fields": [{"name": "name"}],
-            "possibleTypes": [{"name": "Person"}, {"name": "Dog"}, {"name": "Cat"}],
-            "inputFields": None,
-        },
-        "Pet": {
-            "enumValues": None,
-            "name": "Pet",
-            "kind": "UNION",
-            "interfaces": None,
-            "fields": None,
-            "possibleTypes": [{"name": "Dog"}, {"name": "Cat"}],
-            "inputFields": None,
-        },
-    }
-
-
-def test_executes_using_union_types():
-    # type: () -> None
-    # NOTE: This is an *invalid* query, but it should be an *executable* query.
-    ast = parse(
-        """
-        {
-            __typename
-            name
-            pets {
-                __typename
-                name
-                barks
-                meows
-            }
-        }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "__typename": "Person",
-        "name": "John",
-        "pets": [
-            {"__typename": "Cat", "name": "Garfield", "meows": False},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-    }
-
-
-def test_executes_union_types_with_inline_fragment():
-    # type: () -> None
-    # This is the valid version of the query in the above test.
-    ast = parse(
-        """
-      {
-        __typename
-        name
-        pets {
-          __typename
-          ... on Dog {
-            name
-            barks
-          }
-          ... on Cat {
-            name
-            meows
-          }
-        }
-      }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "__typename": "Person",
-        "name": "John",
-        "pets": [
-            {"__typename": "Cat", "name": "Garfield", "meows": False},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-    }
-
-
-def test_executes_using_interface_types():
-    # type: () -> None
-    # NOTE: This is an *invalid* query, but it should be an *executable* query.
-    ast = parse(
-        """
-      {
-        __typename
-        name
-        friends {
-          __typename
-          name
-          barks
-          meows
-        }
-      }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "__typename": "Person",
-        "name": "John",
-        "friends": [
-            {"__typename": "Person", "name": "Liz"},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-    }
-
-
-def test_executes_interface_types_with_inline_fragment():
-    # type: () -> None
-    # This is the valid version of the query in the above test.
-    ast = parse(
-        """
-      {
-        __typename
-        name
-        friends {
-          __typename
-          name
-          ... on Dog {
-            barks
-          }
-          ... on Cat {
-            meows
-          }
-        }
-      }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "__typename": "Person",
-        "name": "John",
-        "friends": [
-            {"__typename": "Person", "name": "Liz"},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-    }
-
-
-def test_allows_fragment_conditions_to_be_abstract_types():
-    # type: () -> None
-    ast = parse(
-        """
-      {
-        __typename
-        name
-        pets { ...PetFields }
-        friends { ...FriendFields }
-      }
-      fragment PetFields on Pet {
-        __typename
-        ... on Dog {
-          name
-          barks
-        }
-        ... on Cat {
-          name
-          meows
-        }
-      }
-      fragment FriendFields on Named {
-        __typename
-        name
-        ... on Dog {
-          barks
-        }
-        ... on Cat {
-          meows
-        }
-      }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "__typename": "Person",
-        "name": "John",
-        "pets": [
-            {"__typename": "Cat", "name": "Garfield", "meows": False},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-        "friends": [
-            {"__typename": "Person", "name": "Liz"},
-            {"__typename": "Dog", "name": "Odie", "barks": True},
-        ],
-    }
-
-
-def test_only_include_fields_from_matching_fragment_condition():
-    # type: () -> None
-    ast = parse(
-        """
-      {
-        pets { ...PetFields }
-      }
-      fragment PetFields on Pet {
-        __typename
-        ... on Dog {
-          name
-        }
-      }
-    """
-    )
-    result = execute(schema, ast, john)
-    assert not result.errors
-    assert result.data == {
-        "pets": [{"__typename": "Cat"}, {"__typename": "Dog", "name": "Odie"}]
-    }
-
-
-def test_gets_execution_info_in_resolver():
-    # type: () -> None
-    class encountered:
-        schema = None
-        root_value = None
-        context = None
-
-    def resolve_type(obj, info):
-        # type: (Person, ResolveInfo) -> GraphQLObjectType
-        encountered.schema = info.schema
-        encountered.root_value = info.root_value
-        encountered.context = context
-        return PersonType2
-
-    NamedType2 = GraphQLInterfaceType(
-        name="Named",
-        fields={"name": GraphQLField(GraphQLString)},
-        resolve_type=resolve_type,
-    )
-
-    PersonType2 = GraphQLObjectType(
-        name="Person",
-        interfaces=[NamedType2],
-        fields={
-            "name": GraphQLField(GraphQLString),
-            "friends": GraphQLField(GraphQLList(NamedType2)),
-        },
-    )
-
-    schema2 = GraphQLSchema(query=PersonType2)
-    john2 = Person("John", [], [liz])
-    context = {"hey"}
-    ast = parse("""{ name, friends { name } }""")
-
-    result = execute(schema2, ast, john2, context_value=context)
-    assert not result.errors
-    assert result.data == {"name": "John", "friends": [{"name": "Liz"}]}
-
-    assert encountered.schema == schema2
-    assert encountered.root_value == john2
-    assert encountered.context == context
diff --git a/graphql/execution/tests/test_variables.py b/graphql/execution/tests/test_variables.py
deleted file mode 100644
index a4a1a8f..0000000
--- a/graphql/execution/tests/test_variables.py
+++ /dev/null
@@ -1,783 +0,0 @@
-# type: ignore
-import json
-from collections import OrderedDict
-
-from pytest import raises
-from graphql.error import GraphQLError, format_error
-from graphql.execution import execute
-from graphql.language.parser import parse
-from graphql.type import (
-    GraphQLArgument,
-    GraphQLField,
-    GraphQLBoolean,
-    GraphQLInputObjectField,
-    GraphQLInputObjectType,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLObjectType,
-    GraphQLScalarType,
-    GraphQLSchema,
-    GraphQLString,
-)
-
-# from typing import Any
-# from graphql.execution.base import ResolveInfo
-# from typing import Optional
-# from typing import Dict
-# from typing import Union
-
-TestComplexScalar = GraphQLScalarType(
-    name="ComplexScalar",
-    serialize=lambda v: "SerializedValue" if v == "DeserializedValue" else None,
-    parse_value=lambda v: "DeserializedValue" if v == "SerializedValue" else None,
-    parse_literal=lambda v: "DeserializedValue"
-    if v.value == "SerializedValue"
-    else None,
-)
-
-
-class my_special_dict(dict):
-    pass
-
-
-TestInputObject = GraphQLInputObjectType(
-    "TestInputObject",
-    OrderedDict(
-        [
-            ("a", GraphQLInputObjectField(GraphQLString)),
-            ("b", GraphQLInputObjectField(GraphQLList(GraphQLString))),
-            ("c", GraphQLInputObjectField(GraphQLNonNull(GraphQLString))),
-            ("d", GraphQLInputObjectField(TestComplexScalar)),
-        ]
-    ),
-)
-
-
-TestCustomInputObject = GraphQLInputObjectType(
-    "TestCustomInputObject",
-    OrderedDict([("a", GraphQLInputObjectField(GraphQLString))]),
-    container_type=my_special_dict,
-)
-
-
-def stringify(obj):
-    # type: (Any) -> str
-    return json.dumps(obj, sort_keys=True)
-
-
-def input_to_json(obj, info, **args):
-    # type: (Optional[Any], ResolveInfo, **Any) -> Optional[str]
-    input = args.get("input")
-    if input:
-        return stringify(input)
-
-
-TestNestedInputObject = GraphQLInputObjectType(
-    name="TestNestedInputObject",
-    fields={
-        "na": GraphQLInputObjectField(GraphQLNonNull(TestInputObject)),
-        "nb": GraphQLInputObjectField(GraphQLNonNull(GraphQLString)),
-    },
-)
-
-TestType = GraphQLObjectType(
-    "TestType",
-    {
-        "fieldWithObjectInput": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(TestInputObject)},
-            resolver=input_to_json,
-        ),
-        "fieldWithCustomObjectInput": GraphQLField(
-            GraphQLBoolean,
-            args={"input": GraphQLArgument(TestCustomInputObject)},
-            resolver=lambda root, info, **args: isinstance(
-                args.get("input"), my_special_dict
-            ),
-        ),
-        "fieldWithNullableStringInput": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLString)},
-            resolver=input_to_json,
-        ),
-        "fieldWithNonNullableStringInput": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLNonNull(GraphQLString))},
-            resolver=input_to_json,
-        ),
-        "fieldWithDefaultArgumentValue": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLString, "Hello World")},
-            resolver=input_to_json,
-        ),
-        "fieldWithNestedInputObject": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(TestNestedInputObject, "Hello World")},
-            resolver=input_to_json,
-        ),
-        "list": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLList(GraphQLString))},
-            resolver=input_to_json,
-        ),
-        "nnList": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLNonNull(GraphQLList(GraphQLString)))},
-            resolver=input_to_json,
-        ),
-        "listNN": GraphQLField(
-            GraphQLString,
-            args={"input": GraphQLArgument(GraphQLList(GraphQLNonNull(GraphQLString)))},
-            resolver=input_to_json,
-        ),
-        "nnListNN": GraphQLField(
-            GraphQLString,
-            args={
-                "input": GraphQLArgument(
-                    GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString)))
-                )
-            },
-            resolver=input_to_json,
-        ),
-    },
-)
-
-schema = GraphQLSchema(TestType)
-
-
-def check(
-    doc,  # type: str
-    expected,  # type: Union[Dict[str, Dict[str, None]], Dict[str, Dict[str, str]]]
-    args=None,  # type: Any
-):
-    # type: (...) -> None
-    ast = parse(doc)
-    response = execute(schema, ast, variable_values=args)
-
-    if response.errors:
-        result = {
-            "data": response.data,
-            "errors": [format_error(e) for e in response.errors],
-        }
-    else:
-        result = {"data": response.data}
-
-    assert result == expected
-
-
-# Handles objects and nullability
-
-
-def test_inline_executes_with_complex_input():
-    # type: () -> None
-    doc = """
-    {
-      fieldWithObjectInput(input: {a: "foo", b: ["bar"], c: "baz"})
-    }
-    """
-    check(
-        doc,
-        {
-            "data": {
-                "fieldWithObjectInput": stringify(
-                    {"a": "foo", "b": ["bar"], "c": "baz"}
-                )
-            }
-        },
-    )
-
-
-def test_properly_parses_single_value_to_list():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithObjectInput(input: {a: "foo", b: "bar", c: "baz"})
-    }
-    """
-    check(
-        doc,
-        {
-            "data": {
-                "fieldWithObjectInput": stringify(
-                    {"a": "foo", "b": ["bar"], "c": "baz"}
-                )
-            }
-        },
-    )
-
-
-def test_does_not_use_incorrect_value():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithObjectInput(input: ["foo", "bar", "baz"])
-    }
-    """
-    check(doc, {"data": {"fieldWithObjectInput": None}})
-
-
-def test_properly_runs_parse_literal_on_complex_scalar_types():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithObjectInput(input: {a: "foo", d: "SerializedValue"})
-    }
-    """
-    check(
-        doc,
-        {"data": {"fieldWithObjectInput": '{"a": "foo", "d": "DeserializedValue"}'}},
-    )
-
-
-# noinspection PyMethodMayBeStatic
-class TestUsingVariables:
-    doc = """
-    query q($input: TestInputObject) {
-      fieldWithObjectInput(input: $input)
-    }
-    """
-
-    def test_executes_with_complex_input(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": ["bar"], "c": "baz"}}
-        check(
-            self.doc,
-            {
-                "data": {
-                    "fieldWithObjectInput": stringify(
-                        {"a": "foo", "b": ["bar"], "c": "baz"}
-                    )
-                }
-            },
-            params,
-        )
-
-    def test_uses_default_value_when_not_provided(self):
-        # type: () -> None
-        with_defaults_doc = """
-        query q($input: TestInputObject = {a: "foo", b: ["bar"], c: "baz"}) {
-            fieldWithObjectInput(input: $input)
-        }
-        """
-
-        check(
-            with_defaults_doc,
-            {
-                "data": {
-                    "fieldWithObjectInput": stringify(
-                        {"a": "foo", "b": ["bar"], "c": "baz"}
-                    )
-                }
-            },
-        )
-
-    def test_properly_parses_single_value_to_list(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": "bar", "c": "baz"}}
-        check(
-            self.doc,
-            {
-                "data": {
-                    "fieldWithObjectInput": stringify(
-                        {"a": "foo", "b": ["bar"], "c": "baz"}
-                    )
-                }
-            },
-            params,
-        )
-
-    def test_executes_with_complex_scalar_input(self):
-        # type: () -> None
-        params = {"input": {"c": "foo", "d": "SerializedValue"}}
-        check(
-            self.doc,
-            {
-                "data": {
-                    "fieldWithObjectInput": stringify(
-                        {"c": "foo", "d": "DeserializedValue"}
-                    )
-                }
-            },
-            params,
-        )
-
-    def test_errors_on_null_for_nested_non_null(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": "bar", "c": None}}
-
-        with raises(GraphQLError) as excinfo:
-            check(self.doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 13, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'In field "c": Expected "String!", found null.'.format(
-                stringify(params["input"])
-            ),
-        }
-
-    def test_errors_on_incorrect_type(self):
-        # type: () -> None
-        params = {"input": "foo bar"}
-
-        with raises(GraphQLError) as excinfo:
-            check(self.doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 13, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'Expected "TestInputObject", found not an object.'.format(
-                stringify(params["input"])
-            ),
-        }
-
-    def test_errors_on_omission_of_nested_non_null(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": "bar"}}
-
-        with raises(GraphQLError) as excinfo:
-            check(self.doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 13, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'In field "c": Expected "String!", found null.'.format(
-                stringify(params["input"])
-            ),
-        }
-
-    def test_errors_on_deep_nested_errors_and_with_many_errors(self):
-        # type: () -> None
-        nested_doc = """
-          query q($input: TestNestedInputObject) {
-            fieldWithNestedObjectInput(input: $input)
-          }
-        """
-
-        params = {"input": {"na": {"a": "foo"}}}
-        with raises(GraphQLError) as excinfo:
-            check(nested_doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 19, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'In field "na": In field "c": Expected "String!", found null.\n'
-            'In field "nb": Expected "String!", found null.'.format(
-                stringify(params["input"])
-            ),
-        }
-
-    def test_errors_on_addition_of_input_field_of_incorrect_type(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": "bar", "c": "baz", "d": "dog"}}
-
-        with raises(GraphQLError) as excinfo:
-            check(self.doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 13, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'In field "d": Expected type "ComplexScalar", found "dog".'.format(
-                stringify(params["input"])
-            ),
-        }
-
-    def test_errors_on_addition_of_unknown_input_field(self):
-        # type: () -> None
-        params = {"input": {"a": "foo", "b": "bar", "c": "baz", "extra": "dog"}}
-
-        with raises(GraphQLError) as excinfo:
-            check(self.doc, {}, params)
-
-        assert format_error(excinfo.value) == {
-            "locations": [{"column": 13, "line": 2}],
-            "message": 'Variable "$input" got invalid value {}.\n'
-            'In field "extra": Unknown field.'.format(stringify(params["input"])),
-        }
-
-
-def test_allows_nullable_inputs_to_be_omitted():
-    # type: () -> None
-    doc = "{ fieldWithNullableStringInput }"
-    check(doc, {"data": {"fieldWithNullableStringInput": None}})
-
-
-def test_allows_nullable_inputs_to_be_omitted_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNullable($value: String) {
-        fieldWithNullableStringInput(input: $value)
-    }
-    """
-
-    check(doc, {"data": {"fieldWithNullableStringInput": None}})
-
-
-def test_allows_nullable_inputs_to_be_omitted_in_an_unlisted_variable():
-    # type: () -> None
-    doc = """
-    query SetsNullable {
-        fieldWithNullableStringInput(input: $value)
-    }
-    """
-
-    check(doc, {"data": {"fieldWithNullableStringInput": None}})
-
-
-def test_allows_nullable_inputs_to_be_set_to_null_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNullable($value: String) {
-        fieldWithNullableStringInput(input: $value)
-    }
-    """
-    check(doc, {"data": {"fieldWithNullableStringInput": None}}, {"value": None})
-
-
-def test_allows_nullable_inputs_to_be_set_to_a_value_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNullable($value: String) {
-        fieldWithNullableStringInput(input: $value)
-    }
-    """
-
-    check(doc, {"data": {"fieldWithNullableStringInput": '"a"'}}, {"value": "a"})
-
-
-def test_allows_nullable_inputs_to_be_set_to_a_value_directly():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithNullableStringInput(input: "a")
-    }
-    """
-    check(doc, {"data": {"fieldWithNullableStringInput": '"a"'}})
-
-
-def test_does_not_allow_non_nullable_inputs_to_be_omitted_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNonNullable($value: String!) {
-        fieldWithNonNullableStringInput(input: $value)
-    }
-    """
-    with raises(GraphQLError) as excinfo:
-        check(doc, {})
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 27, "line": 2}],
-        "message": 'Variable "$value" of required type "String!" was not provided.',
-    }
-
-
-def test_does_not_allow_non_nullable_inputs_to_be_set_to_null_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNonNullable($value: String!) {
-        fieldWithNonNullableStringInput(input: $value)
-    }
-    """
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, {"value": None})
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 27, "line": 2}],
-        "message": 'Variable "$value" of required type "String!" was not provided.',
-    }
-
-
-def test_allows_non_nullable_inputs_to_be_set_to_a_value_in_a_variable():
-    # type: () -> None
-    doc = """
-    query SetsNonNullable($value: String!) {
-        fieldWithNonNullableStringInput(input: $value)
-    }
-    """
-
-    check(doc, {"data": {"fieldWithNonNullableStringInput": '"a"'}}, {"value": "a"})
-
-
-def test_allows_non_nullable_inputs_to_be_set_to_a_value_directly():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithNonNullableStringInput(input: "a")
-    }
-    """
-
-    check(doc, {"data": {"fieldWithNonNullableStringInput": '"a"'}})
-
-
-def test_passes_along_null_for_non_nullable_inputs_if_explcitly_set_in_the_query():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithNonNullableStringInput
-    }
-    """
-
-    check(
-        doc,
-        {
-            "errors": [
-                {
-                    "message": 'Argument "input" of required type String!" was not provided.'
-                }
-            ],
-            "data": None,
-        },
-    )
-
-
-def test_uses_objectinput_container():
-    # type: () -> None
-    doc = """
-    {
-        fieldWithCustomObjectInput(input: {a: "b"})
-    }
-    """
-
-    check(doc, {"data": {"fieldWithCustomObjectInput": True}})
-
-
-def test_allows_lists_to_be_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String]) {
-        list(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"list": None}})
-
-
-def test_allows_lists_to_contain_values():
-    # type: () -> None
-    doc = """
-    query q($input: [String]) {
-        list(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"list": stringify(["A"])}}, {"input": ["A"]})
-
-
-def test_allows_lists_to_contain_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String]) {
-        list(input: $input)
-    }
-    """
-
-    check(
-        doc,
-        {"data": {"list": stringify(["A", None, "B"])}},
-        {"input": ["A", None, "B"]},
-    )
-
-
-def test_does_not_allow_non_null_lists_to_be_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String]!) {
-        nnList(input: $input)
-    }
-    """
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, {"input": None})
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" of required type "[String]!" was not provided.',
-    }
-
-
-def test_allows_non_null_lists_to_contain_values():
-    # type: () -> None
-    doc = """
-    query q($input: [String]!) {
-        nnList(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"nnList": stringify(["A"])}}, {"input": ["A"]})
-
-
-def test_allows_non_null_lists_to_contain_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String]!) {
-        nnList(input: $input)
-    }
-    """
-
-    check(
-        doc,
-        {"data": {"nnList": stringify(["A", None, "B"])}},
-        {"input": ["A", None, "B"]},
-    )
-
-
-def test_allows_lists_of_non_nulls_to_be_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]) {
-        listNN(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"listNN": None}}, {"input": None})
-
-
-def test_allows_lists_of_non_nulls_to_contain_values():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]) {
-        listNN(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"listNN": stringify(["A"])}}, {"input": ["A"]})
-
-
-def test_does_not_allow_lists_of_non_nulls_to_contain_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]) {
-        listNN(input: $input)
-    }
-    """
-
-    params = {"input": ["A", None, "B"]}
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, params)
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" got invalid value {}.\n'
-        'In element #1: Expected "String!", found null.'.format(
-            stringify(params["input"])
-        ),
-    }
-
-
-def test_does_not_allow_non_null_lists_of_non_nulls_to_be_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]!) {
-        nnListNN(input: $input)
-    }
-    """
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, {"input": None})
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" of required type "[String!]!" was not provided.',
-    }
-
-
-def test_allows_non_null_lists_of_non_nulls_to_contain_values():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]!) {
-        nnListNN(input: $input)
-    }
-    """
-
-    check(doc, {"data": {"nnListNN": stringify(["A"])}}, {"input": ["A"]})
-
-
-def test_does_not_allow_non_null_lists_of_non_nulls_to_contain_null():
-    # type: () -> None
-    doc = """
-    query q($input: [String!]!) {
-        nnListNN(input: $input)
-    }
-    """
-
-    params = {"input": ["A", None, "B"]}
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, params)
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" got invalid value {}.\n'
-        'In element #1: Expected "String!", found null.'.format(
-            stringify(params["input"])
-        ),
-    }
-
-
-def test_does_not_allow_invalid_types_to_be_used_as_values():
-    # type: () -> None
-    doc = """
-    query q($input: TestType!) {
-        fieldWithObjectInput(input: $input)
-    }
-    """
-    params = {"input": {"list": ["A", "B"]}}
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, params)
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" expected value of type "TestType!" which cannot be used as an input type.',
-    }
-
-
-def test_does_not_allow_unknown_types_to_be_used_as_values():
-    # type: () -> None
-    doc = """
-    query q($input: UnknownType!) {
-        fieldWithObjectInput(input: $input)
-    }
-    """
-    params = {"input": "whoknows"}
-
-    with raises(GraphQLError) as excinfo:
-        check(doc, {}, params)
-
-    assert format_error(excinfo.value) == {
-        "locations": [{"column": 13, "line": 2}],
-        "message": 'Variable "$input" expected value of type "UnknownType!" which cannot be used as an input type.',
-    }
-
-
-# noinspection PyMethodMayBeStatic
-class TestUsesArgumentDefaultValues:
-    def test_when_no_argument_provided(self):
-        # type: () -> None
-        check(
-            "{ fieldWithDefaultArgumentValue }",
-            {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}},
-        )
-
-    def test_when_nullable_variable_provided(self):
-        # type: () -> None
-        check(
-            """
-        query optionalVariable($optional: String) {
-            fieldWithDefaultArgumentValue(input: $optional)
-        }
-        """,
-            {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}},
-        )
-
-    def test_when_argument_provided_cannot_be_parsed(self):
-        # type: () -> None
-        check(
-            """
-        {
-            fieldWithDefaultArgumentValue(input: WRONG_TYPE)
-        }
-        """,
-            {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}},
-        )
diff --git a/graphql/execution/tests/utils.py b/graphql/execution/tests/utils.py
deleted file mode 100644
index afb44fa..0000000
--- a/graphql/execution/tests/utils.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from promise import Promise
-from typing import Any
-
-
-def resolved(value):
-    # type: (Any) -> Promise
-    return Promise.fulfilled(value)
-
-
-def rejected(error):
-    # type: (Exception) -> Promise
-    return Promise.rejected(error)
diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py
deleted file mode 100644
index e1aab18..0000000
--- a/graphql/execution/utils.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# -*- coding: utf-8 -*-
-import logging
-from traceback import format_exception
-
-from ..error import GraphQLError
-from ..language import ast
-from ..pyutils.default_ordered_dict import DefaultOrderedDict
-from ..type.definition import GraphQLInterfaceType, GraphQLUnionType
-from ..type.directives import GraphQLIncludeDirective, GraphQLSkipDirective
-from ..type.introspection import (
-    SchemaMetaFieldDef,
-    TypeMetaFieldDef,
-    TypeNameMetaFieldDef,
-)
-from ..utils.type_from_ast import type_from_ast
-from .values import get_argument_values, get_variable_values
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..type.definition import GraphQLObjectType, GraphQLField
-    from ..type.schema import GraphQLSchema
-    from ..language.ast import (
-        Document,
-        OperationDefinition,
-        SelectionSet,
-        Directive,
-        FragmentDefinition,
-        InlineFragment,
-        Field,
-    )
-    from .base import ResolveInfo
-    from types import TracebackType
-    from typing import Any, List, Dict, Optional, Union, Callable, Set, Tuple
-
-logger = logging.getLogger(__name__)
-
-
-class ExecutionContext(object):
-    """Data that must be available at all points during query execution.
-
-    Namely, schema of the type system that is currently executing,
-    and the fragments defined in the query document"""
-
-    __slots__ = (
-        "schema",
-        "fragments",
-        "root_value",
-        "operation",
-        "variable_values",
-        "errors",
-        "context_value",
-        "argument_values_cache",
-        "executor",
-        "middleware",
-        "allow_subscriptions",
-        "_subfields_cache",
-    )
-
-    def __init__(
-        self,
-        schema,  # type: GraphQLSchema
-        document_ast,  # type: Document
-        root_value,  # type: Any
-        context_value,  # type: Any
-        variable_values,  # type: Optional[Dict[str, Any]]
-        operation_name,  # type: Optional[str]
-        executor,  # type: Any
-        middleware,  # type: Optional[Any]
-        allow_subscriptions,  # type: bool
-    ):
-        # type: (...) -> None
-        """Constructs a ExecutionContext object from the arguments passed
-        to execute, which we will pass throughout the other execution
-        methods."""
-        errors = []  # type: List[Exception]
-        operation = None
-        fragments = {}  # type: Dict[str, FragmentDefinition]
-
-        for definition in document_ast.definitions:
-            if isinstance(definition, ast.OperationDefinition):
-                if not operation_name and operation:
-                    raise GraphQLError(
-                        "Must provide operation name if query contains multiple operations."
-                    )
-
-                if (
-                    not operation_name
-                    or definition.name
-                    and definition.name.value == operation_name
-                ):
-                    operation = definition
-
-            elif isinstance(definition, ast.FragmentDefinition):
-                fragments[definition.name.value] = definition
-
-            else:
-                raise GraphQLError(
-                    u"GraphQL cannot execute a request containing a {}.".format(
-                        definition.__class__.__name__
-                    ),
-                    definition,
-                )
-
-        if not operation:
-            if operation_name:
-                raise GraphQLError(
-                    u'Unknown operation named "{}".'.format(operation_name)
-                )
-
-            else:
-                raise GraphQLError("Must provide an operation.")
-
-        variable_values = get_variable_values(
-            schema, operation.variable_definitions or [], variable_values
-        )
-
-        self.schema = schema
-        self.fragments = fragments
-        self.root_value = root_value
-        self.operation = operation
-        self.variable_values = variable_values
-        self.errors = errors
-        self.context_value = context_value
-        self.argument_values_cache = (
-            {}
-        )  # type: Dict[Tuple[GraphQLField, Field], Dict[str, Any]]
-        self.executor = executor
-        self.middleware = middleware
-        self.allow_subscriptions = allow_subscriptions
-        self._subfields_cache = (
-            {}
-        )  # type: Dict[Tuple[GraphQLObjectType, Tuple[Field, ...]], DefaultOrderedDict]
-
-    def get_field_resolver(self, field_resolver):
-        # type: (Callable) -> Callable
-        if not self.middleware:
-            return field_resolver
-        return self.middleware.get_field_resolver(field_resolver)
-
-    def get_argument_values(self, field_def, field_ast):
-        # type: (GraphQLField, Field) -> Dict[str, Any]
-        k = field_def, field_ast
-        if k not in self.argument_values_cache:
-            self.argument_values_cache[k] = get_argument_values(
-                field_def.args, field_ast.arguments, self.variable_values
-            )
-
-        return self.argument_values_cache[k]
-
-    def report_error(self, error, traceback=None):
-        # type: (Exception, Optional[TracebackType]) -> None
-        exception = format_exception(
-            type(error), error, getattr(error, "stack", None) or traceback
-        )
-        logger.error("".join(exception))
-        self.errors.append(error)
-
-    def get_sub_fields(self, return_type, field_asts):
-        # type: (GraphQLObjectType, List[Field]) -> DefaultOrderedDict
-        k = return_type, tuple(field_asts)
-        if k not in self._subfields_cache:
-            subfield_asts = DefaultOrderedDict(list)
-            visited_fragment_names = set()  # type: Set[str]
-            for field_ast in field_asts:
-                selection_set = field_ast.selection_set
-                if selection_set:
-                    subfield_asts = collect_fields(
-                        self,
-                        return_type,
-                        selection_set,
-                        subfield_asts,
-                        visited_fragment_names,
-                    )
-            self._subfields_cache[k] = subfield_asts
-        return self._subfields_cache[k]
-
-
-class SubscriberExecutionContext(object):
-    __slots__ = "exe_context", "errors"
-
-    def __init__(self, exe_context):
-        # type: (ExecutionContext) -> None
-        self.exe_context = exe_context
-        self.errors = []  # type: List[Exception]
-
-    def reset(self):
-        # type: () -> None
-        self.errors = []
-
-    def __getattr__(self, name):
-        # type: (str) -> Any
-        return getattr(self.exe_context, name)
-
-
-def get_operation_root_type(schema, operation):
-    # type: (GraphQLSchema, OperationDefinition) -> GraphQLObjectType
-    op = operation.operation
-    if op == "query":
-        return schema.get_query_type()
-
-    elif op == "mutation":
-        mutation_type = schema.get_mutation_type()
-
-        if not mutation_type:
-            raise GraphQLError("Schema is not configured for mutations", [operation])
-
-        return mutation_type
-
-    elif op == "subscription":
-        subscription_type = schema.get_subscription_type()
-
-        if not subscription_type:
-            raise GraphQLError(
-                "Schema is not configured for subscriptions", [operation]
-            )
-
-        return subscription_type
-
-    raise GraphQLError(
-        "Can only execute queries, mutations and subscriptions", [operation]
-    )
-
-
-def collect_fields(
-    ctx,  # type: ExecutionContext
-    runtime_type,  # type: GraphQLObjectType
-    selection_set,  # type: SelectionSet
-    fields,  # type: DefaultOrderedDict
-    prev_fragment_names,  # type: Set[str]
-):
-    # type: (...) -> DefaultOrderedDict
-    """
-    Given a selectionSet, adds all of the fields in that selection to
-    the passed in map of fields, and returns it at the end.
-
-    collect_fields requires the "runtime type" of an object. For a field which
-    returns and Interface or Union type, the "runtime type" will be the actual
-    Object type returned by that field.
-    """
-    for selection in selection_set.selections:
-        directives = selection.directives
-
-        if isinstance(selection, ast.Field):
-            if not should_include_node(ctx, directives):
-                continue
-
-            name = get_field_entry_key(selection)
-            fields[name].append(selection)
-
-        elif isinstance(selection, ast.InlineFragment):
-            if not should_include_node(
-                ctx, directives
-            ) or not does_fragment_condition_match(ctx, selection, runtime_type):
-                continue
-
-            collect_fields(
-                ctx, runtime_type, selection.selection_set, fields, prev_fragment_names
-            )
-
-        elif isinstance(selection, ast.FragmentSpread):
-            frag_name = selection.name.value
-
-            if frag_name in prev_fragment_names or not should_include_node(
-                ctx, directives
-            ):
-                continue
-
-            prev_fragment_names.add(frag_name)
-            fragment = ctx.fragments[frag_name]
-            frag_directives = fragment.directives
-            if (
-                not fragment
-                or not should_include_node(ctx, frag_directives)
-                or not does_fragment_condition_match(ctx, fragment, runtime_type)
-            ):
-                continue
-
-            collect_fields(
-                ctx, runtime_type, fragment.selection_set, fields, prev_fragment_names
-            )
-
-    return fields
-
-
-def should_include_node(ctx, directives):
-    # type: (ExecutionContext, Optional[List[Directive]]) -> bool
-    """Determines if a field should be included based on the @include and
-    @skip directives, where @skip has higher precidence than @include."""
-    # TODO: Refactor based on latest code
-    if directives:
-        skip_ast = None
-
-        for directive in directives:
-            if directive.name.value == GraphQLSkipDirective.name:
-                skip_ast = directive
-                break
-
-        if skip_ast:
-            args = get_argument_values(
-                GraphQLSkipDirective.args, skip_ast.arguments, ctx.variable_values
-            )
-            if args.get("if") is True:
-                return False
-
-        include_ast = None
-
-        for directive in directives:
-            if directive.name.value == GraphQLIncludeDirective.name:
-                include_ast = directive
-                break
-
-        if include_ast:
-            args = get_argument_values(
-                GraphQLIncludeDirective.args, include_ast.arguments, ctx.variable_values
-            )
-
-            if args.get("if") is False:
-                return False
-
-    return True
-
-
-def does_fragment_condition_match(
-    ctx,  # type: ExecutionContext
-    fragment,  # type: Union[FragmentDefinition, InlineFragment]
-    type_,  # type: GraphQLObjectType
-):
-    # type: (...) -> bool
-    type_condition_ast = fragment.type_condition
-    if not type_condition_ast:
-        return True
-
-    conditional_type = type_from_ast(ctx.schema, type_condition_ast)
-    if conditional_type.is_same_type(type_):
-        return True
-
-    if isinstance(conditional_type, (GraphQLInterfaceType, GraphQLUnionType)):
-        return ctx.schema.is_possible_type(conditional_type, type_)
-
-    return False
-
-
-def get_field_entry_key(node):
-    # type: (Field) -> str
-    """Implements the logic to compute the key of a given field's entry"""
-    if node.alias:
-        return node.alias.value
-    return node.name.value
-
-
-def default_resolve_fn(source, info, **args):
-    # type: (Any, ResolveInfo, **Any) -> Optional[Any]
-    """If a resolve function is not given, then a default resolve behavior is used which takes the property of the source object
-    of the same name as the field and returns it as the result, or if it's a function, returns the result of calling that function."""
-    name = info.field_name
-    if isinstance(source, dict):
-        property = source.get(name)
-    else:
-        property = getattr(source, name, None)
-    if callable(property):
-        return property()
-    return property
-
-
-def get_field_def(
-    schema,  # type: GraphQLSchema
-    parent_type,  # type: GraphQLObjectType
-    field_name,  # type: str
-):
-    # type: (...) -> Optional[GraphQLField]
-    """This method looks up the field on the given type defintion.
-    It has special casing for the two introspection fields, __schema
-    and __typename. __typename is special because it can always be
-    queried as a field, even in situations where no other fields
-    are allowed, like on a Union. __schema could get automatically
-    added to the query type, but that would require mutating type
-    definitions, which would cause issues."""
-    if field_name == "__schema" and schema.get_query_type() == parent_type:
-        return SchemaMetaFieldDef
-    elif field_name == "__type" and schema.get_query_type() == parent_type:
-        return TypeMetaFieldDef
-    elif field_name == "__typename":
-        return TypeNameMetaFieldDef
-    return parent_type.fields.get(field_name)
diff --git a/graphql/execution/values.py b/graphql/execution/values.py
deleted file mode 100644
index b4304cb..0000000
--- a/graphql/execution/values.py
+++ /dev/null
@@ -1,186 +0,0 @@
-try:
-    from collections.abc import Iterable
-except ImportError:  # Python <3.3
-    from collections import Iterable
-import json
-
-from six import string_types
-
-from ..error import GraphQLError
-from ..language import ast
-from ..language.printer import print_ast
-from ..type import (
-    GraphQLEnumType,
-    GraphQLInputObjectType,
-    GraphQLList,
-    GraphQLNonNull,
-    GraphQLScalarType,
-    is_input_type,
-)
-from ..utils.is_valid_value import is_valid_value
-from ..utils.type_from_ast import type_from_ast
-from ..utils.value_from_ast import value_from_ast
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from ..language.ast import VariableDefinition, Argument
-    from ..type.schema import GraphQLSchema
-    from ..type.definition import GraphQLArgument
-    from typing import Any, List, Union, Dict, Optional
-
-__all__ = ["get_variable_values", "get_argument_values"]
-
-
-def get_variable_values(
-    schema,  # type: GraphQLSchema
-    definition_asts,  # type: List[VariableDefinition]
-    inputs,  # type: Any
-):
-    # type: (...) -> Dict[str, Any]
-    """Prepares an object map of variables of the correct type based on the provided variable definitions and arbitrary input.
-    If the input cannot be parsed to match the variable definitions, a GraphQLError will be thrown."""
-    if inputs is None:
-        inputs = {}
-
-    values = {}
-    for def_ast in definition_asts:
-        var_name = def_ast.variable.name.value
-        var_type = type_from_ast(schema, def_ast.type)
-        value = inputs.get(var_name)
-
-        if not is_input_type(var_type):
-            raise GraphQLError(
-                'Variable "${var_name}" expected value of type "{var_type}" which cannot be used as an input type.'.format(
-                    var_name=var_name, var_type=print_ast(def_ast.type)
-                ),
-                [def_ast],
-            )
-        elif value is None:
-            if def_ast.default_value is not None:
-                values[var_name] = value_from_ast(
-                    def_ast.default_value, var_type
-                )  # type: ignore
-            if isinstance(var_type, GraphQLNonNull):
-                raise GraphQLError(
-                    'Variable "${var_name}" of required type "{var_type}" was not provided.'.format(
-                        var_name=var_name, var_type=var_type
-                    ),
-                    [def_ast],
-                )
-        else:
-            errors = is_valid_value(value, var_type)
-            if errors:
-                message = u"\n" + u"\n".join(errors)
-                raise GraphQLError(
-                    'Variable "${}" got invalid value {}.{}'.format(
-                        var_name, json.dumps(value, sort_keys=True), message
-                    ),
-                    [def_ast],
-                )
-            coerced_value = coerce_value(var_type, value)
-            if coerced_value is None:
-                raise Exception("Should have reported error.")
-
-            values[var_name] = coerced_value
-
-    return values
-
-
-def get_argument_values(
-    arg_defs,  # type: Union[Dict[str, GraphQLArgument], Dict]
-    arg_asts,  # type: Optional[List[Argument]]
-    variables=None,  # type: Optional[Dict[str, Union[List, Dict, int, float, bool, str, None]]]
-):
-    # type: (...) -> Dict[str, Any]
-    """Prepares an object map of argument values given a list of argument
-    definitions and list of argument AST nodes."""
-    if not arg_defs:
-        return {}
-
-    if arg_asts:
-        arg_ast_map = {
-            arg.name.value: arg for arg in arg_asts
-        }  # type: Dict[str, Argument]
-    else:
-        arg_ast_map = {}
-
-    result = {}
-    for name, arg_def in arg_defs.items():
-        arg_type = arg_def.type
-        arg_ast = arg_ast_map.get(name)
-        if name not in arg_ast_map:
-            if arg_def.default_value is not None:
-                result[arg_def.out_name or name] = arg_def.default_value
-                continue
-            elif isinstance(arg_type, GraphQLNonNull):
-                raise GraphQLError(
-                    'Argument "{name}" of required type {arg_type}" was not provided.'.format(
-                        name=name, arg_type=arg_type
-                    ),
-                    arg_asts,
-                )
-        elif isinstance(arg_ast.value, ast.Variable):  # type: ignore
-            variable_name = arg_ast.value.name.value  # type: ignore
-            if variables and variable_name in variables:
-                result[arg_def.out_name or name] = variables[variable_name]
-            elif arg_def.default_value is not None:
-                result[arg_def.out_name or name] = arg_def.default_value
-            elif isinstance(arg_type, GraphQLNonNull):
-                raise GraphQLError(
-                    'Argument "{name}" of required type {arg_type}" provided the variable "${variable_name}" which was not provided'.format(
-                        name=name, arg_type=arg_type, variable_name=variable_name
-                    ),
-                    arg_asts,
-                )
-            continue
-
-        else:
-            value = value_from_ast(arg_ast.value, arg_type, variables)  # type: ignore
-            if value is None:
-                if arg_def.default_value is not None:
-                    value = arg_def.default_value
-                    result[arg_def.out_name or name] = value
-            else:
-                # We use out_name as the output name for the
-                # dict if exists
-                result[arg_def.out_name or name] = value
-
-    return result
-
-
-def coerce_value(type, value):
-    # type: (Any, Any) -> Union[List, Dict, int, float, bool, str, None]
-    """Given a type and any value, return a runtime value coerced to match the type."""
-    if isinstance(type, GraphQLNonNull):
-        # Note: we're not checking that the result of coerceValue is
-        # non-null.
-        # We only call this function after calling isValidValue.
-        return coerce_value(type.of_type, value)
-
-    if value is None:
-        return None
-
-    if isinstance(type, GraphQLList):
-        item_type = type.of_type
-        if not isinstance(value, string_types) and isinstance(value, Iterable):
-            return [coerce_value(item_type, item) for item in value]
-        else:
-            return [coerce_value(item_type, value)]
-
-    if isinstance(type, GraphQLInputObjectType):
-        fields = type.fields
-        obj = {}
-        for field_name, field in fields.items():
-            if field_name not in value:
-                if field.default_value is not None:
-                    field_value = field.default_value
-                    obj[field.out_name or field_name] = field_value
-            else:
-                field_value = coerce_value(field.type, value.get(field_name))
-                obj[field.out_name or field_name] = field_value
-
-        return type.create_container(obj)
-
-    assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type"
-
-    return type.parse_value(value)
diff --git a/graphql/flags.py b/graphql/flags.py
deleted file mode 100644
index e3f3e62..0000000
--- a/graphql/flags.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# This file makes it easier to know what are the features
-# the GraphQL-core API supports
-
-# This permits to plug different backend when executing graphql(...)
-BACKEND_EXECUTOR = True
-
-# This add a new path attribute to ResolveInfo, filled with the
-# path of the field where is being executed
-PATH_IN_RESOLVEINFO = True
diff --git a/graphql/graphql.py b/graphql/graphql.py
deleted file mode 100644
index 89ccf38..0000000
--- a/graphql/graphql.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from .execution import ExecutionResult
-from .backend import get_default_backend
-
-from promise import promisify
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from promise import Promise
-    from rx import Observable
-    from typing import Any, Union, Optional
-    from .language.ast import Document
-    from .type.schema import GraphQLSchema
-
-# This is the primary entry point function for fulfilling GraphQL operations
-# by parsing, validating, and executing a GraphQL document along side a
-# GraphQL schema.
-
-# More sophisticated GraphQL servers, such as those which persist queries,
-# may wish to separate the validation and execution phases to a static time
-# tooling step, and a server runtime step.
-
-# schema:
-#    The GraphQL type system to use when validating and executing a query.
-# requestString:
-#    A GraphQL language formatted string representing the requested operation.
-# rootValue:
-#    The value provided as the first argument to resolver functions on the top
-#    level type (e.g. the query object type).
-# variableValues:
-#    A mapping of variable name to runtime value to use for all variables
-#    defined in the requestString.
-# operationName:
-#    The name of the operation to use if requestString contains multiple
-#    possible operations. Can be omitted if requestString contains only
-#    one operation.
-
-
-def graphql(*args, **kwargs):
-    # type: (*Any, **Any) -> Union[ExecutionResult, Observable, Promise[ExecutionResult]]
-    return_promise = kwargs.get("return_promise", False)
-    if return_promise:
-        return execute_graphql_as_promise(*args, **kwargs)
-    else:
-        return execute_graphql(*args, **kwargs)
-
-
-def execute_graphql(
-    schema,  # type: GraphQLSchema
-    request_string="",  # type: Union[Document, str]
-    root=None,  # type: Any
-    context=None,  # type: Optional[Any]
-    variables=None,  # type: Optional[Any]
-    operation_name=None,  # type: Optional[Any]
-    middleware=None,  # type: Optional[Any]
-    backend=None,  # type: Optional[Any]
-    **execute_options  # type: Any
-):
-    # type: (...) -> Union[ExecutionResult, Observable, Promise[ExecutionResult]]
-    try:
-        if backend is None:
-            backend = get_default_backend()
-
-        document = backend.document_from_string(schema, request_string)
-        return document.execute(
-            root=root,
-            context=context,
-            operation_name=operation_name,
-            variables=variables,
-            middleware=middleware,
-            **execute_options
-        )
-    except Exception as e:
-        return ExecutionResult(errors=[e], invalid=True)
-
-
-@promisify
-def execute_graphql_as_promise(*args, **kwargs):
-    return execute_graphql(*args, **kwargs)
diff --git a/graphql/language/__init__.py b/graphql/language/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/language/ast.py b/graphql/language/ast.py
deleted file mode 100644
index 0c40d44..0000000
--- a/graphql/language/ast.py
+++ /dev/null
@@ -1,1499 +0,0 @@
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from .parser import Loc
-    from typing import Any, Optional, Union, List, Iterable
-
-# This is autogenerated code. DO NOT change this manually.
-# Run scripts/generate_ast.py to generate this file.
-
-
-class Node(object):
-    __slots__ = ()
-    _fields = ()  # type: Iterable[str]
-    loc = None  # type: Optional[Loc]
-
-
-class Definition(Node):
-    __slots__ = ()
-
-
-class Document(Node):
-    __slots__ = ("loc", "definitions")
-    _fields = ("definitions",)
-
-    def __init__(self, definitions, loc=None):
-        # type: (Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.definitions = definitions
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Document)
-            and
-            # self.loc == other.loc and
-            self.definitions == other.definitions
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("Document(" "definitions={self.definitions!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> Document
-        return type(self)(self.definitions, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class OperationDefinition(Definition):
-    __slots__ = (
-        "loc",
-        "operation",
-        "name",
-        "variable_definitions",
-        "directives",
-        "selection_set",
-    )
-    _fields = (
-        "operation",
-        "name",
-        "variable_definitions",
-        "directives",
-        "selection_set",
-    )
-
-    def __init__(
-        self,
-        operation,  # type: str
-        selection_set,  # type: SelectionSet
-        name=None,  # type: Optional[Name]
-        #
-        variable_definitions=None,  # type: Optional[List[VariableDefinition]]
-        directives=None,  # type: Optional[List[Directive]]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.operation = operation
-        self.name = name
-        self.variable_definitions = variable_definitions
-        self.directives = directives
-        self.selection_set = selection_set
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, OperationDefinition)
-            and
-            # self.loc == other.loc and
-            self.operation == other.operation
-            and self.name == other.name
-            and self.variable_definitions == other.variable_definitions
-            and self.directives == other.directives
-            and self.selection_set == other.selection_set
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "OperationDefinition("
-            "operation={self.operation!r}"
-            ", name={self.name!r}"
-            ", variable_definitions={self.variable_definitions!r}"
-            ", directives={self.directives!r}"
-            ", selection_set={self.selection_set!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> OperationDefinition
-        return type(self)(
-            self.operation,
-            self.selection_set,
-            self.name,
-            self.variable_definitions,
-            self.directives,
-            self.loc,
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class VariableDefinition(Node):
-    __slots__ = ("loc", "variable", "type", "default_value")
-    _fields = ("variable", "type", "default_value")
-
-    def __init__(self, variable, type, default_value=None, loc=None):
-        # type: (Variable, Any, Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.variable = variable
-        self.type = type
-        self.default_value = default_value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, VariableDefinition)
-            and
-            # self.loc == other.loc and
-            self.variable == other.variable
-            and self.type == other.type
-            and self.default_value == other.default_value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "VariableDefinition("
-            "variable={self.variable!r}"
-            ", type={self.type!r}"
-            ", default_value={self.default_value!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> VariableDefinition
-        return type(self)(self.variable, self.type, self.default_value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class SelectionSet(Node):
-    __slots__ = ("loc", "selections")
-    _fields = ("selections",)
-
-    def __init__(self, selections, loc=None):
-        # type: (Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.selections = selections
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, SelectionSet)
-            and
-            # self.loc == other.loc and
-            self.selections == other.selections
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("SelectionSet(" "selections={self.selections!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> SelectionSet
-        return type(self)(self.selections, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Selection(Node):
-    __slots__ = ()
-
-
-class Field(Selection):
-    __slots__ = ("loc", "alias", "name", "arguments", "directives", "selection_set")
-    _fields = ("alias", "name", "arguments", "directives", "selection_set")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        alias=None,  # type: Optional[Name]
-        arguments=None,  # type: Optional[List[Argument]]
-        directives=None,  # type: Optional[List[Directive]]
-        selection_set=None,  # type: Optional[SelectionSet]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.alias = alias
-        self.name = name
-        self.arguments = arguments
-        self.directives = directives
-        self.selection_set = selection_set
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Field)
-            and
-            # self.loc == other.loc and
-            self.alias == other.alias
-            and self.name == other.name
-            and self.arguments == other.arguments
-            and self.directives == other.directives
-            and self.selection_set == other.selection_set
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "Field("
-            "alias={self.alias!r}"
-            ", name={self.name!r}"
-            ", arguments={self.arguments!r}"
-            ", directives={self.directives!r}"
-            ", selection_set={self.selection_set!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> Field
-        return type(self)(
-            self.name,
-            self.alias,
-            self.arguments,
-            self.directives,
-            self.selection_set,
-            self.loc,
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Argument(Node):
-    __slots__ = ("loc", "name", "value")
-    _fields = ("name", "value")
-
-    def __init__(self, name, value, loc=None):
-        # type: (Name, Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.name = name
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Argument)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("Argument(" "name={self.name!r}" ", value={self.value!r}" ")").format(
-            self=self
-        )
-
-    def __copy__(self):
-        # type: () -> Argument
-        return type(self)(self.name, self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class FragmentSpread(Selection):
-    __slots__ = ("loc", "name", "directives")
-    _fields = ("name", "directives")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        directives=None,  # type: List[Directive]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, FragmentSpread)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "FragmentSpread("
-            "name={self.name!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> FragmentSpread
-        return type(self)(self.name, self.directives, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class InlineFragment(Selection):
-    __slots__ = ("loc", "type_condition", "directives", "selection_set")
-    _fields = ("type_condition", "directives", "selection_set")
-
-    def __init__(
-        self,
-        type_condition,  # type: Optional[NamedType]
-        selection_set,  # type: SelectionSet
-        directives=None,  # type: Optional[List[Directive]]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.type_condition = type_condition
-        self.directives = directives
-        self.selection_set = selection_set
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, InlineFragment)
-            and
-            # self.loc == other.loc and
-            self.type_condition == other.type_condition
-            and self.directives == other.directives
-            and self.selection_set == other.selection_set
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "InlineFragment("
-            "type_condition={self.type_condition!r}"
-            ", directives={self.directives!r}"
-            ", selection_set={self.selection_set!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> InlineFragment
-        return type(self)(
-            self.type_condition, self.selection_set, self.directives, self.loc
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class FragmentDefinition(Definition):
-    __slots__ = ("loc", "name", "type_condition", "directives", "selection_set")
-    _fields = ("name", "type_condition", "directives", "selection_set")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        type_condition,  # type: Optional[NamedType]
-        selection_set,  # type: SelectionSet
-        directives=None,  # type: Optional[List[Directive]]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.type_condition = type_condition
-        self.directives = directives
-        self.selection_set = selection_set
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, FragmentDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.type_condition == other.type_condition
-            and self.directives == other.directives
-            and self.selection_set == other.selection_set
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "FragmentDefinition("
-            "name={self.name!r}"
-            ", type_condition={self.type_condition!r}"
-            ", directives={self.directives!r}"
-            ", selection_set={self.selection_set!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> FragmentDefinition
-        return type(self)(
-            self.name,
-            self.type_condition,
-            self.selection_set,
-            self.directives,
-            self.loc,
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Value(Node):
-    __slots__ = ()
-
-
-class Variable(Value):
-    __slots__ = ("loc", "name")
-    _fields = ("name",)
-
-    def __init__(self, name, loc=None):
-        # type: (Name, Optional[Loc]) -> None
-        self.loc = loc
-        self.name = name
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Variable)
-            and self.name == other.name
-            # and self.loc == other.loc
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("Variable(" "name={self.name!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> Variable
-        return type(self)(self.name, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class IntValue(Value):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (str, Optional[Loc]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, IntValue)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("IntValue(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> IntValue
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class FloatValue(Value):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (str, Optional[Any]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, FloatValue)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("FloatValue(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> FloatValue
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class StringValue(Value):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (str, Optional[Loc]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, StringValue)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("StringValue(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> StringValue
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class BooleanValue(Value):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (bool, Optional[Loc]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, BooleanValue)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("BooleanValue(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> BooleanValue
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class EnumValue(Value):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (str, Optional[Loc]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, EnumValue)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("EnumValue(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> EnumValue
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ListValue(Value):
-    __slots__ = ("loc", "values")
-    _fields = ("values",)
-
-    def __init__(self, values, loc=None):
-        # type: (Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.values = values
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ListValue)
-            and
-            # self.loc == other.loc and
-            self.values == other.values
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("ListValue(" "values={self.values!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> ListValue
-        return type(self)(self.values, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ObjectValue(Value):
-    __slots__ = ("loc", "fields")
-    _fields = ("fields",)
-
-    def __init__(self, fields, loc=None):
-        # type: (List[ObjectField], Optional[Loc]) -> None
-        self.loc = loc
-        self.fields = fields
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ObjectValue)
-            and
-            # self.loc == other.loc and
-            self.fields == other.fields
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("ObjectValue(" "fields={self.fields!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> ObjectValue
-        return type(self)(self.fields, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ObjectField(Node):
-    __slots__ = ("loc", "name", "value")
-    _fields = ("name", "value")
-
-    def __init__(self, name, value, loc=None):
-        # type: (Name, Any, Optional[Loc]) -> None
-        self.loc = loc
-        self.name = name
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ObjectField)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "ObjectField(" "name={self.name!r}" ", value={self.value!r}" ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> ObjectField
-        return type(self)(self.name, self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Directive(Node):
-    __slots__ = ("loc", "name", "arguments")
-    _fields = ("name", "arguments")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        arguments=None,  # type: Optional[List[Argument]]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.arguments = arguments
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Directive)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.arguments == other.arguments
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "Directive(" "name={self.name!r}" ", arguments={self.arguments!r}" ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> Directive
-        return type(self)(self.name, self.arguments, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Type(Node):
-    __slots__ = ()
-
-
-class NamedType(Type):
-    __slots__ = ("loc", "name")
-    _fields = ("name",)
-
-    def __init__(self, name, loc=None):
-        # type: (Name, Optional[Loc]) -> None
-        self.loc = loc
-        self.name = name
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, NamedType)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("NamedType(" "name={self.name!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> NamedType
-        return type(self)(self.name, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ListType(Type):
-    __slots__ = ("loc", "type")
-    _fields = ("type",)
-
-    def __init__(self, type, loc=None):
-        # type: (Union[NamedType, NonNullType], Optional[Loc]) -> None
-        self.loc = loc
-        self.type = type
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ListType)
-            and
-            # self.loc == other.loc and
-            self.type == other.type
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("ListType(" "type={self.type!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> ListType
-        return type(self)(self.type, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class NonNullType(Type):
-    __slots__ = ("loc", "type")
-    _fields = ("type",)
-
-    def __init__(self, type, loc=None):
-        # type: (Union[ListType, NamedType], Optional[Loc]) -> None
-        self.loc = loc
-        self.type = type
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, NonNullType)
-            and
-            # self.loc == other.loc and
-            self.type == other.type
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("NonNullType(" "type={self.type!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> NonNullType
-        return type(self)(self.type, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class Name(Node):
-    __slots__ = ("loc", "value")
-    _fields = ("value",)
-
-    def __init__(self, value, loc=None):
-        # type: (str, Optional[Loc]) -> None
-        self.loc = loc
-        self.value = value
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, Name)
-            and
-            # self.loc == other.loc and
-            self.value == other.value
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("Name(" "value={self.value!r}" ")").format(self=self)
-
-    def __copy__(self):
-        # type: () -> Name
-        return type(self)(self.value, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-# Type System Definition
-
-
-class TypeDefinition(Node):
-    pass
-
-
-class TypeSystemDefinition(TypeDefinition):
-    pass
-
-
-class SchemaDefinition(TypeSystemDefinition):
-    __slots__ = ("loc", "directives", "operation_types")
-    _fields = ("operation_types",)
-
-    def __init__(
-        self,
-        operation_types,  # type: List[OperationTypeDefinition]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.operation_types = operation_types
-        self.loc = loc
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, SchemaDefinition)
-            and self.operation_types == other.operation_types
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "SchemaDefinition("
-            "operation_types={self.operation_types!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> SchemaDefinition
-        return type(self)(self.operation_types, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class OperationTypeDefinition(Node):
-    __slots__ = ("loc", "operation", "type")
-    _fields = ("operation", "type")
-
-    def __init__(self, operation, type, loc=None):
-        # type: (str, NamedType, Optional[Loc]) -> None
-        self.operation = operation
-        self.type = type
-        self.loc = loc
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, OperationTypeDefinition)
-            and self.operation == other.operation
-            and self.type == other.type
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "OperationTypeDefinition("
-            "operation={self.operation!r}"
-            ", type={self.type!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> OperationTypeDefinition
-        return type(self)(self.operation, self.type, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ObjectTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "interfaces", "directives", "fields")
-    _fields = ("name", "interfaces", "fields")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        fields,  # type: List[FieldDefinition]
-        interfaces=None,  # type: Optional[List[NamedType]]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.interfaces = interfaces
-        self.fields = fields
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ObjectTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.interfaces == other.interfaces
-            and self.fields == other.fields
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "ObjectTypeDefinition("
-            "name={self.name!r}"
-            ", interfaces={self.interfaces!r}"
-            ", fields={self.fields!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> ObjectTypeDefinition
-        return type(self)(
-            self.name, self.fields, self.interfaces, self.loc, self.directives
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class FieldDefinition(Node):
-    __slots__ = ("loc", "name", "arguments", "type", "directives")
-    _fields = ("name", "arguments", "type")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        arguments,  # type: List[InputValueDefinition]
-        type,  # type: Union[NamedType, NonNullType, ListType]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.arguments = arguments
-        self.type = type
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, FieldDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.arguments == other.arguments
-            and self.type == other.type
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "FieldDefinition("
-            "name={self.name!r}"
-            ", arguments={self.arguments!r}"
-            ", type={self.type!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> FieldDefinition
-        return type(self)(
-            self.name, self.arguments, self.type, self.loc, self.directives
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class InputValueDefinition(Node):
-    __slots__ = ("loc", "name", "type", "default_value", "directives")
-    _fields = ("name", "type", "default_value")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        type,  # type: Union[NamedType, NonNullType, ListType]
-        default_value=None,  # type: Any
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.type = type
-        self.default_value = default_value
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, InputValueDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.type == other.type
-            and self.default_value == other.default_value
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "InputValueDefinition("
-            "name={self.name!r}"
-            ", type={self.type!r}"
-            ", default_value={self.default_value!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> InputValueDefinition
-        return type(self)(
-            self.name, self.type, self.default_value, self.loc, self.directives
-        )
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class InterfaceTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "fields", "directives")
-    _fields = ("name", "fields")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        fields,  # type: List[FieldDefinition]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.fields = fields
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, InterfaceTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.fields == other.fields
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "InterfaceTypeDefinition("
-            "name={self.name!r}"
-            ", fields={self.fields!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> InterfaceTypeDefinition
-        return type(self)(self.name, self.fields, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class UnionTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "types", "directives")
-    _fields = ("name", "types")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        types,  # type: List[NamedType]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.types = types
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, UnionTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.types == other.types
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "UnionTypeDefinition("
-            "name={self.name!r}"
-            ", types={self.types!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> UnionTypeDefinition
-        return type(self)(self.name, self.types, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class ScalarTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "directives")
-    _fields = ("name",)
-
-    def __init__(
-        self,
-        name,  # type: Name
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, ScalarTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "ScalarTypeDefinition("
-            "name={self.name!r}"
-            "directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> ScalarTypeDefinition
-        return type(self)(self.name, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class EnumTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "values", "directives")
-    _fields = ("name", "values")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        values,  # type: List[EnumValueDefinition]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.values = values
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, EnumTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.values == other.values
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "EnumTypeDefinition("
-            "name={self.name!r}"
-            ", values={self.values!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> EnumTypeDefinition
-        return type(self)(self.name, self.values, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class EnumValueDefinition(Node):
-    __slots__ = ("loc", "name", "directives")
-    _fields = ("name",)
-
-    def __init__(
-        self,
-        name,  # type: Name
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, EnumValueDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "EnumValueDefinition("
-            "name={self.name!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> EnumValueDefinition
-        return type(self)(self.name, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class InputObjectTypeDefinition(TypeDefinition):
-    __slots__ = ("loc", "name", "fields", "directives")
-    _fields = ("name", "fields")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        fields,  # type: List[InputValueDefinition]
-        loc=None,  # type: Optional[Loc]
-        directives=None,  # type: Optional[List[Directive]]
-    ):
-        # type: (...) -> None
-        self.loc = loc
-        self.name = name
-        self.fields = fields
-        self.directives = directives
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, InputObjectTypeDefinition)
-            and
-            # self.loc == other.loc and
-            self.name == other.name
-            and self.fields == other.fields
-            and self.directives == other.directives
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "InputObjectTypeDefinition("
-            "name={self.name!r}"
-            ", fields={self.fields!r}"
-            ", directives={self.directives!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> InputObjectTypeDefinition
-        return type(self)(self.name, self.fields, self.loc, self.directives)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class TypeExtensionDefinition(TypeSystemDefinition):
-    __slots__ = ("loc", "definition")
-    _fields = ("definition",)
-
-    def __init__(self, definition, loc=None):
-        # type: (ObjectTypeDefinition, Optional[Loc]) -> None
-        self.loc = loc
-        self.definition = definition
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, TypeExtensionDefinition)
-            and
-            # self.loc == other.loc and
-            self.definition == other.definition
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return ("TypeExtensionDefinition(" "definition={self.definition!r}" ")").format(
-            self=self
-        )
-
-    def __copy__(self):
-        # type: () -> TypeExtensionDefinition
-        return type(self)(self.definition, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
-
-
-class DirectiveDefinition(TypeSystemDefinition):
-    __slots__ = ("loc", "name", "arguments", "locations")
-    _fields = ("name", "locations")
-
-    def __init__(
-        self,
-        name,  # type: Name
-        locations,  # type: List[Name]
-        arguments=None,  # type: Optional[List[InputValueDefinition]]
-        loc=None,  # type: Optional[Loc]
-    ):
-        # type: (...) -> None
-        self.name = name
-        self.locations = locations
-        self.loc = loc
-        self.arguments = arguments
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return self is other or (
-            isinstance(other, DirectiveDefinition)
-            and self.name == other.name
-            and self.locations == other.locations
-            and
-            # self.loc == other.loc and
-            self.arguments == other.arguments
-        )
-
-    def __repr__(self):
-        # type: () -> str
-        return (
-            "DirectiveDefinition("
-            "name={self.name!r}, "
-            "locations={self.locations!r}"
-            ")"
-        ).format(self=self)
-
-    def __copy__(self):
-        # type: () -> DirectiveDefinition
-        return type(self)(self.name, self.locations, self.arguments, self.loc)
-
-    def __hash__(self):
-        # type: () -> int
-        return id(self)
diff --git a/graphql/language/base.py b/graphql/language/base.py
deleted file mode 100644
index fca28dc..0000000
--- a/graphql/language/base.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from .lexer import Lexer
-from .location import get_location
-from .parser import parse, parse_value
-from .printer import print_ast
-from .source import Source
-from .visitor import BREAK, ParallelVisitor, TypeInfoVisitor, visit
-
-__all__ = [
-    "Lexer",
-    "get_location",
-    "parse",
-    "parse_value",
-    "print_ast",
-    "Source",
-    "BREAK",
-    "ParallelVisitor",
-    "TypeInfoVisitor",
-    "visit",
-]
diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py
deleted file mode 100644
index 45cd668..0000000
--- a/graphql/language/lexer.py
+++ /dev/null
@@ -1,475 +0,0 @@
-import json
-
-from six import unichr
-
-from ..error import GraphQLSyntaxError
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Optional, Any, List
-    from .source import Source
-
-__all__ = ["Token", "Lexer", "TokenKind", "get_token_desc", "get_token_kind_desc"]
-
-
-class Token(object):
-    __slots__ = "kind", "start", "end", "value"
-
-    def __init__(self, kind, start, end, value=None):
-        # type: (int, int, int, Optional[str]) -> None
-        self.kind = kind
-        self.start = start
-        self.end = end
-        self.value = value
-
-    def __repr__(self):
-        # type: () -> str
-        return u"<Token kind={} at {}..{} value={}>".format(
-            get_token_kind_desc(self.kind), self.start, self.end, repr(self.value)
-        )
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return (
-            isinstance(other, Token)
-            and self.kind == other.kind
-            and self.start == other.start
-            and self.end == other.end
-            and self.value == other.value
-        )
-
-
-class Lexer(object):
-    __slots__ = "source", "prev_position"
-
-    def __init__(self, source):
-        # type: (Source) -> None
-        self.source = source
-        self.prev_position = 0
-
-    def next_token(self, reset_position=None):
-        # type: (Optional[int]) -> Token
-        if reset_position is None:
-            reset_position = self.prev_position
-        token = read_token(self.source, reset_position)
-        self.prev_position = token.end
-        return token
-
-
-class TokenKind(object):
-    EOF = 1
-    BANG = 2
-    DOLLAR = 3
-    PAREN_L = 4
-    PAREN_R = 5
-    SPREAD = 6
-    COLON = 7
-    EQUALS = 8
-    AT = 9
-    BRACKET_L = 10
-    BRACKET_R = 11
-    BRACE_L = 12
-    PIPE = 13
-    BRACE_R = 14
-    NAME = 15
-    VARIABLE = 16
-    INT = 17
-    FLOAT = 18
-    STRING = 19
-
-
-def get_token_desc(token):
-    # type: (Token) -> str
-    if token.value:
-        return u'{} "{}"'.format(get_token_kind_desc(token.kind), token.value)
-    else:
-        return get_token_kind_desc(token.kind)
-
-
-def get_token_kind_desc(kind):
-    # type: (int) -> str
-    return TOKEN_DESCRIPTION[kind]
-
-
-TOKEN_DESCRIPTION = {
-    TokenKind.EOF: "EOF",
-    TokenKind.BANG: "!",
-    TokenKind.DOLLAR: "$",
-    TokenKind.PAREN_L: "(",
-    TokenKind.PAREN_R: ")",
-    TokenKind.SPREAD: "...",
-    TokenKind.COLON: ":",
-    TokenKind.EQUALS: "=",
-    TokenKind.AT: "@",
-    TokenKind.BRACKET_L: "[",
-    TokenKind.BRACKET_R: "]",
-    TokenKind.BRACE_L: "{",
-    TokenKind.PIPE: "|",
-    TokenKind.BRACE_R: "}",
-    TokenKind.NAME: "Name",
-    TokenKind.VARIABLE: "Variable",
-    TokenKind.INT: "Int",
-    TokenKind.FLOAT: "Float",
-    TokenKind.STRING: "String",
-}
-
-
-def char_code_at(s, pos):
-    # type: (str, int) -> Optional[int]
-    if 0 <= pos < len(s):
-        return ord(s[pos])
-
-    return None
-
-
-PUNCT_CODE_TO_KIND = {
-    ord("!"): TokenKind.BANG,
-    ord("$"): TokenKind.DOLLAR,
-    ord("("): TokenKind.PAREN_L,
-    ord(")"): TokenKind.PAREN_R,
-    ord(":"): TokenKind.COLON,
-    ord("="): TokenKind.EQUALS,
-    ord("@"): TokenKind.AT,
-    ord("["): TokenKind.BRACKET_L,
-    ord("]"): TokenKind.BRACKET_R,
-    ord("{"): TokenKind.BRACE_L,
-    ord("|"): TokenKind.PIPE,
-    ord("}"): TokenKind.BRACE_R,
-}
-
-
-def print_char_code(code):
-    # type: (Optional[int]) -> str
-    if code is None:
-        return "<EOF>"
-
-    if code < 0x007F:
-        return json.dumps(unichr(code))
-
-    return '"\\u%04X"' % code
-
-
-def read_token(source, from_position):
-    # type: (Source, int) -> Token
-    """Gets the next token from the source starting at the given position.
-
-    This skips over whitespace and comments until it finds the next lexable
-    token, then lexes punctuators immediately or calls the appropriate
-    helper fucntion for more complicated tokens."""
-    body = source.body
-    body_length = len(body)
-
-    position = position_after_whitespace(body, from_position)
-
-    if position >= body_length:
-        return Token(TokenKind.EOF, position, position)
-
-    code = char_code_at(body, position)
-    if code:
-        if code < 0x0020 and code not in (0x0009, 0x000A, 0x000D):
-            raise GraphQLSyntaxError(
-                source, position, u"Invalid character {}.".format(print_char_code(code))
-            )
-
-        kind = PUNCT_CODE_TO_KIND.get(code)
-        if kind is not None:
-            return Token(kind, position, position + 1)
-
-        if code == 46:  # .
-            if (
-                char_code_at(body, position + 1)
-                == char_code_at(body, position + 2)
-                == 46
-            ):
-                return Token(TokenKind.SPREAD, position, position + 3)
-
-        elif 65 <= code <= 90 or code == 95 or 97 <= code <= 122:
-            # A-Z, _, a-z
-            return read_name(source, position)
-
-        elif code == 45 or 48 <= code <= 57:  # -, 0-9
-            return read_number(source, position, code)
-
-        elif code == 34:  # "
-            return read_string(source, position)
-
-    raise GraphQLSyntaxError(
-        source, position, u"Unexpected character {}.".format(print_char_code(code))
-    )
-
-
-ignored_whitespace_characters = frozenset(
-    [
-        # BOM
-        0xFEFF,
-        # White Space
-        0x0009,  # tab
-        0x0020,  # space
-        # Line Terminator
-        0x000A,  # new line
-        0x000D,  # carriage return
-        # Comma
-        0x002C,
-    ]
-)
-
-
-def position_after_whitespace(body, start_position):
-    # type: (str, int) -> int
-    """Reads from body starting at start_position until it finds a
-    non-whitespace or commented character, then returns the position of
-    that character for lexing."""
-    body_length = len(body)
-    position = start_position
-    while position < body_length:
-        code = char_code_at(body, position)
-        if code in ignored_whitespace_characters:
-            position += 1
-
-        elif code == 35:  # #, skip comments
-            position += 1
-            while position < body_length:
-                code = char_code_at(body, position)
-                if not (
-                    code is not None
-                    and (code > 0x001F or code == 0x0009)
-                    and code not in (0x000A, 0x000D)
-                ):
-                    break
-
-                position += 1
-        else:
-            break
-    return position
-
-
-def read_number(source, start, first_code):
-    # type: (Source, int, Optional[int]) -> Token
-    r"""Reads a number token from the source file, either a float
-    or an int depending on whether a decimal point appears.
-
-    Int:   -?(0|[1-9][0-9]*)
-    Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?"""
-    code = first_code
-    body = source.body
-    position = start
-    is_float = False
-
-    if code == 45:  # -
-        position += 1
-        code = char_code_at(body, position)
-
-    if code == 48:  # 0
-        position += 1
-        code = char_code_at(body, position)
-
-        if code is not None and 48 <= code <= 57:
-            raise GraphQLSyntaxError(
-                source,
-                position,
-                u"Invalid number, unexpected digit after 0: {}.".format(
-                    print_char_code(code)
-                ),
-            )
-    else:
-        position = read_digits(source, position, code)
-        code = char_code_at(body, position)
-
-    if code == 46:  # .
-        is_float = True
-
-        position += 1
-        code = char_code_at(body, position)
-        position = read_digits(source, position, code)
-        code = char_code_at(body, position)
-
-    if code in (69, 101):  # E e
-        is_float = True
-        position += 1
-        code = char_code_at(body, position)
-        if code in (43, 45):  # + -
-            position += 1
-            code = char_code_at(body, position)
-
-        position = read_digits(source, position, code)
-
-    return Token(
-        TokenKind.FLOAT if is_float else TokenKind.INT,
-        start,
-        position,
-        body[start:position],
-    )
-
-
-def read_digits(source, start, first_code):
-    # type: (Source, int, Optional[int]) -> int
-    body = source.body
-    position = start
-    code = first_code
-
-    if code is not None and 48 <= code <= 57:  # 0 - 9
-        while True:
-            position += 1
-            code = char_code_at(body, position)
-
-            if not (code is not None and 48 <= code <= 57):
-                break
-
-        return position
-
-    raise GraphQLSyntaxError(
-        source,
-        position,
-        u"Invalid number, expected digit but got: {}.".format(print_char_code(code)),
-    )
-
-
-ESCAPED_CHAR_CODES = {
-    34: '"',
-    47: "/",
-    92: "\\",
-    98: "\b",
-    102: "\f",
-    110: "\n",
-    114: "\r",
-    116: "\t",
-}
-
-
-def read_string(source, start):
-    # type: (Source, int) -> Token
-    """Reads a string token from the source file.
-
-    "([^"\\\u000A\u000D\u2028\u2029]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
-    """
-    body = source.body
-    body_length = len(body)
-
-    position = start + 1
-    chunk_start = position
-    code = 0  # type: Optional[int]
-    value = []  # type: List[str]
-    append = value.append
-
-    while position < body_length:
-        code = char_code_at(body, position)
-        if code in (
-            None,
-            # LineTerminator
-            0x000A,
-            0x000D,
-            # Quote
-            34,
-        ):
-            break
-
-        if code < 0x0020 and code != 0x0009:  # type: ignore
-            raise GraphQLSyntaxError(
-                source,
-                position,
-                u"Invalid character within String: {}.".format(print_char_code(code)),
-            )
-
-        position += 1
-        if code == 92:  # \
-            append(body[chunk_start : position - 1])
-
-            code = char_code_at(body, position)
-            escaped = ESCAPED_CHAR_CODES.get(code)  # type: ignore
-            if escaped is not None:
-                append(escaped)
-
-            elif code == 117:  # u
-                char_code = uni_char_code(
-                    char_code_at(body, position + 1) or 0,
-                    char_code_at(body, position + 2) or 0,
-                    char_code_at(body, position + 3) or 0,
-                    char_code_at(body, position + 4) or 0,
-                )
-
-                if char_code < 0:
-                    raise GraphQLSyntaxError(
-                        source,
-                        position,
-                        u"Invalid character escape sequence: \\u{}.".format(
-                            body[position + 1 : position + 5]
-                        ),
-                    )
-
-                append(unichr(char_code))
-                position += 4
-            else:
-                raise GraphQLSyntaxError(
-                    source,
-                    position,
-                    u"Invalid character escape sequence: \\{}.".format(
-                        unichr(code)  # type: ignore
-                    ),
-                )
-
-            position += 1
-            chunk_start = position
-
-    if code != 34:  # Quote (")
-        raise GraphQLSyntaxError(source, position, "Unterminated string")
-
-    append(body[chunk_start:position])
-    return Token(TokenKind.STRING, start, position + 1, u"".join(value))
-
-
-def uni_char_code(a, b, c, d):
-    # type: (int, int, int, int) -> int
-    """Converts four hexidecimal chars to the integer that the
-    string represents. For example, uniCharCode('0','0','0','f')
-    will return 15, and uniCharCode('0','0','f','f') returns 255.
-
-    Returns a negative number on error, if a char was invalid.
-
-    This is implemented by noting that char2hex() returns -1 on error,
-    which means the result of ORing the char2hex() will also be negative.
-    """
-    return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d)
-
-
-def char2hex(a):
-    # type: (int) -> int
-    """Converts a hex character to its integer value.
-    '0' becomes 0, '9' becomes 9
-    'A' becomes 10, 'F' becomes 15
-    'a' becomes 10, 'f' becomes 15
-
-    Returns -1 on error."""
-    if 48 <= a <= 57:  # 0-9
-        return a - 48
-    elif 65 <= a <= 70:  # A-F
-        return a - 55
-    elif 97 <= a <= 102:  # a-f
-        return a - 87
-    return -1
-
-
-def read_name(source, position):
-    # type: (Source, int) -> Token
-    """Reads an alphanumeric + underscore name from the source.
-
-    [_A-Za-z][_0-9A-Za-z]*"""
-    body = source.body
-    body_length = len(body)
-    end = position + 1
-
-    while end != body_length:
-        code = char_code_at(body, end)
-        if not (
-            code is not None
-            and (
-                code == 95
-                or 48 <= code <= 57  # _
-                or 65 <= code <= 90  # 0-9
-                or 97 <= code <= 122  # A-Z  # a-z
-            )
-        ):
-            break
-
-        end += 1
-
-    return Token(TokenKind.NAME, position, end, body[position:end])
diff --git a/graphql/language/location.py b/graphql/language/location.py
deleted file mode 100644
index 71c19bd..0000000
--- a/graphql/language/location.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from .source import Source
-    from typing import Any
-
-__all__ = ["get_location", "SourceLocation"]
-
-
-class SourceLocation(object):
-    __slots__ = "line", "column"
-
-    def __init__(self, line, column):
-        # type: (int, int) -> None
-        self.line = line
-        self.column = column
-
-    def __repr__(self):
-        # type: () -> str
-        return "SourceLocation(line={}, column={})".format(self.line, self.column)
-
-    def __eq__(self, other):
-        # type: (Any) -> bool
-        return (
-            isinstance(other, SourceLocation)
-            and self.line == other.line
-            and self.column == other.column
-        )
-
-
-def get_location(source, position):
-    # type: (Source, int) -> SourceLocation
-    lines = source.body[:position].splitlines()
-    if lines:
-        line = len(lines)
-        column = len(lines[-1]) + 1
-    else:
-        line = 1
-        column = 1
-    return SourceLocation(line, column)
diff --git a/graphql/language/parser.py b/graphql/language/parser.py
deleted file mode 100644
index 6157185..0000000
--- a/graphql/language/parser.py
+++ /dev/null
@@ -1,879 +0,0 @@
-from six import string_types
-
-from . import ast
-from ..error import GraphQLSyntaxError
-from .lexer import Lexer, TokenKind, get_token_desc, get_token_kind_desc
-from .source import Source
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Dict, Union, Any, Optional, Callable, List
-    from .lexer import Token
-    from .ast import (
-        Document,
-        Name,
-        OperationDefinition,
-        VariableDefinition,
-        Variable,
-        SelectionSet,
-        Field,
-        FragmentSpread,
-        Argument,
-        InlineFragment,
-        FragmentDefinition,
-        IntValue,
-        StringValue,
-        BooleanValue,
-        ObjectValue,
-        ListValue,
-        ObjectField,
-        Directive,
-        NamedType,
-        NonNullType,
-        ListType,
-        SchemaDefinition,
-        OperationTypeDefinition,
-        ScalarTypeDefinition,
-        ObjectTypeDefinition,
-        FieldDefinition,
-        InputValueDefinition,
-        InterfaceTypeDefinition,
-        UnionTypeDefinition,
-        EnumTypeDefinition,
-        EnumValueDefinition,
-        InputObjectTypeDefinition,
-        TypeExtensionDefinition,
-        DirectiveDefinition,
-    )
-
-__all__ = ["parse"]
-
-
-def parse(source, **kwargs):
-    # type: (Union[Source, str], **Any) -> Document
-    """Given a GraphQL source, parses it into a Document."""
-    options = {"no_location": False, "no_source": False}
-    options.update(kwargs)
-
-    if isinstance(source, string_types):
-        source_obj = Source(source)  # type: Source
-    else:
-        source_obj = source  # type: ignore
-
-    parser = Parser(source_obj, options)
-    return parse_document(parser)
-
-
-def parse_value(source, **kwargs):
-    options = {"no_location": False, "no_source": False}
-    options.update(kwargs)
-    source_obj = source
-
-    if isinstance(source, string_types):
-        source_obj = Source(source)
-
-    parser = Parser(source_obj, options)
-    return parse_value_literal(parser, False)
-
-
-class Parser(object):
-    __slots__ = "lexer", "source", "options", "prev_end", "token"
-
-    def __init__(self, source, options):
-        # type: (Source, Dict[str, bool]) -> None
-        self.lexer = Lexer(source)
-        self.source = source
-        self.options = options
-        self.prev_end = 0
-        self.token = self.lexer.next_token()
-
-
-class Loc(object):
-    __slots__ = "start", "end", "source"
-
-    def __init__(self, start, end, source=None):
-        # type: (int, int, Union[Source, str]) -> None
-        self.start = start
-        self.end = end
-        self.source = source
-
-    def __repr__(self):
-        # type: () -> str
-        source = " source={}".format(self.source) if self.source else ""
-        return "<Loc start={} end={}{}>".format(self.start, self.end, source)
-
-    def __eq__(self, other):
-        return (
-            isinstance(other, Loc)
-            and self.start == other.start
-            and self.end == other.end
-            and self.source == other.source
-        )
-
-
-def loc(parser, start):
-    # type: (Parser, int) -> Optional[Loc]
-    """Returns a location object, used to identify the place in
-    the source that created a given parsed object."""
-    if parser.options["no_location"]:
-        return None
-
-    if parser.options["no_source"]:
-        return Loc(start, parser.prev_end)
-
-    return Loc(start, parser.prev_end, parser.source)
-
-
-def advance(parser):
-    # type: (Parser) -> None
-    """Moves the internal parser object to the next lexed token."""
-    prev_end = parser.token.end
-    parser.prev_end = prev_end
-    parser.token = parser.lexer.next_token(prev_end)
-
-
-def peek(parser, kind):
-    # type: (Parser, int) -> bool
-    """Determines if the next token is of a given kind"""
-    return parser.token.kind == kind
-
-
-def skip(parser, kind):
-    # type: (Parser, int) -> bool
-    """If the next token is of the given kind, return true after advancing
-    the parser. Otherwise, do not change the parser state
-    and throw an error."""
-    match = parser.token.kind == kind
-    if match:
-        advance(parser)
-
-    return match
-
-
-def expect(parser, kind):
-    # type: (Parser, int) -> Token
-    """If the next token is of the given kind, return that token after
-    advancing the parser. Otherwise, do not change the parser state and
-    return False."""
-    token = parser.token
-    if token.kind == kind:
-        advance(parser)
-        return token
-
-    raise GraphQLSyntaxError(
-        parser.source,
-        token.start,
-        u"Expected {}, found {}".format(
-            get_token_kind_desc(kind), get_token_desc(token)
-        ),
-    )
-
-
-def expect_keyword(parser, value):
-    # type: (Parser, str) -> Token
-    """If the next token is a keyword with the given value, return that
-    token after advancing the parser. Otherwise, do not change the parser
-    state and return False."""
-    token = parser.token
-    if token.kind == TokenKind.NAME and token.value == value:
-        advance(parser)
-        return token
-
-    raise GraphQLSyntaxError(
-        parser.source,
-        token.start,
-        u'Expected "{}", found {}'.format(value, get_token_desc(token)),
-    )
-
-
-def unexpected(parser, at_token=None):
-    # type: (Parser, Optional[Any]) -> GraphQLSyntaxError
-    """Helper function for creating an error when an unexpected lexed token
-    is encountered."""
-    token = at_token or parser.token
-    return GraphQLSyntaxError(
-        parser.source, token.start, u"Unexpected {}".format(get_token_desc(token))
-    )
-
-
-def any(parser, open_kind, parse_fn, close_kind):
-    # type: (Parser, int, Callable, int) -> Any
-    """Returns a possibly empty list of parse nodes, determined by
-    the parse_fn. This list begins with a lex token of openKind
-    and ends with a lex token of closeKind. Advances the parser
-    to the next lex token after the closing token."""
-    expect(parser, open_kind)
-    nodes = []
-    while not skip(parser, close_kind):
-        nodes.append(parse_fn(parser))
-
-    return nodes
-
-
-def many(parser, open_kind, parse_fn, close_kind):
-    # type: (Parser, int, Callable, int) -> Any
-    """Returns a non-empty list of parse nodes, determined by
-    the parse_fn. This list begins with a lex token of openKind
-    and ends with a lex token of closeKind. Advances the parser
-    to the next lex token after the closing token."""
-    expect(parser, open_kind)
-    nodes = [parse_fn(parser)]
-    while not skip(parser, close_kind):
-        nodes.append(parse_fn(parser))
-
-    return nodes
-
-
-def parse_name(parser):
-    # type: (Parser) -> Name
-    """Converts a name lex token into a name parse node."""
-    token = expect(parser, TokenKind.NAME)
-    return ast.Name(value=token.value, loc=loc(parser, token.start))  # type: ignore
-
-
-# Implements the parsing rules in the Document section.
-
-
-def parse_document(parser):
-    # type: (Parser) -> Document
-    start = parser.token.start
-    definitions = []
-    while True:
-        definitions.append(parse_definition(parser))
-
-        if skip(parser, TokenKind.EOF):
-            break
-
-    return ast.Document(definitions=definitions, loc=loc(parser, start))
-
-
-def parse_definition(parser):
-    # type: (Parser) -> Any
-    if peek(parser, TokenKind.BRACE_L):
-        return parse_operation_definition(parser)
-
-    if peek(parser, TokenKind.NAME):
-        name = parser.token.value
-
-        if name in ("query", "mutation", "subscription"):
-            return parse_operation_definition(parser)
-        elif name == "fragment":
-            return parse_fragment_definition(parser)
-        elif name in (
-            "schema",
-            "scalar",
-            "type",
-            "interface",
-            "union",
-            "enum",
-            "input",
-            "extend",
-            "directive",
-        ):
-            return parse_type_system_definition(parser)
-
-    raise unexpected(parser)
-
-
-# Implements the parsing rules in the Operations section.
-def parse_operation_definition(parser):
-    # type: (Parser) -> OperationDefinition
-    start = parser.token.start
-    if peek(parser, TokenKind.BRACE_L):
-        return ast.OperationDefinition(
-            operation="query",
-            name=None,
-            variable_definitions=None,
-            directives=[],
-            selection_set=parse_selection_set(parser),
-            loc=loc(parser, start),
-        )
-
-    operation = parse_operation_type(parser)
-
-    name = None
-    if peek(parser, TokenKind.NAME):
-        name = parse_name(parser)
-
-    return ast.OperationDefinition(
-        operation=operation,
-        name=name,
-        variable_definitions=parse_variable_definitions(parser),
-        directives=parse_directives(parser),
-        selection_set=parse_selection_set(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_operation_type(parser):
-    # type: (Parser) -> str
-    operation_token = expect(parser, TokenKind.NAME)
-    operation = operation_token.value
-    if operation == "query":
-        return "query"
-    elif operation == "mutation":
-        return "mutation"
-    elif operation == "subscription":
-        return "subscription"
-
-    raise unexpected(parser, operation_token)
-
-
-def parse_variable_definitions(parser):
-    # type: (Parser) -> List[VariableDefinition]
-    if peek(parser, TokenKind.PAREN_L):
-        return many(
-            parser, TokenKind.PAREN_L, parse_variable_definition, TokenKind.PAREN_R
-        )
-
-    return []
-
-
-def parse_variable_definition(parser):
-    # type: (Parser) -> VariableDefinition
-    start = parser.token.start
-
-    return ast.VariableDefinition(
-        variable=parse_variable(parser),
-        type=expect(parser, TokenKind.COLON) and parse_type(parser),
-        default_value=parse_value_literal(parser, True)
-        if skip(parser, TokenKind.EQUALS)
-        else None,
-        loc=loc(parser, start),
-    )
-
-
-def parse_variable(parser):
-    # type: (Parser) -> Variable
-    start = parser.token.start
-    expect(parser, TokenKind.DOLLAR)
-
-    return ast.Variable(name=parse_name(parser), loc=loc(parser, start))
-
-
-def parse_selection_set(parser):
-    # type: (Parser) -> SelectionSet
-    start = parser.token.start
-    return ast.SelectionSet(
-        selections=many(parser, TokenKind.BRACE_L, parse_selection, TokenKind.BRACE_R),
-        loc=loc(parser, start),
-    )
-
-
-def parse_selection(parser):
-    # type: (Parser) -> Union[Field, FragmentSpread, InlineFragment]
-    if peek(parser, TokenKind.SPREAD):
-        return parse_fragment(parser)
-    else:
-        return parse_field(parser)
-
-
-def parse_field(parser):
-    # type: (Parser) -> Field
-    # Corresponds to both Field and Alias in the spec
-    start = parser.token.start
-
-    name_or_alias = parse_name(parser)
-    if skip(parser, TokenKind.COLON):
-        alias = name_or_alias
-        name = parse_name(parser)
-    else:
-        alias = None  # type: ignore
-        name = name_or_alias
-
-    return ast.Field(
-        alias=alias,
-        name=name,
-        arguments=parse_arguments(parser),
-        directives=parse_directives(parser),
-        selection_set=parse_selection_set(parser)
-        if peek(parser, TokenKind.BRACE_L)
-        else None,
-        loc=loc(parser, start),
-    )
-
-
-def parse_arguments(parser):
-    # type: (Parser) -> List[Argument]
-    if peek(parser, TokenKind.PAREN_L):
-        return many(parser, TokenKind.PAREN_L, parse_argument, TokenKind.PAREN_R)
-
-    return []
-
-
-def parse_argument(parser):
-    # type: (Parser) -> Argument
-    start = parser.token.start
-
-    return ast.Argument(
-        name=parse_name(parser),
-        value=expect(parser, TokenKind.COLON) and parse_value_literal(parser, False),
-        loc=loc(parser, start),
-    )
-
-
-# Implements the parsing rules in the Fragments section.
-
-
-def parse_fragment(parser):
-    # type: (Parser) -> Union[FragmentSpread, InlineFragment]
-    # Corresponds to both FragmentSpread and InlineFragment in the spec
-    start = parser.token.start
-    expect(parser, TokenKind.SPREAD)
-
-    if peek(parser, TokenKind.NAME) and parser.token.value != "on":
-        return ast.FragmentSpread(
-            name=parse_fragment_name(parser),
-            directives=parse_directives(parser),
-            loc=loc(parser, start),
-        )
-
-    type_condition = None
-    if parser.token.value == "on":
-        advance(parser)
-        type_condition = parse_named_type(parser)
-
-    return ast.InlineFragment(
-        type_condition=type_condition,
-        directives=parse_directives(parser),
-        selection_set=parse_selection_set(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_fragment_definition(parser):
-    # type: (Parser) -> FragmentDefinition
-    start = parser.token.start
-    expect_keyword(parser, "fragment")
-
-    return ast.FragmentDefinition(
-        name=parse_fragment_name(parser),
-        type_condition=parse_named_type(parser)
-        if expect_keyword(parser, "on")
-        else None,
-        directives=parse_directives(parser),
-        selection_set=parse_selection_set(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_fragment_name(parser):
-    # type: (Parser) -> Name
-    if parser.token.value == "on":
-        raise unexpected(parser)
-
-    return parse_name(parser)
-
-
-def parse_value_literal(parser, is_const):
-    # type: (Parser, bool) -> Any
-    token = parser.token
-    if token.kind == TokenKind.BRACKET_L:
-        return parse_list(parser, is_const)
-
-    elif token.kind == TokenKind.BRACE_L:
-        return parse_object(parser, is_const)
-
-    elif token.kind == TokenKind.INT:
-        advance(parser)
-        return ast.IntValue(  # type: ignore
-            value=token.value, loc=loc(parser, token.start)
-        )
-
-    elif token.kind == TokenKind.FLOAT:
-        advance(parser)
-        return ast.FloatValue(  # type: ignore
-            value=token.value, loc=loc(parser, token.start)
-        )
-
-    elif token.kind == TokenKind.STRING:
-        advance(parser)
-        return ast.StringValue(  # type: ignore
-            value=token.value, loc=loc(parser, token.start)
-        )
-
-    elif token.kind == TokenKind.NAME:
-        if token.value in ("true", "false"):
-            advance(parser)
-            return ast.BooleanValue(  # type: ignore
-                value=token.value == "true", loc=loc(parser, token.start)
-            )
-
-        if token.value != "null":
-            advance(parser)
-            return ast.EnumValue(  # type: ignore
-                value=token.value, loc=loc(parser, token.start)
-            )
-
-    elif token.kind == TokenKind.DOLLAR:
-        if not is_const:
-            return parse_variable(parser)
-
-    raise unexpected(parser)
-
-
-# Implements the parsing rules in the Values section.
-def parse_variable_value(parser):
-    # type: (Parser) -> Union[IntValue, StringValue, Variable]
-    return parse_value_literal(parser, False)
-
-
-def parse_const_value(parser):
-    # type: (Parser) -> Union[BooleanValue, ObjectValue, StringValue]
-    return parse_value_literal(parser, True)
-
-
-def parse_list(parser, is_const):
-    # type: (Parser, bool) -> ListValue
-    start = parser.token.start
-    item = parse_const_value if is_const else parse_variable_value
-
-    return ast.ListValue(
-        values=any(parser, TokenKind.BRACKET_L, item, TokenKind.BRACKET_R),
-        loc=loc(parser, start),
-    )
-
-
-def parse_object(parser, is_const):
-    # type: (Parser, bool) -> ObjectValue
-    start = parser.token.start
-    expect(parser, TokenKind.BRACE_L)
-    fields = []
-
-    while not skip(parser, TokenKind.BRACE_R):
-        fields.append(parse_object_field(parser, is_const))
-
-    return ast.ObjectValue(fields=fields, loc=loc(parser, start))
-
-
-def parse_object_field(parser, is_const):
-    # type: (Parser, bool) -> ObjectField
-    start = parser.token.start
-    return ast.ObjectField(
-        name=parse_name(parser),
-        value=expect(parser, TokenKind.COLON) and parse_value_literal(parser, is_const),
-        loc=loc(parser, start),
-    )
-
-
-# Implements the parsing rules in the Directives section.
-
-
-def parse_directives(parser):
-    # type: (Parser) -> List[Directive]
-    directives = []
-    while peek(parser, TokenKind.AT):
-        directives.append(parse_directive(parser))
-    return directives
-
-
-def parse_directive(parser):
-    # type: (Parser) -> Directive
-    start = parser.token.start
-    expect(parser, TokenKind.AT)
-
-    return ast.Directive(
-        name=parse_name(parser),
-        arguments=parse_arguments(parser),
-        loc=loc(parser, start),
-    )
-
-
-# Implements the parsing rules in the Types section.
-def parse_type(parser):
-    # type: (Parser) -> Union[NamedType, NonNullType, ListType]
-    """Handles the 'Type': TypeName, ListType, and NonNullType
-    parsing rules."""
-    start = parser.token.start
-    if skip(parser, TokenKind.BRACKET_L):
-        ast_type = parse_type(parser)
-        expect(parser, TokenKind.BRACKET_R)
-        ast_type = ast.ListType(type=ast_type, loc=loc(parser, start))  # type: ignore
-
-    else:
-        ast_type = parse_named_type(parser)
-
-    if skip(parser, TokenKind.BANG):
-        return ast.NonNullType(type=ast_type, loc=loc(parser, start))
-
-    return ast_type
-
-
-def parse_named_type(parser):
-    # type: (Parser) -> NamedType
-    start = parser.token.start
-    return ast.NamedType(name=parse_name(parser), loc=loc(parser, start))
-
-
-def parse_type_system_definition(parser):
-    # type: (Parser) -> Any
-    """
-      TypeSystemDefinition :
-        - SchemaDefinition
-        - TypeDefinition
-        - TypeExtensionDefinition
-        - DirectiveDefinition
-
-      TypeDefinition :
-      - ScalarTypeDefinition
-      - ObjectTypeDefinition
-      - InterfaceTypeDefinition
-      - UnionTypeDefinition
-      - EnumTypeDefinition
-      - InputObjectTypeDefinition
-    """
-    if not peek(parser, TokenKind.NAME):
-        raise unexpected(parser)
-
-    name = parser.token.value
-
-    if name == "schema":
-        return parse_schema_definition(parser)
-
-    elif name == "scalar":
-        return parse_scalar_type_definition(parser)
-
-    elif name == "type":
-        return parse_object_type_definition(parser)
-
-    elif name == "interface":
-        return parse_interface_type_definition(parser)
-
-    elif name == "union":
-        return parse_union_type_definition(parser)
-
-    elif name == "enum":
-        return parse_enum_type_definition(parser)
-
-    elif name == "input":
-        return parse_input_object_type_definition(parser)
-
-    elif name == "extend":
-        return parse_type_extension_definition(parser)
-
-    elif name == "directive":
-        return parse_directive_definition(parser)
-
-    raise unexpected(parser)
-
-
-def parse_schema_definition(parser):
-    # type: (Parser) -> SchemaDefinition
-    start = parser.token.start
-    expect_keyword(parser, "schema")
-    directives = parse_directives(parser)
-    operation_types = many(
-        parser, TokenKind.BRACE_L, parse_operation_type_definition, TokenKind.BRACE_R
-    )
-
-    return ast.SchemaDefinition(
-        directives=directives, operation_types=operation_types, loc=loc(parser, start)
-    )
-
-
-def parse_operation_type_definition(parser):
-    # type: (Parser) -> OperationTypeDefinition
-    start = parser.token.start
-    operation = parse_operation_type(parser)
-    expect(parser, TokenKind.COLON)
-
-    return ast.OperationTypeDefinition(
-        operation=operation, type=parse_named_type(parser), loc=loc(parser, start)
-    )
-
-
-def parse_scalar_type_definition(parser):
-    # type: (Parser) -> ScalarTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "scalar")
-
-    return ast.ScalarTypeDefinition(
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_object_type_definition(parser):
-    # type: (Parser) -> ObjectTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "type")
-    return ast.ObjectTypeDefinition(
-        name=parse_name(parser),
-        interfaces=parse_implements_interfaces(parser),
-        directives=parse_directives(parser),
-        fields=any(
-            parser, TokenKind.BRACE_L, parse_field_definition, TokenKind.BRACE_R
-        ),
-        loc=loc(parser, start),
-    )
-
-
-def parse_implements_interfaces(parser):
-    # type: (Parser) -> List[NamedType]
-    types = []
-    if parser.token.value == "implements":
-        advance(parser)
-
-        while True:
-            types.append(parse_named_type(parser))
-
-            if not peek(parser, TokenKind.NAME):
-                break
-
-    return types
-
-
-def parse_field_definition(parser):
-    # type: (Parser) -> FieldDefinition
-    start = parser.token.start
-
-    return ast.FieldDefinition(  # type: ignore
-        name=parse_name(parser),
-        arguments=parse_argument_defs(parser),
-        type=expect(parser, TokenKind.COLON) and parse_type(parser),
-        directives=parse_directives(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_argument_defs(parser):
-    # type: (Parser) -> List[InputValueDefinition]
-    if not peek(parser, TokenKind.PAREN_L):
-        return []
-
-    return many(parser, TokenKind.PAREN_L, parse_input_value_def, TokenKind.PAREN_R)
-
-
-def parse_input_value_def(parser):
-    # type: (Parser) -> InputValueDefinition
-    start = parser.token.start
-
-    return ast.InputValueDefinition(  # type: ignore
-        name=parse_name(parser),
-        type=expect(parser, TokenKind.COLON) and parse_type(parser),
-        default_value=parse_const_value(parser)
-        if skip(parser, TokenKind.EQUALS)
-        else None,
-        directives=parse_directives(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_interface_type_definition(parser):
-    # type: (Parser) -> InterfaceTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "interface")
-
-    return ast.InterfaceTypeDefinition(
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        fields=any(
-            parser, TokenKind.BRACE_L, parse_field_definition, TokenKind.BRACE_R
-        ),
-        loc=loc(parser, start),
-    )
-
-
-def parse_union_type_definition(parser):
-    # type: (Parser) -> UnionTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "union")
-
-    return ast.UnionTypeDefinition(  # type: ignore
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        types=expect(parser, TokenKind.EQUALS) and parse_union_members(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_union_members(parser):
-    # type: (Parser) -> List[NamedType]
-    members = []
-
-    while True:
-        members.append(parse_named_type(parser))
-
-        if not skip(parser, TokenKind.PIPE):
-            break
-
-    return members
-
-
-def parse_enum_type_definition(parser):
-    # type: (Parser) -> EnumTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "enum")
-
-    return ast.EnumTypeDefinition(
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        values=many(
-            parser, TokenKind.BRACE_L, parse_enum_value_definition, TokenKind.BRACE_R
-        ),
-        loc=loc(parser, start),
-    )
-
-
-def parse_enum_value_definition(parser):
-    # type: (Parser) -> EnumValueDefinition
-    start = parser.token.start
-
-    return ast.EnumValueDefinition(
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        loc=loc(parser, start),
-    )
-
-
-def parse_input_object_type_definition(parser):
-    # type: (Parser) -> InputObjectTypeDefinition
-    start = parser.token.start
-    expect_keyword(parser, "input")
-
-    return ast.InputObjectTypeDefinition(
-        name=parse_name(parser),
-        directives=parse_directives(parser),
-        fields=any(parser, TokenKind.BRACE_L, parse_input_value_def, TokenKind.BRACE_R),
-        loc=loc(parser, start),
-    )
-
-
-def parse_type_extension_definition(parser):
-    # type: (Parser) -> TypeExtensionDefinition
-    start = parser.token.start
-    expect_keyword(parser, "extend")
-
-    return ast.TypeExtensionDefinition(
-        definition=parse_object_type_definition(parser), loc=loc(parser, start)
-    )
-
-
-def parse_directive_definition(parser):
-    # type: (Parser) -> DirectiveDefinition
-    start = parser.token.start
-    expect_keyword(parser, "directive")
-    expect(parser, TokenKind.AT)
-
-    name = parse_name(parser)
-    args = parse_argument_defs(parser)
-    expect_keyword(parser, "on")
-
-    locations = parse_directive_locations(parser)
-    return ast.DirectiveDefinition(
-        name=name, locations=locations, arguments=args, loc=loc(parser, start)
-    )
-
-
-def parse_directive_locations(parser):
-    # type: (Parser) -> List[Name]
-    locations = []
-
-    while True:
-        locations.append(parse_name(parser))
-
-        if not skip(parser, TokenKind.PIPE):
-            break
-
-    return locations
diff --git a/graphql/language/printer.py b/graphql/language/printer.py
deleted file mode 100644
index e540bce..0000000
--- a/graphql/language/printer.py
+++ /dev/null
@@ -1,282 +0,0 @@
-import json
-
-from .visitor import Visitor, visit
-
-# Necessary for static type checking
-if False:  # flake8: noqa
-    from typing import Any, List, Optional
-    from graphql.language.ast import Node
-
-__all__ = ["print_ast"]
-
-
-def print_ast(ast):
-    # type: (Node) -> str
-    return visit(ast, PrintingVisitor())
-
-
-class PrintingVisitor(Visitor):
-    __slots__ = ()
-
-    def leave_Name(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.value  # type: ignore
-
-    def leave_Variable(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "$" + node.name  # type: ignore
-
-    def leave_Document(self, node, *args):
-        # type: (Any, *Any) -> str
-        return join(node.definitions, "\n\n") + "\n"  # type: ignore
-
-    def leave_OperationDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        name = node.name
-        selection_set = node.selection_set
-        op = node.operation
-        var_defs = wrap("(", join(node.variable_definitions, ", "), ")")
-        directives = join(node.directives, " ")
-
-        if not name and not directives and not var_defs and op == "query":
-            return selection_set
-
-        return join([op, join([name, var_defs]), directives, selection_set], " ")
-
-    def leave_VariableDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.variable + ": " + node.type + wrap(" = ", node.default_value)
-
-    def leave_SelectionSet(self, node, *args):
-        # type: (Any, *Any) -> str
-        return block(node.selections)
-
-    def leave_Field(self, node, *args):
-        # type: (Any, *Any) -> str
-        return join(
-            [
-                wrap("", node.alias, ": ")
-                + node.name
-                + wrap("(", join(node.arguments, ", "), ")"),
-                join(node.directives, " "),
-                node.selection_set,
-            ],
-            " ",
-        )
-
-    def leave_Argument(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "{0.name}: {0.value}".format(node)
-
-    # Fragments
-
-    def leave_FragmentSpread(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "..." + node.name + wrap(" ", join(node.directives, " "))
-
-    def leave_InlineFragment(self, node, *args):
-        # type: (Any, *Any) -> str
-        return join(
-            [
-                "...",
-                wrap("on ", node.type_condition),
-                join(node.directives, ""),
-                node.selection_set,
-            ],
-            " ",
-        )
-
-    def leave_FragmentDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            "fragment {} on {} ".format(node.name, node.type_condition)
-            + wrap("", join(node.directives, " "), " ")
-            + node.selection_set
-        )
-
-    # Value
-
-    def leave_IntValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.value
-
-    def leave_FloatValue(self, node, *args):
-        return node.value
-
-    def leave_StringValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return json.dumps(node.value)
-
-    def leave_BooleanValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return json.dumps(node.value)
-
-    def leave_EnumValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.value
-
-    def leave_ListValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "[" + join(node.values, ", ") + "]"
-
-    def leave_ObjectValue(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "{" + join(node.fields, ", ") + "}"
-
-    def leave_ObjectField(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.name + ": " + node.value
-
-    # Directive
-
-    def leave_Directive(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "@" + node.name + wrap("(", join(node.arguments, ", "), ")")
-
-    # Type
-
-    def leave_NamedType(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.name
-
-    def leave_ListType(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "[" + node.type + "]"
-
-    def leave_NonNullType(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.type + "!"
-
-    # Type Definitions:
-
-    def leave_SchemaDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return join(
-            ["schema", join(node.directives, " "), block(node.operation_types)], " "
-        )
-
-    def leave_OperationTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "{}: {}".format(node.operation, node.type)
-
-    def leave_ScalarTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "scalar " + node.name + wrap(" ", join(node.directives, " "))
-
-    def leave_ObjectTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return join(
-            [
-                "type",
-                node.name,
-                wrap("implements ", join(node.interfaces, ", ")),
-                join(node.directives, " "),
-                block(node.fields),
-            ],
-            " ",
-        )
-
-    def leave_FieldDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            node.name
-            + wrap("(", join(node.arguments, ", "), ")")
-            + ": "
-            + node.type
-            + wrap(" ", join(node.directives, " "))
-        )
-
-    def leave_InputValueDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            node.name
-            + ": "
-            + node.type
-            + wrap(" = ", node.default_value)
-            + wrap(" ", join(node.directives, " "))
-        )
-
-    def leave_InterfaceTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            "interface "
-            + node.name
-            + wrap(" ", join(node.directives, " "))
-            + " "
-            + block(node.fields)
-        )
-
-    def leave_UnionTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            "union "
-            + node.name
-            + wrap(" ", join(node.directives, " "))
-            + " = "
-            + join(node.types, " | ")
-        )
-
-    def leave_EnumTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            "enum "
-            + node.name
-            + wrap(" ", join(node.directives, " "))
-            + " "
-            + block(node.values)
-        )
-
-    def leave_EnumValueDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return node.name + wrap(" ", join(node.directives, " "))
-
-    def leave_InputObjectTypeDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return (
-            "input "
-            + node.name
-            + wrap(" ", join(node.directives, " "))
-            + " "
-            + block(node.fields)
-        )
-
-    def leave_TypeExtensionDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "extend " + node.definition
-
-    def leave_DirectiveDefinition(self, node, *args):
-        # type: (Any, *Any) -> str
-        return "directive @{}{} on {}".format(
-            node.name,
-            wrap("(", join(node.arguments, ", "), ")"),
-            " | ".join(node.locations),
-        )
-
-
-def join(maybe_list, separator=""):
-    # type: (Optional[List[str]], str) -> str
-    if maybe_list:
-        return separator.join(filter(None, maybe_list))
-    return ""
-
-
-def block(_list):
-    # type: (List[str]) -> str
-    """Given a list, print each item on its own line, wrapped in an indented "{ }" block."""
-    if _list:
-        return indent("{\n" + join(_list, "\n")) + "\n}"
-    return "{}"
-
-
-def wrap(start, maybe_str, end=""):
-    # type: (str, Optional[str], str) -> str
-    if maybe_str:
-        return start + maybe_str + end
-    return ""
-
-
-def indent(maybe_str):
-    # type: (Optional[str]) -> str
-    if maybe_str:
-        return maybe_str.replace("\n", "\n  ")
-    return ""
diff --git a/graphql/language/source.py b/graphql/language/source.py
deleted file mode 100644
index 0f73777..0000000
--- a/graphql/language/source.py
+++ /dev/null
@@ -1,17 +0,0 @@
-__all__ = ["Source"]
-
-
-class Source(object):
-    __slots__ = "body", "name"
-
-    def __init__(self, body, name="GraphQL"):
-        # type: (str, str) -> None
-        self.body = body
-        self.name = name
-
-    def __eq__(self, other):
-        return self is other or (
-            isinstance(other, Source)
-            and self.body == other.body
-            and self.name == other.name
-        )
diff --git a/graphql/language/tests/__init__.py b/graphql/language/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/graphql/language/tests/fixtures.py b/graphql/language/tests/fixtures.py
deleted file mode 100644
index b16653c..0000000
--- a/graphql/language/tests/fixtures.py
+++ /dev/null
@@ -1,135 +0,0 @@
-KITCHEN_SINK = """
-# Copyright (c) 2015, Facebook, Inc.
-# All rights reserved.
-#
-# This source code is licensed under the BSD-style license found in the
-# LICENSE file in the root directory of this source tree. An additional grant
-# of patent rights can be found in the PATENTS file in the same directory.
-
-query queryName($foo: ComplexType, $site: Site = MOBILE) {
-  whoever123is: node(id: [123, 456]) {
-    id ,
-    ... on User @defer {
-      field2 {
-        id ,
-        alias: field1(first:10, after:$foo,) @include(if: $foo) {
-          id,
-          ...frag
-        }
-      }
-    }
-    ... @skip(unless: $foo) {
-      id
-    }
-    ... {
-      id
-    }
-  }
-}
-
-mutation likeStory {
-  like(story: 123) @defer {
-    story {
-      id
-    }
-  }
-}
-
-subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
-  storyLikeSubscribe(input: $input) {
-    story {
-      likers {
-        count
-      }
-      likeSentence {
-        text
-      }
-    }
-  }
-}
-
-fragment frag on Friend {
-  foo(size: $size, bar: $b, obj: {key: "value"})
-}
-
-{
-  unnamed(truthy: true, falsey: false),
-  query
-}
-"""
-
-SCHEMA_KITCHEN_SINK = """
-
-# Copyright (c) 2015, Facebook, Inc.
-# All rights reserved.
-#
-# This source code is licensed under the BSD-style license found in the
-# LICENSE file in the root directory of this source tree. An additional grant
-# of patent rights can be found in the PATENTS file in the same directory.
-
-schema {
-  query: QueryType
-  mutation: MutationType
-}
-
-type Foo implements Bar {
-  one: Type
-  two(argument: InputType!): Type
-  three(argument: InputType, other: String): Int
-  four(argument: String = "string"): String
-  five(argument: [String] = ["string", "string"]): String
-  six(argument: InputType = {key: "value"}): Type
-}
-
-type AnnotatedObject @onObject(arg: "value") {
-  annotatedField(arg: Type = "default" @onArg): Type @onField
-}
-
-interface Bar {
-  one: Type
-  four(argument: String = "string"): String
-}
-
-interface AnnotatedInterface @onInterface {
-  annotatedField(arg: Type @onArg): Type @onField
-}
-
-union Feed = Story | Article | Advert
-
-union AnnotatedUnion @onUnion = A | B
-
-scalar CustomScalar
-
-scalar AnnotatedScalar @onScalar
-
-enum Site {
-  DESKTOP
-  MOBILE
-}
-
-enum AnnotatedEnum @onEnum {
-  ANNOTATED_VALUE @onEnumValue
-  OTHER_VALUE
-}
-
-input InputType {
-  key: String!
-  answer: Int = 42
-}
-
-input AnnotatedInput @onInputObjectType {
-  annotatedField: Type @onField
-}
-
-extend type Foo {
-  seven(argument: [String]): Type
-}
-
-extend type Foo @onType {}
-
-type NoFields {}
-
-directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
-
-directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
-"""
diff --git a/graphql/language/tests/test_ast.py b/graphql/language/tests/test_ast.py
deleted file mode 100644
index 64b849a..0000000
--- a/graphql/language/tests/test_ast.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import copy
-
-from graphql.language.visitor_meta import QUERY_DOCUMENT_KEYS
-
-
-def test_ast_is_hashable():
-    # type: () -> None
-    for node_class in QUERY_DOCUMENT_KEYS:
-        node = node_class(loc=None, **{k: k for k in node_class._fields})
-        assert hash(node)
-
-
-def test_ast_is_copyable():
-    # type: () -> None
-    for node_class in QUERY_DOCUMENT_KEYS:
-        node = node_class(loc=None, **{k: k for k in node_class._fields})
-        assert copy.copy(node) == node
-
-
-def test_ast_is_reprable():
-    # type: () -> None
-    for node_class in QUERY_DOCUMENT_KEYS:
-        node = node_class(loc=None, **{k: k for k in node_class._fields})
-        assert repr(node)
diff --git a/graphql/language/tests/test_lexer.py b/graphql/language/tests/test_lexer.py
deleted file mode 100644
index dda777d..0000000
--- a/graphql/language/tests/test_lexer.py
+++ /dev/null
@@ -1,318 +0,0 @@
-from pytest import raises
-
-from graphql.error import GraphQLSyntaxError
-from graphql.language.lexer import Lexer, Token, TokenKind
-from graphql.language.source import Source
-
-
-def lex_one(s):
-    # type: (str) -> Token
-    return Lexer(Source(s)).next_token()
-
-
-def test_repr_token():
-    # type: () -> None
-    token = lex_one("500")
-    assert repr(token) == "<Token kind=Int at 0..3 value='500'>"
-
-
-def test_disallows_uncommon_control_characters():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"\u0007")
-
-    assert (
-        u'Syntax Error GraphQL (1:1) Invalid character "\\u0007"'
-        in excinfo.value.message
-    )
-
-
-def test_accepts_bom_header():
-    # type: () -> None
-    assert lex_one(u"\uFEFF foo") == Token(TokenKind.NAME, 2, 5, u"foo")
-
-
-def test_skips_whitespace():
-    # type: () -> None
-    assert (
-        lex_one(
-            u"""
-
-    foo
-
-
-"""
-        )
-        == Token(TokenKind.NAME, 6, 9, "foo")
-    )
-
-    assert (
-        lex_one(
-            u"""
-    #comment
-    foo#comment
-"""
-        )
-        == Token(TokenKind.NAME, 18, 21, "foo")
-    )
-
-    assert lex_one(u""",,,foo,,,""") == Token(TokenKind.NAME, 3, 6, "foo")
-
-
-def test_errors_respect_whitespace():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(
-            u"""
-
-    ?
-
-
-"""
-        )
-    assert excinfo.value.message == (
-        u'Syntax Error GraphQL (3:5) Unexpected character "?".\n'
-        u"\n"
-        u"2: \n"
-        u"3:     ?\n"
-        u"       ^\n"
-        u"4: \n"
-    )
-
-
-def test_lexes_strings():
-    # type: () -> None
-    assert lex_one(u'"simple"') == Token(TokenKind.STRING, 0, 8, "simple")
-    assert lex_one(u'" white space "') == Token(
-        TokenKind.STRING, 0, 15, " white space "
-    )
-    assert lex_one(u'"quote \\""') == Token(TokenKind.STRING, 0, 10, 'quote "')
-    assert lex_one(u'"escaped \\n\\r\\b\\t\\f"') == Token(
-        TokenKind.STRING, 0, 20, "escaped \n\r\b\t\f"
-    )
-    assert lex_one(u'"slashes \\\\ \\/"') == Token(
-        TokenKind.STRING, 0, 15, "slashes \\ /"
-    )
-    assert lex_one(u'"unicode \\u1234\\u5678\\u90AB\\uCDEF"') == Token(
-        TokenKind.STRING, 0, 34, u"unicode \u1234\u5678\u90AB\uCDEF"
-    )
-
-
-def test_lex_reports_useful_string_errors():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"')
-    assert u"Syntax Error GraphQL (1:2) Unterminated string" in excinfo.value.message
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"no end quote')
-    assert u"Syntax Error GraphQL (1:14) Unterminated string" in excinfo.value.message
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"contains unescaped \u0007 control char"')
-    assert (
-        u'Syntax Error GraphQL (1:21) Invalid character within String: "\\u0007".'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"null-byte is not \u0000 end of file"')
-    assert (
-        u'Syntax Error GraphQL (1:19) Invalid character within String: "\\u0000".'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"multi\nline"')
-    assert u"Syntax Error GraphQL (1:7) Unterminated string" in excinfo.value.message
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"multi\rline"')
-    assert u"Syntax Error GraphQL (1:7) Unterminated string" in excinfo.value.message
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\z esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\z."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\x esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\x."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\u1 esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u1 es."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\u0XX1 esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u0XX1."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\uXXXX esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXX"
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\uFXXX esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uFXXX."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u'"bad \\uXXXF esc"')
-    assert (
-        u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXF."
-        in excinfo.value.message
-    )
-
-
-def test_lexes_numbers():
-    # type: () -> None
-    assert lex_one(u"4") == Token(TokenKind.INT, 0, 1, "4")
-    assert lex_one(u"4.123") == Token(TokenKind.FLOAT, 0, 5, "4.123")
-    assert lex_one(u"-4") == Token(TokenKind.INT, 0, 2, "-4")
-    assert lex_one(u"9") == Token(TokenKind.INT, 0, 1, "9")
-    assert lex_one(u"0") == Token(TokenKind.INT, 0, 1, "0")
-    assert lex_one(u"-4.123") == Token(TokenKind.FLOAT, 0, 6, "-4.123")
-    assert lex_one(u"0.123") == Token(TokenKind.FLOAT, 0, 5, "0.123")
-    assert lex_one(u"123e4") == Token(TokenKind.FLOAT, 0, 5, "123e4")
-    assert lex_one(u"123E4") == Token(TokenKind.FLOAT, 0, 5, "123E4")
-    assert lex_one(u"123e-4") == Token(TokenKind.FLOAT, 0, 6, "123e-4")
-    assert lex_one(u"123e+4") == Token(TokenKind.FLOAT, 0, 6, "123e+4")
-    assert lex_one(u"-1.123e4") == Token(TokenKind.FLOAT, 0, 8, "-1.123e4")
-    assert lex_one(u"-1.123E4") == Token(TokenKind.FLOAT, 0, 8, "-1.123E4")
-    assert lex_one(u"-1.123e-4") == Token(TokenKind.FLOAT, 0, 9, "-1.123e-4")
-    assert lex_one(u"-1.123e+4") == Token(TokenKind.FLOAT, 0, 9, "-1.123e+4")
-    assert lex_one(u"-1.123e4567") == Token(TokenKind.FLOAT, 0, 11, "-1.123e4567")
-
-
-def test_lex_reports_useful_number_errors():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"00")
-    assert (
-        u'Syntax Error GraphQL (1:2) Invalid number, unexpected digit after 0: "0".'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"+1")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character "+"' in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"1.")
-    assert (
-        u"Syntax Error GraphQL (1:3) Invalid number, expected digit but got: <EOF>."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u".123")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character ".".' in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"1.A")
-    assert (
-        u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "A".'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"-A")
-    assert (
-        u'Syntax Error GraphQL (1:2) Invalid number, expected digit but got: "A".'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"1.0e")
-    assert (
-        u"Syntax Error GraphQL (1:5) Invalid number, expected digit but got: <EOF>."
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"1.0eA")
-    assert (
-        u'Syntax Error GraphQL (1:5) Invalid number, expected digit but got: "A".'
-        in excinfo.value.message
-    )
-
-
-def test_lexes_punctuation():
-    # type: () -> None
-    assert lex_one(u"!") == Token(TokenKind.BANG, 0, 1)
-    assert lex_one(u"$") == Token(TokenKind.DOLLAR, 0, 1)
-    assert lex_one(u"(") == Token(TokenKind.PAREN_L, 0, 1)
-    assert lex_one(u")") == Token(TokenKind.PAREN_R, 0, 1)
-    assert lex_one(u"...") == Token(TokenKind.SPREAD, 0, 3)
-    assert lex_one(u":") == Token(TokenKind.COLON, 0, 1)
-    assert lex_one(u"=") == Token(TokenKind.EQUALS, 0, 1)
-    assert lex_one(u"@") == Token(TokenKind.AT, 0, 1)
-    assert lex_one(u"[") == Token(TokenKind.BRACKET_L, 0, 1)
-    assert lex_one(u"]") == Token(TokenKind.BRACKET_R, 0, 1)
-    assert lex_one(u"{") == Token(TokenKind.BRACE_L, 0, 1)
-    assert lex_one(u"|") == Token(TokenKind.PIPE, 0, 1)
-    assert lex_one(u"}") == Token(TokenKind.BRACE_R, 0, 1)
-
-
-def test_lex_reports_useful_unknown_character_error():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"..")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character "."' in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"?")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character "?"' in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"\u203B")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character "\\u203B"'
-        in excinfo.value.message
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        lex_one(u"\u200b")
-    assert (
-        u'Syntax Error GraphQL (1:1) Unexpected character "\\u200B"'
-        in excinfo.value.message
-    )
-
-
-def test_lex_reports_useful_information_for_dashes_in_names():
-    # type: () -> None
-    q = u"a-b"
-    lexer = Lexer(Source(q))
-    first_token = lexer.next_token()
-    assert first_token == Token(TokenKind.NAME, 0, 1, "a")
-    with raises(GraphQLSyntaxError) as excinfo:
-        lexer.next_token()
-
-    assert (
-        u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "b".'
-        in excinfo.value.message
-    )
diff --git a/graphql/language/tests/test_location.py b/graphql/language/tests/test_location.py
deleted file mode 100644
index 3562d53..0000000
--- a/graphql/language/tests/test_location.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from graphql.language.location import SourceLocation
-
-
-def test_repr_source_location():
-    # type: () -> None
-    loc = SourceLocation(10, 25)
-    assert repr(loc) == "SourceLocation(line=10, column=25)"
diff --git a/graphql/language/tests/test_parser.py b/graphql/language/tests/test_parser.py
deleted file mode 100644
index 6c9d5f4..0000000
--- a/graphql/language/tests/test_parser.py
+++ /dev/null
@@ -1,307 +0,0 @@
-from pytest import raises
-
-from graphql.error import GraphQLSyntaxError
-from graphql.language import ast
-from graphql.language.location import SourceLocation
-from graphql.language.parser import Loc, parse
-from graphql.language.source import Source
-
-from .fixtures import KITCHEN_SINK
-
-
-def test_repr_loc():
-    # type: () -> None
-    loc = Loc(start=10, end=25, source="foo")
-    assert repr(loc) == "<Loc start=10 end=25 source=foo>"
-
-
-def test_empty_parse():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("")
-    assert (
-        u"Syntax Error GraphQL (1:1) Unexpected EOF\n" u"\n"
-    ) == excinfo.value.message
-
-
-def test_parse_provides_useful_errors():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("""{""")
-    assert (
-        u"Syntax Error GraphQL (1:2) Expected Name, found EOF\n"
-        u"\n"
-        u"1: {\n"
-        u"    ^\n"
-        u""
-    ) == excinfo.value.message
-
-    assert excinfo.value.positions == [1]
-    assert excinfo.value.locations == [SourceLocation(line=1, column=2)]
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse(
-            """{ ...MissingOn }
-fragment MissingOn Type
-"""
-        )
-    assert 'Syntax Error GraphQL (2:20) Expected "on", found Name "Type"' in str(
-        excinfo.value
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("{ field: {} }")
-    assert "Syntax Error GraphQL (1:10) Expected Name, found {" in str(excinfo.value)
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("notanoperation Foo { field }")
-    assert 'Syntax Error GraphQL (1:1) Unexpected Name "notanoperation"' in str(
-        excinfo.value
-    )
-
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("...")
-    assert "Syntax Error GraphQL (1:1) Unexpected ..." in str(excinfo.value)
-
-
-def test_parse_provides_useful_error_when_using_source():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse(Source("query", "MyQuery.graphql"))
-    assert "Syntax Error MyQuery.graphql (1:6) Expected {, found EOF" in str(
-        excinfo.value
-    )
-
-
-def test_parses_variable_inline_values():
-    # type: () -> None
-    parse("{ field(complex: { a: { b: [ $var ] } }) }")
-
-
-def test_parses_constant_default_values():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("query Foo($x: Complex = { a: { b: [ $var ] } }) { field }")
-    assert "Syntax Error GraphQL (1:37) Unexpected $" in str(excinfo.value)
-
-
-def test_does_not_accept_fragments_named_on():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("fragment on on on { on }")
-
-    assert 'Syntax Error GraphQL (1:10) Unexpected Name "on"' in excinfo.value.message
-
-
-def test_does_not_accept_fragments_spread_of_on():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("{ ...on }")
-
-    assert "Syntax Error GraphQL (1:9) Expected Name, found }" in excinfo.value.message
-
-
-def test_does_not_allow_null_value():
-    # type: () -> None
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse("{ fieldWithNullableStringInput(input: null) }")
-
-    assert 'Syntax Error GraphQL (1:39) Unexpected Name "null"' in excinfo.value.message
-
-
-def test_parses_multi_byte_characters():
-    # type: () -> None
-    result = parse(
-        u"""
-        # This comment has a \u0A0A multi-byte character.
-        { field(arg: "Has a \u0A0A multi-byte character.") }
-    """,
-        no_location=True,
-        no_source=True,
-    )
-    assert result == ast.Document(
-        definitions=[
-            ast.OperationDefinition(
-                operation="query",
-                name=None,
-                variable_definitions=None,
-                directives=[],
-                selection_set=ast.SelectionSet(
-                    selections=[
-                        ast.Field(
-                            alias=None,
-                            name=ast.Name(value=u"field"),
-                            arguments=[
-                                ast.Argument(
-                                    name=ast.Name(value=u"arg"),
-                                    value=ast.StringValue(
-                                        value=u"Has a \u0a0a multi-byte character."
-                                    ),
-                                )
-                            ],
-                            directives=[],
-                            selection_set=None,
-                        )
-                    ]
-                ),
-            )
-        ]
-    )
-
-
-def tesst_allows_non_keywords_anywhere_a_name_is_allowed():
-    non_keywords = [
-        "on",
-        "fragment",
-        "query",
-        "mutation",
-        "subscription",
-        "true",
-        "false",
-    ]
-
-    query_template = """
-    query {keyword} {
-        ... {fragment_name}
-        ... on {keyword} { field }
-    }
-    fragment {fragment_name} on Type {
-        {keyword}({keyword}: ${keyword}) @{keyword}({keyword}: {keyword})
-    }
-    """
-
-    for keyword in non_keywords:
-        fragment_name = keyword
-        if keyword == "on":
-            fragment_name = "a"
-
-        parse(query_template.format(fragment_name=fragment_name, keyword=keyword))
-
-
-def test_parses_kitchen_sink():
-    # type: () -> None
-    parse(KITCHEN_SINK)
-
-
-def test_parses_anonymous_mutation_operations():
-    # type: () -> None
-    parse(
-        """
-        mutation {
-            mutationField
-        }
-    """
-    )
-
-
-def test_parses_anonymous_subscription_operations():
-    # type: () -> None
-    parse(
-        """
-        subscription {
-            mutationField
-        }
-    """
-    )
-
-
-def test_parses_named_mutation_operations():
-    # type: () -> None
-    parse(
-        """
-        mutation Foo {
-            mutationField
-        }
-    """
-    )
-
-
-def test_parses_named_subscription_operations():
-    # type: () -> None
-    parse(
-        """
-        subscription Foo {
-            subscriptionField
-        }
-    """
-    )
-
-
-def test_parse_creates_ast():
-    # type: () -> None
-    source = Source(
-        """{
-  node(id: 4) {
-    id,
-    name
-  }
-}
-"""
-    )
-    result = parse(source)
-
-    assert result == ast.Document(
-        loc=Loc(start=0, end=41, source=source),
-        definitions=[
-            ast.OperationDefinition(
-                loc=Loc(start=0, end=40, source=source),
-                operation="query",
-                name=None,
-                variable_definitions=None,
-                directives=[],
-                selection_set=ast.SelectionSet(
-                    loc=Loc(start=0, end=40, source=source),
-                    selections=[
-                        ast.Field(
-                            loc=Loc(start=4, end=38, source=source),
-                            alias=None,
-                            name=ast.Name(
-                                loc=Loc(start=4, end=8, source=source), value="node"
-                            ),
-                            arguments=[
-                                ast.Argument(
-                                    name=ast.Name(
-                                        loc=Loc(start=9, end=11, source=source),
-                                        value="id",
-                                    ),
-                                    value=ast.IntValue(
-                                        loc=Loc(start=13, end=14, source=source),
-                                        value="4",
-                                    ),
-                                    loc=Loc(start=9, end=14, source=source),
-                                )
-                            ],
-                            directives=[],
-                            selection_set=ast.SelectionSet(
-                                loc=Loc(start=16, end=38, source=source),
-                                selections=[
-                                    ast.Field(
-                                        loc=Loc(start=22, end=24, source=source),
-                                        alias=None,
-                                        name=ast.Name(
-                                            loc=Loc(start=22, end=24, source=source),
-                                            value="id",
-                                        ),
-                                        arguments=[],
-                                        directives=[],
-                                        selection_set=None,
-                                    ),
-                                    ast.Field(
-                                        loc=Loc(start=30, end=34, source=source),
-                                        alias=None,
-                                        name=ast.Name(
-                                            loc=Loc(start=30, end=34, source=source),
-                                            value="name",
-                                        ),
-                                        arguments=[],
-                                        directives=[],
-                                        selection_set=None,
-                                    ),
-                                ],
-                            ),
-                        )
-                    ],
-                ),
-            )
-        ],
-    )
diff --git a/graphql/language/tests/test_printer.py b/graphql/language/tests/test_printer.py
deleted file mode 100644
index 470991d..0000000
--- a/graphql/language/tests/test_printer.py
+++ /dev/null
@@ -1,145 +0,0 @@
-import copy
-
-from pytest import raises
-
-from graphql.language.ast import Field, Name
-from graphql.language.parser import parse
-from graphql.language.printer import print_ast
-
-from .fixtures import KITCHEN_SINK
-
-
-def test_does_not_alter_ast():
-    # type: () -> None
-    ast = parse(KITCHEN_SINK)
-    ast_copy = copy.deepcopy(ast)
-    print_ast(ast)
-    assert ast == ast_copy
-
-
-def test_prints_minimal_ast():
-    # type: () -> None
-    ast = Field(name=Name(loc=None, value="foo"))
-    assert print_ast(ast) == "foo"
-
-
-def test_produces_helpful_error_messages():
-    # type: () -> None
-    bad_ast = {"random": "Data"}
-    with raises(Exception) as excinfo:
-        print_ast(bad_ast)
-    assert "Invalid AST Node" in str(excinfo.value)
-
-
-def test_correctly_prints_query_operation_without_name():
-    # type: () -> None
-    query_ast_shorthanded = parse("query { id, name }")
-    assert (
-        print_ast(query_ast_shorthanded)
-        == """{
-  id
-  name
-}
-"""
-    )
-
-
-def test_correctly_prints_mutation_operation_without_name():
-    # type: () -> None
-    mutation_ast = parse("mutation { id, name }")
-    assert (
-        print_ast(mutation_ast)
-        == """mutation {
-  id
-  name
-}
-"""
-    )
-
-
-def test_correctly_prints_query_with_artifacts():
-    # type: () -> None
-    query_ast_shorthanded = parse("query ($foo: TestType) @testDirective { id, name }")
-    assert (
-        print_ast(query_ast_shorthanded)
-        == """query ($foo: TestType) @testDirective {
-  id
-  name
-}
-"""
-    )
-
-
-def test_correctly_prints_mutation_with_artifacts():
-    # type: () -> None
-    query_ast_shorthanded = parse(
-        "mutation ($foo: TestType) @testDirective { id, name }"
-    )
-    assert (
-        print_ast(query_ast_shorthanded)
-        == """mutation ($foo: TestType) @testDirective {
-  id
-  name
-}
-"""
-    )
-
-
-def test_prints_kitchen_sink():
-    # type: () -> None
-    ast = parse(KITCHEN_SINK)
-    printed = print_ast(ast)
-    assert (
-        printed
-        == """query queryName($foo: ComplexType, $site: Site = MOBILE) {
-  whoever123is: node(id: [123, 456]) {
-    id
-    ... on User @defer {
-      field2 {
-        id
-        alias: field1(first: 10, after: $foo) @include(if: $foo) {
-          id
-          ...frag
-        }
-      }
-    }
-    ... @skip(unless: $foo) {
-      id
-    }
-    ... {
-      id
-    }
-  }
-}
-
-mutation likeStory {
-  like(story: 123) @defer {
-    story {
-      id
-    }
-  }
-}
-
-subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
-  storyLikeSubscribe(input: $input) {
-    story {
-      likers {
-        count
-      }
-      likeSentence {
-        text
-      }
-    }
-  }
-}
-
-fragment frag on Friend {
-  foo(size: $size, bar: $b, obj: {key: "value"})
-}
-
-{
-  unnamed(truthy: true, falsey: false)
-  query
-}
-"""
-    )
diff --git a/graphql/language/tests/test_schema_parser.py b/graphql/language/tests/test_schema_parser.py
deleted file mode 100644
index 6ec58d4..0000000
--- a/graphql/language/tests/test_schema_parser.py
+++ /dev/null
@@ -1,580 +0,0 @@
-from pytest import raises
-
-from graphql import Source, parse
-from graphql.error import GraphQLSyntaxError
-from graphql.language import ast
-from graphql.language.parser import Loc
-from typing import Callable
-
-
-def create_loc_fn(body):
-    # type: (str) -> Callable
-    source = Source(body)
-    return lambda start, end: Loc(start, end, source)
-
-
-def test_parses_simple_type():
-    # type: () -> None
-    body = """
-type Hello {
-  world: String
-}"""
-
-    doc = parse(body)
-    loc = create_loc_fn(body)
-
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(23, 29)),
-                            loc=loc(23, 29),
-                        ),
-                        directives=[],
-                        loc=loc(16, 29),
-                    )
-                ],
-                loc=loc(1, 31),
-            )
-        ],
-        loc=loc(1, 31),
-    )
-    assert doc == expected
-
-
-def test_parses_simple_extension():
-    # type: () -> None
-    body = """
-extend type Hello {
-  world: String
-}"""
-    doc = parse(body)
-    loc = create_loc_fn(body)
-
-    expected = ast.Document(
-        definitions=[
-            ast.TypeExtensionDefinition(
-                definition=ast.ObjectTypeDefinition(
-                    name=ast.Name(value="Hello", loc=loc(13, 18)),
-                    interfaces=[],
-                    directives=[],
-                    fields=[
-                        ast.FieldDefinition(
-                            name=ast.Name(value="world", loc=loc(23, 28)),
-                            arguments=[],
-                            type=ast.NamedType(
-                                name=ast.Name(value="String", loc=loc(30, 36)),
-                                loc=loc(30, 36),
-                            ),
-                            directives=[],
-                            loc=loc(23, 36),
-                        )
-                    ],
-                    loc=loc(8, 38),
-                ),
-                loc=loc(1, 38),
-            )
-        ],
-        loc=loc(1, 38),
-    )
-
-    assert doc == expected
-
-
-def test_simple_non_null_type():
-    # type: () -> None
-    body = """
-type Hello {
-  world: String!
-}"""
-
-    doc = parse(body)
-    loc = create_loc_fn(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[],
-                        type=ast.NonNullType(
-                            type=ast.NamedType(
-                                name=ast.Name(value="String", loc=loc(23, 29)),
-                                loc=loc(23, 29),
-                            ),
-                            loc=loc(23, 30),
-                        ),
-                        directives=[],
-                        loc=loc(16, 30),
-                    )
-                ],
-                loc=loc(1, 32),
-            )
-        ],
-        loc=loc(1, 32),
-    )
-    assert doc == expected
-
-
-def test_parses_simple_type_inheriting_interface():
-    # type: () -> None
-    body = "type Hello implements World { }"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(5, 10)),
-                interfaces=[
-                    ast.NamedType(
-                        name=ast.Name(value="World", loc=loc(22, 27)), loc=loc(22, 27)
-                    )
-                ],
-                directives=[],
-                fields=[],
-                loc=loc(0, 31),
-            )
-        ],
-        loc=loc(0, 31),
-    )
-
-    assert doc == expected
-
-
-def test_parses_simple_type_inheriting_multiple_interfaces():
-    # type: () -> None
-    body = "type Hello implements Wo, rld { }"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(5, 10)),
-                interfaces=[
-                    ast.NamedType(
-                        name=ast.Name(value="Wo", loc=loc(22, 24)), loc=loc(22, 24)
-                    ),
-                    ast.NamedType(
-                        name=ast.Name(value="rld", loc=loc(26, 29)), loc=loc(26, 29)
-                    ),
-                ],
-                directives=[],
-                fields=[],
-                loc=loc(0, 33),
-            )
-        ],
-        loc=loc(0, 33),
-    )
-    assert doc == expected
-
-
-def test_parses_single_value_enum():
-    # type: () -> None
-    body = "enum Hello { WORLD }"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.EnumTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(5, 10)),
-                directives=[],
-                values=[
-                    ast.EnumValueDefinition(
-                        name=ast.Name(value="WORLD", loc=loc(13, 18)),
-                        directives=[],
-                        loc=loc(13, 18),
-                    )
-                ],
-                loc=loc(0, 20),
-            )
-        ],
-        loc=loc(0, 20),
-    )
-
-    assert doc == expected
-
-
-def test_parses_double_value_enum():
-    # type: () -> None
-    body = "enum Hello { WO, RLD }"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.EnumTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(5, 10)),
-                directives=[],
-                values=[
-                    ast.EnumValueDefinition(
-                        name=ast.Name(value="WO", loc=loc(13, 15)),
-                        directives=[],
-                        loc=loc(13, 15),
-                    ),
-                    ast.EnumValueDefinition(
-                        name=ast.Name(value="RLD", loc=loc(17, 20)),
-                        directives=[],
-                        loc=loc(17, 20),
-                    ),
-                ],
-                loc=loc(0, 22),
-            )
-        ],
-        loc=loc(0, 22),
-    )
-
-    assert doc == expected
-
-
-def test_parses_simple_interface():
-    # type: () -> None
-    body = """
-interface Hello {
-  world: String
-}
-"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.InterfaceTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(11, 16)),
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(21, 26)),
-                        arguments=[],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(28, 34)),
-                            loc=loc(28, 34),
-                        ),
-                        directives=[],
-                        loc=loc(21, 34),
-                    )
-                ],
-                loc=loc(1, 36),
-            )
-        ],
-        loc=loc(1, 37),
-    )
-
-    assert doc == expected
-
-
-def test_parses_simple_field_with_arg():
-    # type: () -> None
-    body = """
-type Hello {
-  world(flag: Boolean): String
-}"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[
-                            ast.InputValueDefinition(
-                                name=ast.Name(value="flag", loc=loc(22, 26)),
-                                type=ast.NamedType(
-                                    name=ast.Name(value="Boolean", loc=loc(28, 35)),
-                                    loc=loc(28, 35),
-                                ),
-                                default_value=None,
-                                directives=[],
-                                loc=loc(22, 35),
-                            )
-                        ],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(38, 44)),
-                            loc=loc(38, 44),
-                        ),
-                        directives=[],
-                        loc=loc(16, 44),
-                    )
-                ],
-                loc=loc(1, 46),
-            )
-        ],
-        loc=loc(1, 46),
-    )
-
-    assert doc == expected
-
-
-def test_parses_simple_field_with_arg_with_default_value():
-    # type: () -> None
-    body = """
-type Hello {
-  world(flag: Boolean = true): String
-}"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[
-                            ast.InputValueDefinition(
-                                name=ast.Name(value="flag", loc=loc(22, 26)),
-                                type=ast.NamedType(
-                                    name=ast.Name(value="Boolean", loc=loc(28, 35)),
-                                    loc=loc(28, 35),
-                                ),
-                                default_value=ast.BooleanValue(
-                                    value=True, loc=loc(38, 42)
-                                ),
-                                directives=[],
-                                loc=loc(22, 42),
-                            )
-                        ],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(45, 51)),
-                            loc=loc(45, 51),
-                        ),
-                        directives=[],
-                        loc=loc(16, 51),
-                    )
-                ],
-                loc=loc(1, 53),
-            )
-        ],
-        loc=loc(1, 53),
-    )
-
-    assert doc == expected
-
-
-def test_parses_simple_field_with_list_arg():
-    # type: () -> None
-    body = """
-type Hello {
-  world(things: [String]): String
-}"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[
-                            ast.InputValueDefinition(
-                                name=ast.Name(value="things", loc=loc(22, 28)),
-                                type=ast.ListType(
-                                    type=ast.NamedType(
-                                        name=ast.Name(value="String", loc=loc(31, 37)),
-                                        loc=loc(31, 37),
-                                    ),
-                                    loc=loc(30, 38),
-                                ),
-                                default_value=None,
-                                directives=[],
-                                loc=loc(22, 38),
-                            )
-                        ],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(41, 47)),
-                            loc=loc(41, 47),
-                        ),
-                        directives=[],
-                        loc=loc(16, 47),
-                    )
-                ],
-                loc=loc(1, 49),
-            )
-        ],
-        loc=loc(1, 49),
-    )
-    assert doc == expected
-
-
-def test_parses_simple_field_with_two_args():
-    # type: () -> None
-    body = """
-type Hello {
-  world(argOne: Boolean, argTwo: Int): String
-}"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                interfaces=[],
-                directives=[],
-                fields=[
-                    ast.FieldDefinition(
-                        name=ast.Name(value="world", loc=loc(16, 21)),
-                        arguments=[
-                            ast.InputValueDefinition(
-                                name=ast.Name(value="argOne", loc=loc(22, 28)),
-                                type=ast.NamedType(
-                                    name=ast.Name(value="Boolean", loc=loc(30, 37)),
-                                    loc=loc(30, 37),
-                                ),
-                                default_value=None,
-                                directives=[],
-                                loc=loc(22, 37),
-                            ),
-                            ast.InputValueDefinition(
-                                name=ast.Name(value="argTwo", loc=loc(39, 45)),
-                                type=ast.NamedType(
-                                    name=ast.Name(value="Int", loc=loc(47, 50)),
-                                    loc=loc(47, 50),
-                                ),
-                                default_value=None,
-                                directives=[],
-                                loc=loc(39, 50),
-                            ),
-                        ],
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(53, 59)),
-                            loc=loc(53, 59),
-                        ),
-                        directives=[],
-                        loc=loc(16, 59),
-                    )
-                ],
-                loc=loc(1, 61),
-            )
-        ],
-        loc=loc(1, 61),
-    )
-    assert doc == expected
-
-
-def test_parses_simple_union():
-    # type: () -> None
-    body = "union Hello = World"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.UnionTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                directives=[],
-                types=[
-                    ast.NamedType(
-                        name=ast.Name(value="World", loc=loc(14, 19)), loc=loc(14, 19)
-                    )
-                ],
-                loc=loc(0, 19),
-            )
-        ],
-        loc=loc(0, 19),
-    )
-    assert doc == expected
-
-
-def test_parses_union_with_two_types():
-    # type: () -> None
-    body = "union Hello = Wo | Rld"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.UnionTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(6, 11)),
-                directives=[],
-                types=[
-                    ast.NamedType(
-                        name=ast.Name(value="Wo", loc=loc(14, 16)), loc=loc(14, 16)
-                    ),
-                    ast.NamedType(
-                        name=ast.Name(value="Rld", loc=loc(19, 22)), loc=loc(19, 22)
-                    ),
-                ],
-                loc=loc(0, 22),
-            )
-        ],
-        loc=loc(0, 22),
-    )
-    assert doc == expected
-
-
-def test_parses_scalar():
-    # type: () -> None
-    body = "scalar Hello"
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.ScalarTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(7, 12)),
-                directives=[],
-                loc=loc(0, 12),
-            )
-        ],
-        loc=loc(0, 12),
-    )
-    assert doc == expected
-
-
-def test_parses_simple_input_object():
-    # type: () -> None
-    body = """
-input Hello {
-  world: String
-}"""
-    loc = create_loc_fn(body)
-    doc = parse(body)
-    expected = ast.Document(
-        definitions=[
-            ast.InputObjectTypeDefinition(
-                name=ast.Name(value="Hello", loc=loc(7, 12)),
-                directives=[],
-                fields=[
-                    ast.InputValueDefinition(
-                        name=ast.Name(value="world", loc=loc(17, 22)),
-                        type=ast.NamedType(
-                            name=ast.Name(value="String", loc=loc(24, 30)),
-                            loc=loc(24, 30),
-                        ),
-                        default_value=None,
-                        directives=[],
-                        loc=loc(17, 30),
-                    )
-                ],
-                loc=loc(1, 32),
-            )
-        ],
-        loc=loc(1, 32),
-    )
-    assert doc == expected
-
-
-def test_parsing_simple_input_object_with_args_should_fail():
-    # type: () -> None
-    body = """
-input Hello {
-  world(foo: Int): String
-}
-"""
-    with raises(GraphQLSyntaxError) as excinfo:
-        parse(body)
-
-    assert "Syntax Error GraphQL (3:8) Expected :, found (" in excinfo.value.message
diff --git a/graphql/language/tests/test_schema_printer.py b/graphql/language/tests/test_schema_printer.py
deleted file mode 100644
index afa979c..0000000
--- a/graphql/language/tests/test_schema_printer.py
+++ /dev/null
@@ -1,108 +0,0 @@
-from copy import deepcopy
-
-from pytest import raises
-
-from graphql import parse
-from graphql.language import ast
-from graphql.language.printer import print_ast
-
-from .fixtures import SCHEMA_KITCHEN_SINK
-
-
-def test_prints_minimal_ast():
-    # type: () -> None
-    node = ast.ScalarTypeDefinition(name=ast.Name("foo"))
-
-    assert print_ast(node) == "scalar foo"
-
-
-def test_print_produces_helpful_error_messages():
-    # type: () -> None
-    bad_ast = {"random": "Data"}
-    with raises(AssertionError) as excinfo:
-        print_ast(bad_ast)
-
-    assert "Invalid AST Node: {'random': 'Data'}" in str(excinfo.value)
-
-
-def test_does_not_alter_ast():
-    # type: () -> None
-    ast = parse(SCHEMA_KITCHEN_SINK)
-    ast_copy = deepcopy(ast)
-    print_ast(ast)
-    assert ast == ast_copy
-
-
-def test_prints_kitchen_sink():
-    # type: () -> None
-    ast = parse(SCHEMA_KITCHEN_SINK)
-    printed = print_ast(ast)
-
-    expected = """schema {
-  query: QueryType
-  mutation: MutationType
-}
-
-type Foo implements Bar {
-  one: Type
-  two(argument: InputType!): Type
-  three(argument: InputType, other: String): Int
-  four(argument: String = "string"): String
-  five(argument: [String] = ["string", "string"]): String
-  six(argument: InputType = {key: "value"}): Type
-}
-
-type AnnotatedObject @onObject(arg: "value") {
-  annotatedField(arg: Type = "default" @onArg): Type @onField
-}
-
-interface Bar {
-  one: Type
-  four(argument: String = "string"): String
-}
-
-interface AnnotatedInterface @onInterface {
-  annotatedField(arg: Type @onArg): Type @onField
-}
-
-union Feed = Story | Article | Advert
-
-union AnnotatedUnion @onUnion = A | B
-
-scalar CustomScalar
-
-scalar AnnotatedScalar @onScalar
-
-enum Site {
-  DESKTOP
-  MOBILE
-}
-
-enum AnnotatedEnum @onEnum {
-  ANNOTATED_VALUE @onEnumValue
-  OTHER_VALUE
-}
-
-input InputType {
-  key: String!
-  answer: Int = 42
-}
-
-input AnnotatedInput @onInputObjectType {
-  annotatedField: Type @onField
-}
-
-extend type Foo {
-  seven(argument: [String]): Type
-}
-
-extend type Foo @onType {}
-
-type NoFields {}
-
-directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
-
-directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
-"""
-
-    assert printed == expected
diff --git a/graphql/language/tests/test_visitor.py b/graphql/language/tests/test_visitor.py
deleted file mode 100644
index 1392fe3..0000000
--- a/graphql/language/tests/test_visitor.py
+++ /dev/null
@@ -1,1197 +0,0 @@
-from graphql.language.ast import (
-    Document,
-    Field,
-    Name,
-    OperationDefinition,
-    SelectionSet,
-)
-from graphql.language.parser import parse
-from graphql.language.printer import print_ast
-from graphql.language.visitor import (
-    BREAK,
-    REMOVE,
-    ParallelVisitor,
-    TypeInfoVisitor,
-    Visitor,
-    visit,
-)
-from graphql.type import get_named_type, is_composite_type
-from graphql.utils.type_info import TypeInfo
-
-from ...validation.tests.utils import test_schema
-from .fixtures import KITCHEN_SINK
-from graphql.language.ast import Document
-from graphql.language.ast import OperationDefinition
-from graphql.language.ast import SelectionSet
-from typing import Any
-from typing import Optional
-from typing import Union
-from graphql.language.ast import Field
-from graphql.language.ast import Name
-from graphql.language.visitor import _Falsey
-from typing import List
-from graphql.language.ast import Argument
-from graphql.language.ast import IntValue
-
-
-def test_allows_editing_a_node_both_on_enter_and_on_leave():
-    # type: () -> None
-    ast = parse("{ a, b, c { a, b, c } }", no_location=True)
-
-    class TestVisitor(Visitor):
-        def __init__(self):
-            # type: () -> None
-            self.did_enter = False
-            self.did_leave = False
-
-        def enter(
-            self,
-            node,  # type: Union[Document, OperationDefinition, SelectionSet]
-            *args  # type: Any
-        ):
-            # type: (...) -> Optional[OperationDefinition]
-            if isinstance(node, OperationDefinition):
-                self.did_enter = True
-                selection_set = node.selection_set
-                self.selections = None
-                if selection_set:
-                    self.selections = selection_set.selections
-                new_selection_set = SelectionSet(selections=[])
-                return OperationDefinition(
-                    name=node.name,
-                    variable_definitions=node.variable_definitions,
-                    directives=node.directives,
-                    loc=node.loc,
-                    operation=node.operation,
-                    selection_set=new_selection_set,
-                )
-
-        def leave(
-            self,
-            node,  # type: Union[Document, OperationDefinition, SelectionSet]
-            *args  # type: Any
-        ):
-            # type: (...) -> Optional[OperationDefinition]
-            if isinstance(node, OperationDefinition):
-                self.did_leave = True
-                new_selection_set = None
-                if self.selections:
-                    new_selection_set = SelectionSet(selections=self.selections)
-                return OperationDefinition(
-                    name=node.name,
-                    variable_definitions=node.variable_definitions,
-                    directives=node.directives,
-                    loc=node.loc,
-                    operation=node.operation,
-                    selection_set=new_selection_set,
-                )
-
-    visitor = TestVisitor()
-    edited_ast = visit(ast, visitor)
-    assert ast == parse("{ a, b, c { a, b, c } }", no_location=True)
-    assert edited_ast == ast
-    assert visitor.did_enter
-    assert visitor.did_leave
-
-
-def test_allows_editing_the_root_node_on_enter_and_on_leave():
-    # type: () -> None
-    ast = parse("{ a, b, c { a, b, c } }", no_location=True)
-
-    definitions = ast.definitions
-
-    class TestVisitor(Visitor):
-        def __init__(self):
-            # type: () -> None
-            self.did_enter = False
-            self.did_leave = False
-
-        def enter(self, node, *args):
-            # type: (Document, *Any) -> Document
-            if isinstance(node, Document):
-                self.did_enter = True
-                return Document(loc=node.loc, definitions=[])
-
-        def leave(self, node, *args):
-            # type: (Document, *Any) -> Document
-            if isinstance(node, Document):
-                self.did_leave = True
-                return Document(loc=node.loc, definitions=definitions)
-
-    visitor = TestVisitor()
-    edited_ast = visit(ast, visitor)
-    assert edited_ast == ast
-    assert visitor.did_enter
-    assert visitor.did_leave
-
-
-def test_allows_for_editing_on_enter():
-    # type: () -> None
-    ast = parse("{ a, b, c { a, b, c } }", no_location=True)
-
-    class TestVisitor(Visitor):
-        def enter(self, node, *args):
-            # type: (Any, *Any) -> Optional[Any]
-            if isinstance(node, Field) and node.name.value == "b":
-                return REMOVE
-
-    edited_ast = visit(ast, TestVisitor())
-
-    assert ast == parse("{ a, b, c { a, b, c } }", no_location=True)
-    assert edited_ast == parse("{ a,   c { a,   c } }", no_location=True)
-
-
-def test_allows_for_editing_on_leave():
-    # type: () -> None
-    ast = parse("{ a, b, c { a, b, c } }", no_location=True)
-
-    class TestVisitor(Visitor):
-        def leave(self, node, *args):
-            # type: (Union[Field, Name], *Any) -> Optional[Falsey]
-            if isinstance(node, Field) and node.name.value == "b":
-                return REMOVE
-
-    edited_ast = visit(ast, TestVisitor())
-
-    assert ast == parse("{ a, b, c { a, b, c } }", no_location=True)
-    assert edited_ast == parse("{ a,   c { a,   c } }", no_location=True)
-
-
-def test_visits_edited_node():
-    # type: () -> None
-    added_field = Field(name=Name(value="__typename"))
-    ast = parse("{ a { x } }")
-
-    class TestVisitor(Visitor):
-        def __init__(self):
-            # type: () -> None
-            self.did_visit_added_field = False
-
-        def enter(self, node, *args):
-            # type: (Any, *Any) -> Optional[Field]
-            if isinstance(node, Field) and node.name.value == "a":
-                selection_set = node.selection_set
-                selections = []
-                if selection_set:
-                    selections = selection_set.selections
-                new_selection_set = SelectionSet(selections=[added_field] + selections)
-                return Field(name=None, selection_set=new_selection_set)
-            if node is added_field:
-                self.did_visit_added_field = True
-
-    visitor = TestVisitor()
-    visit(ast, visitor)
-    assert visitor.did_visit_added_field
-
-
-def test_allows_skipping_a_subtree():
-    # type: () -> None
-    visited = []
-    ast = parse("{ a, b { x }, c }")
-
-    class TestVisitor(Visitor):
-        def enter(self, node, *args):
-            # type: (Any, *Any) -> Optional[Any]
-            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
-            if isinstance(node, Field) and node.name.value == "b":
-                return False
-
-        def leave(self, node, *args):
-            # type: (Union[Field, Name, SelectionSet], *Any) -> None
-            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])
-
-    visit(ast, TestVisitor())
-
-    assert visited == [
-        ["enter", "Document", None],
-        ["enter", "OperationDefinition", None],
-        ["enter", "SelectionSet", None],
-        ["enter", "Field", None],
-        ["enter", "Name", "a"],
-        ["leave", "Name", "a"],
-        ["leave", "Field", None],
-        ["enter", "Field", None],
-        ["enter", "Field", None],
-        ["enter", "Name", "c"],
-        ["leave", "Name", "c"],
-        ["leave", "Field", None],
-        ["leave", "SelectionSet", None],
-        ["leave", "OperationDefinition", None],
-        ["leave", "Document", None],
-    ]
-
-
-def test_allows_early_exit_while_visiting():
-    # type: () -> None
-    visited = []
-    ast = parse("{ a, b { x }, c }")
-
-    class TestVisitor(Visitor):
-        def enter(self, node, *args):
-            # type: (Any, *Any) -> Optional[Any]
-            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
-            if isinstance(node, Name) and node.value == "x":
-                return BREAK
-
-        def leave(self, node, *args):
-            # type: (Union[Field, Name], *Any) -> None
-            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])
-
-    visit(ast, TestVisitor())
-
-    assert visited == [
-        ["enter", "Document", None],
-        ["enter", "OperationDefinition", None],
-        ["enter", "SelectionSet", None],
-        ["enter", "Field", None],
-        ["enter", "Name", "a"],
-        ["leave", "Name", "a"],
-        ["leave", "Field", None],
-        ["enter", "Field", None],
-        ["enter", "Name", "b"],
-        ["leave", "Name", "b"],
-        ["enter", "SelectionSet", None],
-        ["enter", "Field", None],
-        ["enter", "Name", "x"],
-    ]
-
-
-def test_allows_a_named_functions_visitor_api():
-    # type: () -> None
-    visited = []
-    ast = parse("{ a, b { x }, c }")
-
-    class TestVisitor(Visitor):
-        def enter_Name(self, node, *args):
-            # type: (Name, *Any) -> None
-            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
-
-        def enter_SelectionSet(self, node, *args):
-            # type: (SelectionSet, *Any) -> None
-            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
-
-        def leave_SelectionSet(self, node, *args):
-            # type: (SelectionSet, *Any) -> None
-            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])
-
-    visit(ast, TestVisitor())
-
-    assert visited == [
-        ["enter", "SelectionSet", None],
-        ["enter", "Name", "a"],
-        ["enter", "Name", "b"],
-        ["enter", "SelectionSet", None],
-        ["enter", "Name", "x"],
-        ["leave", "SelectionSet", None],
-        ["enter", "Name", "c"],
-        ["leave", "SelectionSet", None],
-    ]
-
-
-def test_visits_kitchen_sink():
-    # type: () -> None
-    visited = []
-    ast = parse(KITCHEN_SINK)
-
-    class TestVisitor(Visitor):
-        def enter(self, node, key, parent, *args):
-            # type: (Any, Union[None, int, str], Any, *List[Any]) -> None
-            kind = parent and type(parent).__name__
-            if kind == "list":
-                kind = None
-            visited.append(["enter", type(node).__name__, key, kind])
-
-        def leave(self, node, key, parent, *args):
-            # type: (Any, Union[int, str], Any, *List[Any]) -> None
-            kind = parent and type(parent).__name__
-            if kind == "list":
-                kind = None
-            visited.append(["leave", type(node).__name__, key, kind])
-
-    visit(ast, TestVisitor())
-    assert visited == [
-        ["enter", "Document", None, None],
-        ["enter", "OperationDefinition", 0, None],
-        ["enter", "Name", "name", "OperationDefinition"],
-        ["leave", "Name", "name", "OperationDefinition"],
-        ["enter", "VariableDefinition", 0, None],
-        ["enter", "Variable", "variable", "VariableDefinition"],
-        ["enter", "Name", "name", "Variable"],
-        ["leave", "Name", "name", "Variable"],
-        ["leave", "Variable", "variable", "VariableDefinition"],
-        ["enter", "NamedType", "type", "VariableDefinition"],
-        ["enter", "Name", "name", "NamedType"],
-        ["leave", "Name", "name", "NamedType"],