Skip to content

Commit

Permalink
πŸ”₯ Remove GraphQL support (#1198)
Browse files Browse the repository at this point in the history
* πŸ”₯ Remove GraphQL support

* Remove graphene dependency and add docs

* Update docs/graphql.md

Co-authored-by: Jamie Hewland <[email protected]>

* Update docs/graphql.md

Co-authored-by: Jamie Hewland <[email protected]>

* Remove aiofiles warning on setup.cfg

Co-authored-by: Jamie Hewland <[email protected]>
  • Loading branch information
Kludex and JayH5 authored Oct 3, 2021
1 parent 6c556f6 commit 2808857
Show file tree
Hide file tree
Showing 10 changed files with 6 additions and 556 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ It is production-ready, and gives you the following:

* Seriously impressive performance.
* WebSocket support.
* GraphQL support.
* In-process background tasks.
* Startup and shutdown events.
* Test client built on `requests`.
Expand Down Expand Up @@ -92,7 +91,6 @@ Starlette only requires `anyio`, and the following are optional:
* [`python-multipart`][python-multipart] - Required if you want to support form parsing, with `request.form()`.
* [`itsdangerous`][itsdangerous] - Required for `SessionMiddleware` support.
* [`pyyaml`][pyyaml] - Required for `SchemaGenerator` support.
* [`graphene`][graphene] - Required for `GraphQLApp` support.

You can install all of these with `pip3 install starlette[full]`.

Expand Down Expand Up @@ -169,7 +167,6 @@ gunicorn -k uvicorn.workers.UvicornH11Worker ...
[requests]: http://docs.python-requests.org/en/master/
[jinja2]: http://jinja.pocoo.org/
[python-multipart]: https://andrew-d.github.io/python-multipart/
[graphene]: https://graphene-python.org/
[itsdangerous]: https://pythonhosted.org/itsdangerous/
[sqlalchemy]: https://www.sqlalchemy.org
[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation
119 changes: 6 additions & 113 deletions docs/graphql.md
Original file line number Diff line number Diff line change
@@ -1,116 +1,9 @@
GraphQL support in Starlette was deprecated in version 0.15.0, and removed in version 0.17.0.

!!! Warning
Although GraphQL support is no longer built in to Starlette, you can still use GraphQL with Starlette via 3rd party libraries. These libraries all have Starlette-specific guides to help you do just that:

GraphQL support in Starlette is **deprecated** as of version 0.15 and will
be removed in a future release. It is also incompatible with Python 3.10+.
Please consider using a third-party library to provide GraphQL support. This
is usually done by mounting a GraphQL ASGI application.
See [#619](https://github.com/encode/starlette/issues/619).
Some example libraries are:
- [Ariadne](https://ariadnegraphql.org/docs/starlette-integration.html)
- [`starlette-graphene3`](https://github.com/ciscorn/starlette-graphene3#example)
- [Strawberry](https://strawberry.rocks/docs/integrations/starlette)
- [`tartiflette-asgi`](https://tartiflette.github.io/tartiflette-asgi/usage/#starlette)

* [Ariadne](https://ariadnegraphql.org/docs/asgi)
* [`tartiflette-asgi`](https://tartiflette.github.io/tartiflette-asgi/)
* [Strawberry](https://strawberry.rocks/docs/integrations/asgi)
* [`starlette-graphene3`](https://github.com/ciscorn/starlette-graphene3)

Starlette includes optional support for GraphQL, using the `graphene` library.

Here's an example of integrating the support into your application.

```python
from starlette.applications import Starlette
from starlette.routing import Route
from starlette.graphql import GraphQLApp
import graphene


class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.String(default_value="stranger"))

def resolve_hello(self, info, name):
return "Hello " + name

routes = [
Route('/', GraphQLApp(schema=graphene.Schema(query=Query)))
]

app = Starlette(routes=routes)
```

If you load up the page in a browser, you'll be served the GraphiQL tool,
which you can use to interact with your GraphQL API.


![GraphiQL](img/graphiql.png)

## Accessing request information

The current request is available in the context.

```python
class Query(graphene.ObjectType):
user_agent = graphene.String()

def resolve_user_agent(self, info):
"""
Return the User-Agent of the incoming request.
"""
request = info.context["request"]
return request.headers.get("User-Agent", "<unknown>")
```

## Adding background tasks

You can add background tasks to run once the response has been sent.

```python
class Query(graphene.ObjectType):
user_agent = graphene.String()

def resolve_user_agent(self, info):
"""
Return the User-Agent of the incoming request.
"""
user_agent = request.headers.get("User-Agent", "<unknown>")
background = info.context["background"]
background.add_task(log_user_agent, user_agent=user_agent)
return user_agent

async def log_user_agent(user_agent):
...
```

## Sync or Async executors

If you're working with a standard ORM, then just use regular function calls for
your "resolve" methods, and Starlette will manage running the GraphQL query within a
separate thread.

If you want to use an asynchronous ORM, then use "async resolve" methods, and
make sure to setup Graphene's AsyncioExecutor using the `executor` argument.

```python
from graphql.execution.executors.asyncio import AsyncioExecutor
from starlette.applications import Starlette
from starlette.graphql import GraphQLApp
from starlette.routing import Route
import graphene


class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.String(default_value="stranger"))

async def resolve_hello(self, info, name):
# We can make asynchronous network calls here.
return "Hello " + name

routes = [
# We're using `executor_class=AsyncioExecutor` here.
Route('/', GraphQLApp(
schema=graphene.Schema(query=Query),
executor_class=AsyncioExecutor
))
]

app = Starlette(routes=routes)
```
Binary file removed docs/img/graphiql.png
Binary file not shown.
1 change: 0 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ gunicorn -k uvicorn.workers.UvicornH11Worker ...
[requests]: http://docs.python-requests.org/en/master/
[jinja2]: http://jinja.pocoo.org/
[python-multipart]: https://andrew-d.github.io/python-multipart/
[graphene]: https://graphene-python.org/
[itsdangerous]: https://pythonhosted.org/itsdangerous/
[sqlalchemy]: https://www.sqlalchemy.org
[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Optionals
graphene; python_version<'3.10'
itsdangerous
jinja2
python-multipart
Expand Down
7 changes: 0 additions & 7 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ xfail_strict=True
filterwarnings=
# Turn warnings that aren't filtered into exceptions
error
# Deprecated GraphQL (including https://github.com/graphql-python/graphene/issues/1055)
ignore: GraphQLApp is deprecated and will be removed in a future release\..*:DeprecationWarning
ignore: Using or importing the ABCs from 'collections' instead of from 'collections\.abc' is deprecated.*:DeprecationWarning
ignore: The 'context' alias has been deprecated. Please use 'context_value' instead\.:DeprecationWarning
ignore: The 'variables' alias has been deprecated. Please use 'variable_values' instead\.:DeprecationWarning
Expand All @@ -34,8 +32,3 @@ filterwarnings=

[coverage:run]
source_pkgs = starlette, tests
# GraphQLApp incompatible with and untested on Python 3.10. It's deprecated, let's just ignore
# coverage for it until it's gone.
omit =
starlette/graphql.py
tests/test_graphql.py
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def get_long_description():
],
extras_require={
"full": [
"graphene; python_version<'3.10'",
"itsdangerous",
"jinja2",
"python-multipart",
Expand Down
Loading

0 comments on commit 2808857

Please sign in to comment.