mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-13 10:00:39 +03:00
* Integrate async tests into main code * Added full support for subscriptions * Fixed syntax using black * Fixed typo
139 lines
5.2 KiB
Python
139 lines
5.2 KiB
Python
import inspect
|
|
from collections.abc import Mapping
|
|
from functools import partial
|
|
|
|
from .argument import Argument, to_arguments
|
|
from .mountedtype import MountedType
|
|
from .resolver import default_resolver
|
|
from .structures import NonNull
|
|
from .unmountedtype import UnmountedType
|
|
from .utils import get_type
|
|
from ..utils.deprecated import warn_deprecation
|
|
|
|
base_type = type
|
|
|
|
|
|
def source_resolver(source, root, info, **args):
|
|
resolved = default_resolver(source, None, root, info, **args)
|
|
if inspect.isfunction(resolved) or inspect.ismethod(resolved):
|
|
return resolved()
|
|
return resolved
|
|
|
|
|
|
class Field(MountedType):
|
|
"""
|
|
Makes a field available on an ObjectType in the GraphQL schema. Any type can be mounted as a
|
|
Field:
|
|
|
|
- Object Type
|
|
- Scalar Type
|
|
- Enum
|
|
- Interface
|
|
- Union
|
|
|
|
All class attributes of ``graphene.ObjectType`` are implicitly mounted as Field using the below
|
|
arguments.
|
|
|
|
.. code:: python
|
|
|
|
class Person(ObjectType):
|
|
first_name = graphene.String(required=True) # implicitly mounted as Field
|
|
last_name = graphene.Field(String, description='Surname') # explicitly mounted as Field
|
|
|
|
args:
|
|
type (class for a graphene.UnmountedType): Must be a class (not an instance) of an
|
|
unmounted graphene type (ex. scalar or object) which is used for the type of this
|
|
field in the GraphQL schema.
|
|
args (optional, Dict[str, graphene.Argument]): Arguments that can be input to the field.
|
|
Prefer to use ``**extra_args``, unless you use an argument name that clashes with one
|
|
of the Field arguments presented here (see :ref:`example<ResolverParamGraphQLArguments>`).
|
|
resolver (optional, Callable): A function to get the value for a Field from the parent
|
|
value object. If not set, the default resolver method for the schema is used.
|
|
source (optional, str): attribute name to resolve for this field from the parent value
|
|
object. Alternative to resolver (cannot set both source and resolver).
|
|
deprecation_reason (optional, str): Setting this value indicates that the field is
|
|
depreciated and may provide instruction or reason on how for clients to proceed.
|
|
required (optional, bool): indicates this field as not null in the graphql schema. Same behavior as
|
|
graphene.NonNull. Default False.
|
|
name (optional, str): the name of the GraphQL field (must be unique in a type). Defaults to attribute
|
|
name.
|
|
description (optional, str): the description of the GraphQL field in the schema.
|
|
default_value (optional, Any): Default value to resolve if none set from schema.
|
|
**extra_args (optional, Dict[str, Union[graphene.Argument, graphene.UnmountedType]): any
|
|
additional arguments to mount on the field.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
type_,
|
|
args=None,
|
|
resolver=None,
|
|
source=None,
|
|
deprecation_reason=None,
|
|
name=None,
|
|
description=None,
|
|
required=False,
|
|
_creation_counter=None,
|
|
default_value=None,
|
|
**extra_args,
|
|
):
|
|
super(Field, self).__init__(_creation_counter=_creation_counter)
|
|
assert not args or isinstance(
|
|
args, Mapping
|
|
), f'Arguments in a field have to be a mapping, received "{args}".'
|
|
assert not (
|
|
source and resolver
|
|
), "A Field cannot have a source and a resolver in at the same time."
|
|
assert not callable(
|
|
default_value
|
|
), f'The default value can not be a function but received "{base_type(default_value)}".'
|
|
|
|
if required:
|
|
type_ = NonNull(type_)
|
|
|
|
# Check if name is actually an argument of the field
|
|
if isinstance(name, (Argument, UnmountedType)):
|
|
extra_args["name"] = name
|
|
name = None
|
|
|
|
# Check if source is actually an argument of the field
|
|
if isinstance(source, (Argument, UnmountedType)):
|
|
extra_args["source"] = source
|
|
source = None
|
|
|
|
self.name = name
|
|
self._type = type_
|
|
self.args = to_arguments(args or {}, extra_args)
|
|
if source:
|
|
resolver = partial(source_resolver, source)
|
|
self.resolver = resolver
|
|
self.deprecation_reason = deprecation_reason
|
|
self.description = description
|
|
self.default_value = default_value
|
|
|
|
@property
|
|
def type(self):
|
|
return get_type(self._type)
|
|
|
|
get_resolver = None
|
|
|
|
def wrap_resolve(self, parent_resolver):
|
|
"""
|
|
Wraps a function resolver, using the ObjectType resolve_{FIELD_NAME}
|
|
(parent_resolver) if the Field definition has no resolver.
|
|
"""
|
|
if self.get_resolver is not None:
|
|
warn_deprecation(
|
|
"The get_resolver method is being deprecated, please rename it to wrap_resolve."
|
|
)
|
|
return self.get_resolver(parent_resolver)
|
|
|
|
return self.resolver or parent_resolver
|
|
|
|
def wrap_subscribe(self, parent_subscribe):
|
|
"""
|
|
Wraps a function subscribe, using the ObjectType subscribe_{FIELD_NAME}
|
|
(parent_subscribe) if the Field definition has no subscribe.
|
|
"""
|
|
return parent_subscribe
|