Merge branch 'master' into issue_863

This commit is contained in:
Eran Kampf 2019-03-08 14:57:26 -08:00 committed by GitHub
commit 4344d8f442
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 172 additions and 36 deletions

View File

@ -1,24 +1,28 @@
repos:
- repo: git://github.com/pre-commit/pre-commit-hooks
rev: v1.3.0
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: trailing-whitespace
exclude: README.md
- id: pretty-format-json
args:
- --autofix
- id: flake8
- id: trailing-whitespace
exclude: README.md
- repo: https://github.com/asottile/pyupgrade
rev: v1.4.0
rev: v1.12.0
hooks:
- id: pyupgrade
- repo: https://github.com/ambv/black
rev: 18.6b4
rev: 18.9b0
hooks:
- id: black
language_version: python3
- repo: https://github.com/PyCQA/flake8
rev: 3.7.7
hooks:
- id: flake8

1
CODEOWNERS Normal file
View File

@ -0,0 +1 @@
/ @syrusakbary @ekampf @dan98765 @projectcheshire

View File

@ -17,7 +17,7 @@ developer has to write to use them.
**New Features!**
* [`InputObjectType`](#inputobjecttype)
* [`Meta as Class arguments`](#meta-ass-class-arguments) (_only available for Python 3_)
* [`Meta as Class arguments`](#meta-as-class-arguments) (_only available for Python 3_)
> The type metaclasses are now deleted as they are no longer necessary. If your code was depending

View File

@ -25,8 +25,8 @@ This example model defines a Person, with a first and a last name:
last_name = graphene.String()
full_name = graphene.String()
def resolve_full_name(self, info):
return '{} {}'.format(self.first_name, self.last_name)
def resolve_full_name(root, info):
return '{} {}'.format(root.first_name, root.last_name)
**first\_name** and **last\_name** are fields of the ObjectType. Each
field is specified as a class attribute, and each attribute maps to a
@ -56,23 +56,148 @@ NOTE: The resolvers on an ``ObjectType`` are always treated as ``staticmethod``\
so the first argument to the resolver method ``self`` (or ``root``) need
not be an actual instance of the ``ObjectType``.
If an explicit resolver is not defined on the ``ObjectType`` then Graphene will
attempt to use a property with the same name on the object that is passed to the
``ObjectType``.
Quick example
~~~~~~~~~~~~~
.. code:: python
This example model defines a ``Query`` type, which has a reverse field
that reverses the given ``word`` argument using the ``resolve_reverse``
method in the class.
import graphene
class Person(graphene.ObjectType):
first_name = graphene.String()
last_name = graphene.String()
class Query(graphene.ObjectType):
me = graphene.Field(Person)
def resolve_me(_, info):
# returns an object that represents a Person
return get_human(name='Luke Skywalker')
If you are passing a dict instead of an object to your ``ObjectType`` you can
change the default resolver in the ``Meta`` class like this:
.. code:: python
import graphene
from graphene.types.resolver import dict_resolver
class Person(graphene.ObjectType):
class Meta:
default_resolver = dict_resolver
first_name = graphene.String()
last_name = graphene.String()
class Query(graphene.ObjectType):
me = graphene.Field(Person)
def resolve_me(_, info):
return {
"first_name": "Luke",
"last_name": "Skywalker",
}
Or you can change the default resolver globally by calling ``set_default_resolver``
before executing a query.
.. code:: python
import graphene
from graphene.types.resolver import dict_resolver, set_default_resolver
set_default_resolver(dict_resolver)
schema = graphene.Schema(query=Query)
result = schema.execute('''
query {
me {
firstName
}
}
''')
Resolvers with arguments
~~~~~~~~~~~~~~~~~~~~~~~~
Any arguments that a field defines gets passed to the resolver function as
kwargs. For example:
.. code:: python
import graphene
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String())
human_by_name = graphene.Field(Human, name=graphene.String(required=True))
def resolve_human_by_name(_, info, name):
return get_human(name=name)
You can then execute the following query:
.. code::
query {
humanByName(name: "Luke Skywalker") {
firstName
lastName
}
}
NOTE: if you define an argument for a field that is not required (and in a query
execution it is not provided as an argument) it will not be passed to the
resolver function at all. This is so that the developer can differenciate
between a ``undefined`` value for an argument and an explicit ``null`` value.
For example, given this schema:
.. code:: python
import graphene
class Query(graphene.ObjectType):
hello = graphene.String(required=True, name=graphene.String())
def resolve_hello(_, info, name):
return name if name else 'World'
And this query:
.. code::
query {
hello
}
An error will be thrown:
.. code::
TypeError: resolve_hello() missing 1 required positional argument: 'name'
You can fix this error in 2 ways. Either by combining all keyword arguments
into a dict:
.. code:: python
class Query(graphene.ObjectType):
hello = graphene.String(required=True, name=graphene.String())
def resolve_hello(_, info, **args):
return args.get('name', 'World')
Or by setting a default value for the keyword argument:
.. code:: python
class Query(graphene.ObjectType):
hello = graphene.String(required=True, name=graphene.String())
def resolve_hello(_, info, name='World'):
return name
def resolve_reverse(self, info, word):
return word[::-1]
Resolvers outside the class
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -83,11 +208,13 @@ A field can use a custom resolver from outside the class:
import graphene
def reverse(root, info, word):
return word[::-1]
def resolve_full_name(person, info):
return '{} {}'.format(person.first_name, person.last_name)
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String(), resolver=reverse)
class Person(graphene.ObjectType):
first_name = graphene.String()
last_name = graphene.String()
full_name = graphene.String(resolver=resolve_full_name)
Instances as data containers

View File

@ -707,7 +707,10 @@ class Signature(object):
break
elif param.name in kwargs:
if param.kind == _POSITIONAL_ONLY:
msg = "{arg!r} parameter is positional only, " "but was passed as a keyword"
msg = (
"{arg!r} parameter is positional only, "
"but was passed as a keyword"
)
msg = msg.format(arg=param.name)
raise TypeError(msg)
parameters_ex = (param,)

View File

@ -75,9 +75,7 @@ def to_arguments(args, extra_args=None):
arg_name = default_name or arg.name
assert (
arg_name not in arguments
), 'More than one Argument have same name "{}".'.format(
arg_name
)
), 'More than one Argument have same name "{}".'.format(arg_name)
arguments[arg_name] = arg
return arguments

