Skip to content

Commit af66474

Browse files
committed
First version of webob_graphql
0 parents  commit af66474

21 files changed

+1411
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.pyc
2+
.idea
3+
.cache
4+
.tox
5+
*.egg
6+
*.egg-info
7+
.coverage
8+
/build/
9+
10+
/dist/

.travis.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
language: python
2+
sudo: false
3+
matrix:
4+
include:
5+
- python: pypy
6+
env: TOX_ENV=pypy
7+
- python: '2.7'
8+
env: TOX_ENV=py27
9+
- python: '3.3'
10+
env: TOX_ENV=py33
11+
- python: '3.4'
12+
env: TOX_ENV=py34
13+
- python: '3.5'
14+
env: TOX_ENV=py35,import-order,flake8
15+
cache:
16+
directories:
17+
- $HOME/.cache/pip
18+
- $TRAVIS_BUILD_DIR/.tox
19+
install:
20+
- pip install tox coveralls
21+
script:
22+
- tox -e $TOX_ENV -- --cov=webob_graphql
23+
after_success:
24+
- coveralls
25+
deploy:
26+
provider: pypi
27+
user: syrusakbary
28+
on:
29+
tags: true
30+
password:
31+
secure: GB3YHihKAbmfh9kzMxzsZQDMf5h1aIJYwESfaYMc4DjMA1Qms+ZhBN2RiH3irwJ6FW47ZsS/O6ZsrlNxu75J/Mc1NJfzFev1d0xt7cYp+s0umYHhheelR6wmP8KOt3ugK7qmWuk5bykljpxsRKzKJCvGH+LOM7mDQy3NZOfYPTAM2znWjuBr+X4iUv6pUCKk5N20GBbs9T+jNttE7K8TH4zuXCWxgbE7xVHth76pB5Q/9FZkB8hZQ7K2esO3QyajDO7FzsOk8Z/jXRJ3MOxZCI3vGgmSzKTH4fMqmSrtyr1sCaBO5tgS8ytqQBjsuV1vIWl+75bXrAXfdkin63zMne4Rsb+uSWj3djP+iy2yML8a2mWMizxr803v8lwaGnMZ26f4rwdZnHGUPlTp3geVKq23vidVTQwF8v2o1rHvtdD4KJ5Mi41TXAfnih3XUf+fCTXdbAXKqweDuhcZg09/r7U/6zo76wjnt1cePPZe63/xG6bAVQ+Gz1J+HZz55ofDZV9g9kwyNll4Jfdzj9hUHO8AfBMvXQJewRj/LbzbmbBp5peov+DFhx7TWofvqxjreVKxDiDN89pC+WKy5BwZMcpB3dRVGuZ25ZrENLgoTX7W4PHPb1+OF4edP6xM44egcJLamk7vhvpZQqukJGRQZFtIMw8KIkC7OWzpCFIXN08=

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Syrus Akbary
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include README.md
2+
recursive-include webob_graphql/static *
3+
recursive-include webob_graphql/templates *

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# WebOb-GraphQL
2+
3+
[![Build Status](https://travis-ci.org/graphql-python/webob-graphql.svg?branch=master)](https://travis-ci.org/graphql-python/webob-graphql) [![Coverage Status](https://coveralls.io/repos/graphql-python/webob-graphql/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-python/webob-graphql?branch=master) [![PyPI version](https://badge.fury.io/py/webob-graphql.svg)](https://badge.fury.io/py/webob-graphql)
4+
5+
Adds GraphQL support to your WebOb application.
6+
7+
## Usage
8+
9+
Just use the `serve_graphql_request` function from `webob_graphql`
10+
11+
12+
### Pyramid
13+
14+
```python
15+
from pyramid.view import view_config
16+
17+
from webob_graphql import serve_graphql_request
18+
19+
20+
@view_config(
21+
route_name='graphql',
22+
# The serve_graphql_request method will detect what's the best renderer
23+
# to use, so it will do the json render automatically.
24+
# In summary, don't use the renderer='json' here :)
25+
)
26+
def graphql_view(request):
27+
return serve_graphql_request(request, schema)
28+
29+
# Optional, for adding batch query support (used in Apollo-Client)
30+
return serve_graphql_request(request, schema, batch_enabled=True)
31+
```
32+
33+
### Supported options
34+
* `schema`: The `GraphQLSchema` object that you want the view to execute when it gets a valid request.
35+
* `context`: A value to pass as the `context` to the `graphql()` function.
36+
* `root_value`: The `root_value` you want to provide to `executor.execute`.
37+
* `pretty`: Whether or not you want the response to be pretty printed JSON.
38+
* `executor`: The `Executor` that you want to use to execute queries.
39+
* `graphiql_enabled`: If `True` (default), may present [GraphiQL](https://github.com/graphql/graphiql) when loaded directly from a browser (a useful tool for debugging and exploration).
40+
* `graphiql_template`: Inject a Jinja template string to customize GraphiQL.
41+
* `batch_enabled`: Enable batch support (for using in [Apollo-Client](http://dev.apollodata.com/core/network.html#query-batching) or [ReactRelayNetworkLayer](https://github.com/nodkz/react-relay-network-layer))

README.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
WebOb-GraphQL
2+
=============
3+
4+
|Build Status| |Coverage Status| |PyPI version|
5+
6+
Adds GraphQL support to your WebOb application.
7+
8+
Usage
9+
-----
10+
11+
Just use the ``serve_graphql_request`` function from ``webob_graphql``
12+
13+
Pyramid
14+
~~~~~~~
15+
16+
.. code:: python
17+
18+
from pyramid.view import view_config
19+
20+
from webob_graphql import serve_graphql_request
21+
22+
23+
@view_config(
24+
route_name='graphql',
25+
# The serve_graphql_request method will detect what's the best renderer
26+
# to use, so it will do the json render automatically.
27+
# In summary, don't use the renderer='json' here :)
28+
)
29+
def graphql_view(request):
30+
return serve_graphql_request(request, schema)
31+
32+
# Optional, for adding batch query support (used in Apollo-Client)
33+
return serve_graphql_request(request, schema, batch_enabled=True)
34+
35+
Supported options
36+
~~~~~~~~~~~~~~~~~
37+
38+
- ``schema``: The ``GraphQLSchema`` object that you want the view to
39+
execute when it gets a valid request.
40+
- ``context``: A value to pass as the ``context`` to the ``graphql()``
41+
function.
42+
- ``root_value``: The ``root_value`` you want to provide to
43+
``executor.execute``.
44+
- ``pretty``: Whether or not you want the response to be pretty printed
45+
JSON.
46+
- ``executor``: The ``Executor`` that you want to use to execute
47+
queries.
48+
- ``graphiql_enabled``: If ``True`` (default), may present
49+
`GraphiQL <https://github.com/graphql/graphiql>`__ when loaded
50+
directly from a browser (a useful tool for debugging and
51+
exploration).
52+
- ``graphiql_template``: Inject a Jinja template string to customize
53+
GraphiQL.
54+
- ``batch_enabled``: Enable batch support (for using in
55+
`Apollo-Client <http://dev.apollodata.com/core/network.html#query-batching>`__
56+
or
57+
`ReactRelayNetworkLayer <https://github.com/nodkz/react-relay-network-layer>`__)
58+
59+
.. |Build Status| image:: https://travis-ci.org/graphql-python/webob-graphql.svg?branch=master
60+
:target: https://travis-ci.org/graphql-python/webob-graphql
61+
.. |Coverage Status| image:: https://coveralls.io/repos/graphql-python/webob-graphql/badge.svg?branch=master&service=github
62+
:target: https://coveralls.io/github/graphql-python/webob-graphql?branch=master
63+
.. |PyPI version| image:: https://badge.fury.io/py/webob-graphql.svg
64+
:target: https://badge.fury.io/py/webob-graphql

bin/autolinter

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
# Install the required scripts with
4+
# pip install autoflake autopep8 isort
5+
autoflake ./webob_graphql/ -r --remove-unused-variables --remove-all-unused-imports --in-place
6+
autopep8 ./webob_graphql/ -r --in-place --experimental --aggressive --max-line-length 120
7+
isort -rc ./webob_graphql/

bin/convert_documentation

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
pandoc README.md --from markdown --to rst -s -o README.rst

setup.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[flake8]
2+
exclude = tests,scripts,setup.py,docs
3+
max-line-length = 160
4+
5+
[isort]
6+
known_first_party=graphql
7+
8+
[pytest]
9+
norecursedirs = venv .tox .cache

setup.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from setuptools import setup, find_packages
2+
3+
required_packages = [
4+
'graphql-core>=1.0',
5+
'webob',
6+
'graphql-server-core>=1.0.dev'
7+
]
8+
9+
tests_require = [
10+
'pytest>=2.7.3',
11+
'mako'
12+
]
13+
14+
setup(
15+
name='WebOb-GraphQL',
16+
version='1.0.dev20170404001',
17+
description='Adds GraphQL support to your WebOb (Pyramid/Pylons/...) application',
18+
long_description=open('README.rst').read(),
19+
url='https://github.com/graphql-python/webob-graphql',
20+
download_url='https://github.com/graphql-python/webob-graphql/releases',
21+
author='Syrus Akbary',
22+
author_email='me@syrusakbary.com',
23+
license='MIT',
24+
classifiers=[
25+
'Development Status :: 5 - Production/Stable',
26+
'Intended Audience :: Developers',
27+
'Topic :: Software Development :: Libraries',
28+
'Programming Language :: Python :: 2',
29+
'Programming Language :: Python :: 2.7',
30+
'Programming Language :: Python :: 3',
31+
'Programming Language :: Python :: 3.3',
32+
'Programming Language :: Python :: 3.4',
33+
'Programming Language :: Python :: 3.5',
34+
'Programming Language :: Python :: Implementation :: PyPy',
35+
'License :: OSI Approved :: MIT License',
36+
],
37+
keywords='api graphql protocol rest webob',
38+
packages=find_packages(exclude=['tests']),
39+
install_requires=required_packages,
40+
extras_require={
41+
'test': tests_require,
42+
},
43+
tests_require=tests_require,
44+
include_package_data=True,
45+
zip_safe=False,
46+
platforms='any',
47+
)

tests/__init__.py

Whitespace-only changes.

tests/schema.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from graphql.type.definition import GraphQLArgument, GraphQLField, GraphQLNonNull, GraphQLObjectType
2+
from graphql.type.scalars import GraphQLString
3+
from graphql.type.schema import GraphQLSchema
4+
5+
6+
def resolve_raises(*_):
7+
raise Exception("Throws!")
8+
9+
10+
QueryRootType = GraphQLObjectType(
11+
name='QueryRoot',
12+
fields={
13+
'thrower': GraphQLField(GraphQLNonNull(GraphQLString), resolver=resolve_raises),
14+
'request': GraphQLField(GraphQLNonNull(GraphQLString),
15+
resolver=lambda obj, args, context, info: context.params.get('q')),
16+
'context': GraphQLField(GraphQLNonNull(GraphQLString),
17+
resolver=lambda obj, args, context, info: context),
18+
'test': GraphQLField(
19+
type=GraphQLString,
20+
args={
21+
'who': GraphQLArgument(GraphQLString)
22+
},
23+
resolver=lambda obj, args, context, info: 'Hello %s' % (args.get('who') or 'World')
24+
)
25+
}
26+
)
27+
28+
MutationRootType = GraphQLObjectType(
29+
name='MutationRoot',
30+
fields={
31+
'writeTest': GraphQLField(
32+
type=QueryRootType,
33+
resolver=lambda *_: QueryRootType
34+
)
35+
}
36+
)
37+
38+
schema = GraphQLSchema(QueryRootType, MutationRootType)

tests/test_graphiql.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import pytest
2+
3+
from .schema import schema
4+
from .utils import url_string, response_json, j, jl, Client
5+
6+
from webob_graphql.mako import render_graphiql as mako_render_graphiql
7+
8+
9+
@pytest.fixture
10+
def settings():
11+
return {}
12+
13+
14+
@pytest.fixture
15+
def client(settings):
16+
return Client(schema, settings)
17+
18+
19+
@pytest.fixture
20+
def pretty_response():
21+
return (
22+
'{\n'
23+
' "data": {\n'
24+
' "test": "Hello World"\n'
25+
' }\n'
26+
'}'
27+
).replace('\"','\\\"').replace('\n', '\\n')
28+
29+
30+
def test_graphiql_is_enabled_by_default(client):
31+
response = client.get(url_string(), headers={'Accept': 'text/html'})
32+
assert response.status_code == 200
33+
assert response.content_type == 'text/html'
34+
35+
36+
def test_graphiql_simple_renderer(client, pretty_response):
37+
response = client.get(url_string(query='{test}'), headers={'Accept': 'text/html'})
38+
assert response.status_code == 200
39+
assert pretty_response in response.body.decode('utf-8')
40+
41+
42+
@pytest.mark.parametrize('settings', [dict(render_graphiql=mako_render_graphiql)])
43+
def test_graphiql_mako_renderer(client, pretty_response):
44+
response = client.get(url_string(query='{test}'), headers={'Accept': 'text/html'})
45+
assert response.status_code == 200
46+
assert pretty_response in response.body.decode('utf-8')
47+
48+
49+
def test_graphiql_html_is_not_accepted(client):
50+
response = client.get(url_string(), headers={'Accept': 'application/json'})
51+
assert response.status_code == 400
52+
53+
54+
def test_graphiql_get_mutation(client, pretty_response):
55+
query = 'mutation TestMutation { writeTest { test } }'
56+
response = client.get(url_string(query=query), headers={'Accept': 'text/html'})
57+
assert response.status_code == 200
58+
assert 'response: null' in response.body.decode('utf-8')
59+
60+
61+
@pytest.mark.parametrize('settings', [dict(graphiql_enabled=False)])
62+
def test_graphiql_is_enabled_by_default(client):
63+
response = client.get(url_string(query='{test}'), headers={'Accept': 'text/html'})
64+
assert response.status_code == 200
65+
assert response.content_type == 'application/json'

0 commit comments

Comments
 (0)