Skip to content

Commit

Permalink
Apply suggestions after proof-read
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalp committed Dec 14, 2018
1 parent 73a322e commit 6d56972
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 102 deletions.
16 changes: 8 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
## 0.2.0 (UNRELEASED)

- Removed support for Python 3.5 and added support for 3.7.
- Moved to `GraphQL-core-next` that supports `async` resolvers, query execution and implements more recent version of GraphQL spec. If you are updating existing project, you will need to uninstall `graphql-core` before installing `graphql-core-next`, as both libraries use `graphql` namespace.
- Moved to `GraphQL-core-next` that supports `async` resolvers, query execution and implements a more recent version of GraphQL spec. If you are updating an existing project, you will need to uninstall `graphql-core` before installing `graphql-core-next`, as both libraries use `graphql` namespace.
- Added `gql()` utility that provides GraphQL string validation on declaration time, and enables use of [Apollo-GraphQL](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo) plugin in Python code.
- Added `load_schema_from_path()` utility function that loads GraphQL types from file or directory containing `.graphql` files, also performing syntax validation.
- Added `start_simple_server()` shortcut function for a quick dev server creation, abstracting away the `GraphQLMiddleware.make_server()` from first time users.
- Added `load_schema_from_path()` utility function that loads GraphQL types from a file or directory containing `.graphql` files, also performing syntax validation.
- Added `start_simple_server()` shortcut function for quick dev server creation, abstracting away the `GraphQLMiddleware.make_server()` from first time users.
- `Boolean` built-in scalar now checks the type of each serialized value. Returning values of type other than `bool`, `int` or `float` from a field resolver will result in a `Boolean cannot represent a non boolean value` error.
- Redefining type in `type_defs` will now result in `TypeError` being raised. This is breaking change from previous behaviour where old type was simply replaced with new one.
- Returning `None` from scalar `parse_literal` and `parse_value` function no longer results in GraphQL API producing default error message. Instead `None` will be passed further down to resolver or producing "value is required" error if its marked as such with `!` For old behaviour raise either `ValueError` or `TypeError`. See documentation for more details.
- Redefining type in `type_defs` will now result in `TypeError` being raised. This is a breaking change from previous behavior where the old type was simply replaced with a new one.
- Returning `None` from scalar `parse_literal` and `parse_value` function no longer results in GraphQL API producing default error message. Instead, `None` will be passed further down to resolver or produce a "value is required" error if its marked as such with `!` For old behavior raise either `ValueError` or `TypeError`. See documentation for more details.
- `resolvers` argument defined by `GraphQLMiddleware.__init__()`, `GraphQLMiddleware.make_server()` and `start_simple_server()` is now optional, allowing for quick experiments with schema definitions.
- `dict` has been removed as primitive for mapping python function to fields. Instead, `make_executable_schema()` expects object or iterable of objects with `bind_to_schema` method, that is called with `GraphQLSchema` instance and are expected to add resolvers to schema.
- Default resolvers are no longer set implicitly by `make_executable_schema()`. Instead you expected to include either `ariadne.fallback_resolvers` or `ariadne.snake_case_fallback_resolvers` in the list of `resolvers` for your schema.
- `dict` has been removed as primitive for mapping python function to fields. Instead, `make_executable_schema()` expects object or list of objects with a `bind_to_schema` method, that is called with a `GraphQLSchema` instance and are expected to add resolvers to schema.
- Default resolvers are no longer set implicitly by `make_executable_schema()`. Instead you are expected to include either `ariadne.fallback_resolvers` or `ariadne.snake_case_fallback_resolvers` in the list of `resolvers` for your schema.
- Added `snake_case_fallback_resolvers` that populates schema with default resolvers that map `CamelCase` and `PascalCase` field names from schema to `snake_sase` names in Python.
- Added `ResolverMap` object that enables assignment of resolver functions to schema types.
- Added `Scalar` object that enables assignment of `serialize`, `parse_value` and `parse_literal` functions to custom scalars.
- Both `ResolverMap` and `Scalar` are validating if schema defines specified types and/or fields at moment of creation of executable schema, providing better feedback to developer.
- Both `ResolverMap` and `Scalar` are validating if schema defines specified types and/or fields at the moment of creation of executable schema, providing better feedback to the developer.
16 changes: 8 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,36 @@