View File

@ -1,5 +1,9 @@
from ..utils.subclass_with_meta import SubclassWithMeta
from ..utils.trim_docstring import trim_docstring
import six
if six.PY3:
from typing import Type
class BaseOptions(object):

View File

@ -4,6 +4,9 @@ from graphql.language.ast import BooleanValue, FloatValue, IntValue, StringValue
from .base import BaseOptions, BaseType
from .unmountedtype import UnmountedType
if six.PY3:
from typing import Any
class ScalarOptions(BaseOptions):
pass

View File

@ -1,5 +1,3 @@
from ..argument import Argument
from ..enum import Enum
from ..field import Field

View File

@ -1,4 +1,3 @@
from ..argument import Argument
from ..field import Field
from ..inputfield import InputField

View File

@ -1,4 +1,3 @@
from ..json import JSONString
from ..objecttype import ObjectType
from ..schema import Schema

View File

@ -1,4 +1,3 @@
from ..field import Field
from ..scalars import String

View File

@ -1,4 +1,3 @@
from ..resolver import (
attr_resolver,
dict_resolver,

View File

@ -1,4 +1,3 @@
from ..scalars import Scalar

View File

@ -18,4 +18,4 @@ def to_snake_case(name):
def to_const(string):
return re.sub("[\W|^]+", "_", string).upper()
return re.sub(r"[\W|^]+", "_", string).upper() # noqa

View File

@ -1,4 +1,5 @@
import ast
import codecs
import re
import sys
@ -61,7 +62,9 @@ setup(
name="graphene",
version=version,
description="GraphQL Framework for Python",
long_description=open("README.rst").read(),
long_description=codecs.open(
"README.rst", "r", encoding="ascii", errors="replace"
).read(),
url="https://github.com/graphql-python/graphene",
author="Syrus Akbary",
author_email="me@syrusakbary.com",