Merge pull request #1 from graphql-python/master

Catch up with parent repo
This commit is contained in:
Timothy J Laurent 2016-11-15 16:38:57 -08:00 committed by GitHub
commit 297b741cdb
13 changed files with 107 additions and 25 deletions

View File

@ -59,3 +59,10 @@ matrix:
env: TEST_TYPE=build DJANGO_VERSION=1.9 env: TEST_TYPE=build DJANGO_VERSION=1.9
- python: '2.7' - python: '2.7'
env: TEST_TYPE=lint env: TEST_TYPE=lint
deploy:
provider: pypi
user: syrusakbary
on:
tags: true
password:
secure: kymIFCEPUbkgRqe2NAXkWfxMmGRfWvWBOP6LIXdVdkOOkm91fU7bndPGrAjos+/7gN0Org609ZmHSlVXNMJUWcsL2or/x5LcADJ4cZDe+79qynuoRb9xs1Ri4O4SBAuVMZxuVJvs8oUzT2R11ql5vASSMtXgbX+ZDGpmPRVZStkCuXgOc4LBhbPKyl3OFy7UQFPgAEmy3Yjh4ZSKzlXheK+S6mmr60+DCIjpaA0BWPxYK9FUE0qm7JJbHLUbwsUP/QMp5MmGjwFisXCNsIe686B7QKRaiOw62eJc2R7He8AuEC8T9OM4kRwDlecSn8mMpkoSB7QWtlJ+6XdLrJFPNvtrOfgfzS9/96Qrw9WlOslk68hMlhJeRb0s2YUD8tiV3UUkvbL1mfFoS4SI9U+rojS55KhUEJWHg1w7DjoOPoZmaIL2ChRupmvrFYNAGae1cxwG3Urh+t3wYlN3gpKsRDe5GOT7Wm2tr0ad3McCpDGUwSChX59BAJXe/MoLxkKScTrMyR8yMxHOF0b4zpVn5l7xB/o2Ik4zavx5q/0rGBMK2D+5d+gpQogKShoquTPsZUwO7sB5hYeH2hqGqpeGzZtb76E2zZYd18pJ0FsBudm5+KWjYdZ+vbtGrLxdTXJ1EEtzVXm0lscykTpqUucbXSa51dhStJvW2xEEz6p3rHo=

View File

@ -107,3 +107,21 @@ After developing, the full test suite can be evaluated by running:
```sh ```sh
python setup.py test # Use --pytest-args="-v -s" for verbose mode python setup.py test # Use --pytest-args="-v -s" for verbose mode
``` ```
### Documentation
The documentation is generated using the excellent [Sphinx](http://www.sphinx-doc.org/) and a custom theme.
The documentation dependencies are installed by running:
```sh
cd docs
pip install -r requirements.txt
```
Then to produce a HTML version of the documentation:
```sh
make html
```

View File

@ -117,6 +117,25 @@ After developing, the full test suite can be evaluated by running:
python setup.py test # Use --pytest-args="-v -s" for verbose mode python setup.py test # Use --pytest-args="-v -s" for verbose mode
Documentation
~~~~~~~~~~~~~
The documentation can be generated using the excellent
`Sphinx <http://www.sphinx-doc.org/>`__ and a custom theme.
To install the documentation dependencies, run the following:
.. code:: sh
cd docs
pip install -r requirements.txt
Then to produce a HTML version of the documentation:
.. code:: sh
make html
.. |Graphene Logo| image:: http://graphene-python.org/favicon.png .. |Graphene Logo| image:: http://graphene-python.org/favicon.png
.. |Build Status| image:: https://travis-ci.org/graphql-python/graphene-django.svg?branch=master .. |Build Status| image:: https://travis-ci.org/graphql-python/graphene-django.svg?branch=master
:target: https://travis-ci.org/graphql-python/graphene-django :target: https://travis-ci.org/graphql-python/graphene-django

View File

@ -1,2 +1,3 @@
sphinx
# Docs template # Docs template
https://github.com/graphql-python/graphene-python.org/archive/docs.zip https://github.com/graphql-python/graphene-python.org/archive/docs.zip

View File

@ -188,6 +188,8 @@ And then add the ``SCHEMA`` to the ``GRAPHENE`` config in ``cookbook/settings.py
'SCHEMA': 'cookbook.schema.schema' 'SCHEMA': 'cookbook.schema.schema'
} }
Alternatively, we can specify the schema to be used in the urls definition,
as explained below.
Creating GraphQL and GraphiQL views Creating GraphQL and GraphiQL views
----------------------------------- -----------------------------------
@ -199,6 +201,22 @@ view.
This view will serve as GraphQL endpoint. As we want to have the This view will serve as GraphQL endpoint. As we want to have the
aforementioned GraphiQL we specify that on the params with ``graphiql=True``. aforementioned GraphiQL we specify that on the params with ``graphiql=True``.
.. code:: python
from django.conf.urls import url, include
from django.contrib import admin
from graphene_django.views import GraphQLView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', GraphQLView.as_view(graphiql=True)),
]
If we didn't specify the target schema in the Django settings file
as explained above, we can do so here using:
.. code:: python .. code:: python
from django.conf.urls import url, include from django.conf.urls import url, include
@ -210,7 +228,7 @@ aforementioned GraphiQL we specify that on the params with ``graphiql=True``.
urlpatterns = [ urlpatterns = [
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^graphql', GraphQLView.as_view(graphiql=True)), url(r'^graphql', GraphQLView.as_view(graphiql=True, schema=schema)),
] ]
Apply model changes to database Apply model changes to database