Thank you for your interest in contributing to Ariadne!

We welcome bug reports, questions, pull requests and general feedback.
We welcome bug reports, questions, pull requests, and general feedback.

We also ask all contributors to familiarize themselves with and follow project's code of conduct, available in [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file kept in repository's main directory.
We also ask all contributors to familiarize themselves with and follow project's code of conduct, available in the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file kept in the repository's main directory.


# Reporting bugs, asking for help, offering feedback and ideas

You can use [GitHub issues](https://github.com/mirumee/ariadne/issues) to report bugs, ask for help, share your ideas or simply offer feedback. We are curious what you are thinking about Ariadne!
You can use [GitHub issues](https://github.com/mirumee/ariadne/issues) to report bugs, ask for help, share your ideas, or simply offer feedback. We are curious what you think of Ariadne!


## Development setup

Ariadne is written to support Python 3.6 and 3.7.

Codebase is formatted using [Black](https://github.com/ambv/black), and contents of `ariadne` package are annotated with types and validated using [mypy](http://mypy-lang.org/index.html).
Codebase is formatted using [Black](https://github.com/ambv/black), and the contents of the `ariadne` package are annotated with types and validated using [mypy](http://mypy-lang.org/index.html).

Tests are developed using [pytest](https://pytest.org/) with [Codecov](https://codecov.io/gh/mirumee/ariadne) for monitoring coverage.

Dev requirements can be installed using `requirements-dev.txt`.

We require for all changes to be done via pull requests, and to be approved by member-ranked users before merging.
We require all changes to be done via pull requests, and to be approved by member-ranked users before merging.


## Working on issues

We consider all issues not assigned to anybody as available for contributors. The **[help wanted](https://github.com/mirumee/ariadne/labels/help%20wanted)** label is used to single out issues that we consider easier or higher priority on list of things that we would like to see.
We consider all issues which are not assigned to anybody as being available for contributors. The **[help wanted](https://github.com/mirumee/ariadne/labels/help%20wanted)** label is used to single out issues that we consider easier or higher priority on the list of things that we would like to see.

If you've found issue you want to help with, please add your comment to it - this lets other contributors know what issues are being worked on, as well as for maintainers to offer guidance and help.
If you've found issue you want to help with, please add your comment to it - this lets other contributors know what issues are being worked on, as well as allowing maintainers to offer guidance and help.


## Pull requests

We don't require that pull requests to be followed with bug reports. If you've found typo or silly little bug that has no issue or pull request already, you can open your own pull request. We only ask that this PR provides context or explanation for what problem it fixes or which are of project it improves.
We don't require pull requests to be followed with bug reports. If you've found a typo or a silly little bug that has no issue or pull request already, you can open your own pull request. We only ask that this PR provides context or explanation for what problem it fixes, or which area of the project it improves.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

Ariadne is a Python library for implementing [GraphQL](http://graphql.github.io/) servers, inspired by [Apollo Server](https://www.apollographql.com/docs/apollo-server/) and built with [GraphQL-core-next](https://github.com/graphql-python/graphql-core-next).

Currently the library already implements enough features to enable developers to build functional GraphQL APIs. It is also being dogfooded internally at number of projects.
The library already implements enough features to enable developers to build functional GraphQL APIs. It is also being dogfooded internally on a number of projects.

Documentation is available [here](https://ariadne.readthedocs.io/en/latest/?badge=latest).

Expand All @@ -24,7 +24,7 @@ Ariadne can be installed with pip:

## Quickstart

Following example creates API defining `Person` type and single query field `people` returning list of two persons. It also starts local dev server with [GraphQL Playground](https://github.com/prisma/graphql-playground) available on the `http://127.0.0.1:8888` address.
The following example creates an API defining `Person` type and single query field `people` returning a list of two persons. It also starts a local dev server with [GraphQL Playground](https://github.com/prisma/graphql-playground) available on the `http://127.0.0.1:8888` address.

```python
from ariadne import ResolverMap, gql, start_simple_server
Expand Down Expand Up @@ -72,6 +72,6 @@ For more guides and examples, please see the [documentation](https://ariadne.rea
Contributing
------------

We are welcoming contributions to Ariadne! If you've found a bug, issue, got question or just want to drop general feedback, feel free to use [GitHub issues](https://github.com/mirumee/ariadne/issues).
We are welcoming contributions to Ariadne! If you've found a bug or issue, or if you have any questions or feedback, feel free to use [GitHub issues](https://github.com/mirumee/ariadne/issues).

For guidance and instructions, please see [CONTRIBUTING.md](CONTRIBUTING.md).
2 changes: 1 addition & 1 deletion docs/custom-server.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Custom server example
=====================

In addition to simple GraphQL server implementation in form of ``GraphQLMiddleware``, Ariadne provides building blocks for assembling custom GraphQL servers.
In addition to simple a GraphQL server implementation in the form of ``GraphQLMiddleware``, Ariadne provides building blocks for assembling custom GraphQL servers.


Creating executable schema
Expand Down
30 changes: 15 additions & 15 deletions docs/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ Make sure that you've installed Ariadne using ``pip install ariadne``, and that
Defining schema
---------------

First, we will with describe what data can be obtained from our API.
First, we will describe what data can be obtained from our API.

In Ariadne this is achieved by defining Python strings with content written in `Schema Definition Language <https://graphql.github.io/learn/schema/>`_ (SDL), a special language for declaring GraphQL schemas.

We will start with defining the special type ``Query`` that GraphQL services use as entry point for all reading operations. Next we will specify a single field on it, named ``hello``, and define that it will return a value of type ``String``, and that it will never return ``null``.
We will start by defining the special type ``Query`` that GraphQL services use as entry point for all reading operations. Next, we will specify a single field on it, named ``hello``, and define that it will return a value of type ``String``, and that it will never return ``null``.

Using the SDL, our ``Query`` type definition will look like this::

Expand All @@ -27,13 +27,13 @@ Using the SDL, our ``Query`` type definition will look like this::
}
"""

The ``type Query { }`` block declares the type, ``hello`` is the field definition, ``String`` is the return value type, and the exclamation mark following it means that returned value will never be ``null``.
The ``type Query { }`` block declares the type, ``hello`` is the field definition, ``String`` is the return value type, and the exclamation mark following it means that the returned value will never be ``null``.


Validating schema
-----------------

Ariadne provides tiny ``gql`` utility function that takes single argument: GraphQL string, validates it and raises descriptive ``GraphQLSyntaxError``, or returns original unmodified string if its correct::
Ariadne provides tiny ``gql`` utility function that takes single argument: GraphQL string, validates it and raises descriptive ``GraphQLSyntaxError``, or returns the original unmodified string if its correct::

from ariadne import gql

Expand All @@ -43,7 +43,7 @@ Ariadne provides tiny ``gql`` utility function that takes single argument: Graph
}
""")

If we try to run above code now, we will get an error pointing to our incorrect syntax within our ``type_defs`` declaration::
If we try to run the above code now, we will get an error pointing to our incorrect syntax within our ``type_defs`` declaration::

graphql.error.syntax_error.GraphQLSyntaxError: Syntax Error: Expected :, found Name

Expand All @@ -53,7 +53,7 @@ If we try to run above code now, we will get an error pointing to our incorrect
^
}

Using ``gql`` is optional, but without it above error would occur during your server's initialization and point to somewhere inside Ariadne's GraphQL initialization logic, making tracking down incorrect place trickier if your API is large and spread across many modules.
Using ``gql`` is optional; however, without it, the above error would occur during your server's initialization and point to somewhere inside Ariadne's GraphQL initialization logic, making tracking down the error tricky if your API is large and spread across many modules.


Resolvers
Expand All @@ -63,31 +63,31 @@ The resolvers are functions mediating between API consumers and the application'

We want our API to greet clients with a "Hello (user agent)!" string. This means that the ``hello`` field has to have a resolver that somehow finds the client's user agent, and returns a greeting message from it.

At its simplest, resolver is a function that returns value::
At its simplest, resolver is a function that returns a value::

def resolve_hello(*_):
return "Hello..." # What's next?

The above code is perfectly valid, minimal resolver meeting the requirements of our schema. It takes any arguments, does nothing with them and returns blank greeting string.
The above code is perfectly valid, with a minimal resolver meeting the requirements of our schema. It takes any arguments, does nothing with them and returns a blank greeting string.

Real-world resolvers are rarely that simple: they usually read data from some source such as a database, process inputs, or resolve value in the context of a parent object. How should our basic resolver look to resolve a client's user agent?

In Ariadne every field resolver is called with at least two arguments: ``obj`` parent object, and the query's execution ``info`` that usually contains the ``context`` attribute that is GraphQL's way of passing additional information from the application to its query resolvers.

Default GraphQL server implementation provided by Ariadne defines ``info.context`` as Python ``dict`` containing a single key named ``environ`` containing basic request data. We can use this in our resolver::
The default GraphQL server implementation provided by Ariadne defines ``info.context`` as Python ``dict`` containing a single key named ``environ`` containing basic request data. We can use this in our resolver::

def resolve_hello(_, info):
request = info.context["environ"]
user_agent = request.get("HTTP_USER_AGENT", "guest")
return "Hello, %s!" % user_agent

Notice that we are discarding the first argument in our resolver. This is because ``resolve_hello`` is special type of resolver: it belongs to a field defined on a root type (`Query`), and such fields, by default, have no parent that could be passed to their resolvers. This type of resolver is called a *root resolver*.
Notice that we are discarding the first argument in our resolver. This is because ``resolve_hello`` is a special type of resolver: it belongs to a field defined on a root type (`Query`), and such fields, by default, have no parent that could be passed to their resolvers. This type of resolver is called a *root resolver*.

Now we need to map our resolver to the ``hello`` field of type ``Query``. To do this, we will use the ``ResolverMap`` class that maps resolver functions to types in the schema. First, we will update our imports::

from ariadne import ResolverMap, gql

Next, we will create an resolver map for our only type - ``Query``::
Next, we will create a resolver map for our only type - ``Query``::

# Create ResolverMap for Query type defined in our schema...
query = ResolverMap("Query")
Expand All @@ -104,19 +104,19 @@ Next, we will create an resolver map for our only type - ``Query``::
Testing the API
---------------

Now we have everything we need to finish our API, with only piece missing being the http server that would receive the HTTP requests, execute GraphQL queries and return responses.
Now we have everything we need to finish our API, with the missing only piece being the http server that would receive the HTTP requests, execute GraphQL queries and return responses.

This is where Ariadne comes into play. One of the utilities that Ariadne provides is a ``start_simple_server`` that enables developers to experiment with GraphQL locally without need for full-fledged HTTP stack or web framework::
This is where Ariadne comes into play. One of the utilities that Ariadne provides is a ``start_simple_server`` that enables developers to experiment with GraphQL locally without the need for a full-fledged HTTP stack or web framework::

from ariadne import start_simple_server

We will now call ``start_simple_server`` with ``type_defs`` and ``query`` as its arguments to start a simple dev server::

start_simple_server(type_defs, query)

Run your script with ``python myscript.py`` (remember to replace ``myscript.py`` with name of your file!). If all is well, you will see a message telling you that simple GraphQL server is running on the http://127.0.0.1:8888. Open this link in your web browser.
Run your script with ``python myscript.py`` (remember to replace ``myscript.py`` with the name of your file!). If all is well, you will see a message telling you that the simple GraphQL server is running on the http://127.0.0.1:8888. Open this link in your web browser.

You will see the GraphQL Playground, the open source API explorer for GraphQL APIs. You can enter ``{ hello }`` query on the left, press the big bright "run" button, and see the result on the right:
You will see the GraphQL Playground, the open source API explorer for GraphQL APIs. You can enter ``{ hello }`` query on the left, press the big, bright "run" button, and see the result on the right:

.. image:: _static/hello-world.png
:alt: Your first Ariadne GraphQL in action!
Expand Down
Loading

0 comments on commit 6d56972

Please sign in to comment.