View File

@ -4,6 +4,7 @@ from django.db import models
class MissingType(object): class MissingType(object):
pass pass
try: try:
DurationField = models.DurationField DurationField = models.DurationField
UUIDField = models.UUIDField UUIDField = models.UUIDField
@ -21,6 +22,13 @@ except:
try: try:
# Postgres fields are only available in Django 1.8+ # Postgres fields are only available in Django 1.8+
from django.contrib.postgres.fields import ArrayField, HStoreField, JSONField, RangeField from django.contrib.postgres.fields import ArrayField, HStoreField, RangeField
except ImportError: except ImportError:
ArrayField, HStoreField, JSONField, RangeField = (MissingType, ) * 4 ArrayField, HStoreField, JSONField, RangeField = (MissingType, ) * 4
try:
# Postgres fields are only available in Django 1.9+
from django.contrib.postgres.fields import JSONField
except ImportError:
JSONField = MissingType

View File

@ -6,7 +6,7 @@ from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List,
from graphene.relay import is_node from graphene.relay import is_node
from graphene.types.datetime import DateTime from graphene.types.datetime import DateTime
from graphene.types.json import JSONString from graphene.types.json import JSONString
from graphene.utils.str_converters import to_const from graphene.utils.str_converters import to_camel_case, to_const
from graphql import assert_valid_name from graphql import assert_valid_name
from .compat import (ArrayField, HStoreField, JSONField, RangeField, from .compat import (ArrayField, HStoreField, JSONField, RangeField,
@ -41,7 +41,7 @@ def convert_django_field_with_choices(field, registry=None):
choices = getattr(field, 'choices', None) choices = getattr(field, 'choices', None)
if choices: if choices:
meta = field.model._meta meta = field.model._meta
name = '{}{}'.format(meta.object_name, field.name.capitalize()) name = to_camel_case('{}_{}'.format(meta.object_name, field.name))
choices = list(get_choices(choices)) choices = list(get_choices(choices))
named_choices = [(c[0], c[1]) for c in choices] named_choices = [(c[0], c[1]) for c in choices]
named_choices_descriptions = {c[0]: c[2] for c in choices} named_choices_descriptions = {c[0]: c[2] for c in choices}

View File

@ -112,7 +112,7 @@ add "&raw" to the end of the URL within a browser.
{% if variables %} {% if variables %}
variables: '{{ variables|escapejs }}', variables: '{{ variables|escapejs }}',
{% endif %} {% endif %}
{% if operationName %} {% if operation_name %}
operationName: '{{ operation_name|escapejs }}', operationName: '{{ operation_name|escapejs }}',
{% endif %} {% endif %}
}), }),

View File

@ -38,6 +38,7 @@ class Article(models.Model):
headline = models.CharField(max_length=100) headline = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, related_name='articles') reporter = models.ForeignKey(Reporter, related_name='articles')
editor = models.ForeignKey(Reporter, related_name='edited_articles_+')
lang = models.CharField(max_length=2, help_text='Language', choices=[ lang = models.CharField(max_length=2, help_text='Language', choices=[
('es', 'Spanish'), ('es', 'Spanish'),
('en', 'English') ('en', 'English')

View File

@ -52,7 +52,7 @@ def test_django_objecttype_map_correct_fields():
def test_django_objecttype_with_node_have_correct_fields(): def test_django_objecttype_with_node_have_correct_fields():
fields = Article._meta.fields fields = Article._meta.fields
assert list(fields.keys()) == ['id', 'headline', 'pub_date', 'reporter', 'lang', 'importance'] assert list(fields.keys()) == ['id', 'headline', 'pub_date', 'reporter', 'editor', 'lang', 'importance']
def test_schema_representation(): def test_schema_representation():
@ -66,13 +66,14 @@ type Article implements Node {
headline: String! headline: String!
pubDate: DateTime! pubDate: DateTime!
reporter: Reporter! reporter: Reporter!
editor: Reporter!
lang: ArticleLang! lang: ArticleLang!
importance: ArticleImportance importance: ArticleImportance
} }
type ArticleConnection { type ArticleConnection {
pageInfo: PageInfo! pageInfo: PageInfo!
edges: [ArticleEdge] edges: [ArticleEdge]!
} }
type ArticleEdge { type ArticleEdge {
@ -109,11 +110,11 @@ type Reporter {
lastName: String! lastName: String!
email: String! email: String!
pets: [Reporter] pets: [Reporter]
aChoice: ReporterA_choice! aChoice: ReporterAChoice!
articles(before: String, after: String, first: Int, last: Int): ArticleConnection articles(before: String, after: String, first: Int, last: Int): ArticleConnection
} }
enum ReporterA_choice { enum ReporterAChoice {
A_1 A_1
A_2 A_2
} }

View File

@ -26,9 +26,12 @@ def construct_fields(options):
is_not_in_only = only_fields and name not in options.only_fields is_not_in_only = only_fields and name not in options.only_fields
is_already_created = name in options.fields is_already_created = name in options.fields
is_excluded = name in exclude_fields or is_already_created is_excluded = name in exclude_fields or is_already_created
if is_not_in_only or is_excluded: # https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
is_no_backref = str(name).endswith('+')
if is_not_in_only or is_excluded or is_no_backref:
# We skip this field if we specify only_fields and is not # We skip this field if we specify only_fields and is not
# in there. Or when we exclude this field in exclude_fields # in there. Or when we exclude this field in exclude_fields.
# Or when there is no back reference.
continue continue
converted = convert_django_field_with_choices(field, options.registry) converted = convert_django_field_with_choices(field, options.registry)
if not converted: if not converted:

View File

@ -1,3 +1,6 @@
[aliases]
test=pytest
[tool:pytest] [tool:pytest]
DJANGO_SETTINGS_MODULE = django_test_settings DJANGO_SETTINGS_MODULE = django_test_settings

View File

@ -2,7 +2,7 @@ from setuptools import find_packages, setup
setup( setup(
name='graphene-django', name='graphene-django',
version='1.0', version='1.1.0',
description='Graphene Django integration', description='Graphene Django integration',
long_description=open('README.rst').read(), long_description=open('README.rst').read(),
@ -38,6 +38,9 @@ setup(
'iso8601', 'iso8601',
'singledispatch>=3.4.0.3', 'singledispatch>=3.4.0.3',
], ],
setup_requires=[
'pytest-runner',
],
tests_require=[ tests_require=[
'django-filter>=0.10.0', 'django-filter>=0.10.0',
'pytest', 'pytest',