From 54df11f9a08f94fedf9b2661f4c2ec748697572d Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sat, 23 Jun 2018 12:08:11 -0700 Subject: [PATCH 01/12] Added initial version of static typing --- .gitignore | 4 + conftest.py | 30 + graphql/backend/__init__.py | 5 + graphql/backend/base.py | 24 +- graphql/backend/cache.py | 22 +- graphql/backend/compiled.py | 29 +- graphql/backend/core.py | 38 +- graphql/backend/decider.py | 10 +- graphql/backend/tests/test_base.py | 3 + graphql/backend/tests/test_cache.py | 2 + .../backend/tests/test_compileddocument.py | 2 + graphql/backend/tests/test_core.py | 5 + graphql/backend/tests/test_decider.py | 8 + graphql/backend/tests/test_document.py | 7 + graphql/error/__init__.py | 2 +- graphql/error/base.py | 36 +- graphql/error/format_error.py | 17 +- graphql/error/located_error.py | 26 +- graphql/error/syntax_error.py | 17 +- graphql/error/tests/test_base.py | 8 + graphql/execution/__init__.py | 12 +- graphql/execution/base.py | 83 +- graphql/execution/executor.py | 419 +++-- graphql/execution/executors/asyncio.py | 21 +- graphql/execution/executors/asyncio_utils.py | 6 +- graphql/execution/executors/gevent.py | 1 - graphql/execution/executors/process.py | 1 - graphql/execution/executors/sync.py | 7 +- graphql/execution/executors/thread.py | 7 +- graphql/execution/executors/utils.py | 13 +- graphql/execution/middleware.py | 24 +- graphql/execution/tests/test_abstract.py | 280 ++-- graphql/execution/tests/test_benchmark.py | 76 +- graphql/execution/tests/test_dataloader.py | 159 +- graphql/execution/tests/test_directives.py | 148 +- .../execution/tests/test_execute_schema.py | 230 ++- graphql/execution/tests/test_executor.py | 57 +- .../execution/tests/test_executor_asyncio.py | 102 +- .../execution/tests/test_executor_gevent.py | 63 +- .../execution/tests/test_executor_thread.py | 272 +-- graphql/execution/tests/test_lists.py | 465 +++-- graphql/execution/tests/test_located_error.py | 13 +- graphql/execution/tests/test_mutations.py | 148 +- graphql/execution/tests/test_nonnull.py | 840 ++++++---- graphql/execution/tests/test_resolve.py | 221 ++- graphql/execution/tests/test_subscribe.py | 395 +++-- .../execution/tests/test_union_interface.py | 250 +-- graphql/execution/tests/test_variables.py | 746 +++++---- graphql/execution/tests/utils.py | 4 + graphql/execution/utils.py | 195 ++- graphql/execution/values.py | 85 +- graphql/graphql.py | 29 +- graphql/language/ast.py | 1489 +++++++++-------- graphql/language/lexer.py | 223 +-- graphql/language/location.py | 20 +- graphql/language/parser.py | 367 ++-- graphql/language/printer.py | 260 ++- graphql/language/source.py | 1 + graphql/language/tests/test_ast.py | 3 + graphql/language/tests/test_lexer.py | 13 + graphql/language/tests/test_location.py | 1 + graphql/language/tests/test_parser.py | 16 + graphql/language/tests/test_printer.py | 8 + graphql/language/tests/test_schema_parser.py | 19 + graphql/language/tests/test_schema_printer.py | 4 + graphql/language/tests/test_visitor.py | 155 +- graphql/language/tests/test_visitor_meta.py | 2 + graphql/language/visitor.py | 118 +- graphql/pyutils/cached_property.py | 7 +- graphql/pyutils/contain_subset.py | 10 +- graphql/pyutils/default_ordered_dict.py | 17 +- graphql/pyutils/ordereddict.py | 2 +- graphql/pyutils/pair_set.py | 9 +- graphql/pyutils/tests/test_contain_subset.py | 154 +- graphql/type/definition.py | 400 +++-- graphql/type/introspection.py | 882 ++++++---- graphql/type/scalars.py | 13 + graphql/type/schema.py | 84 +- graphql/type/typemap.py | 55 +- graphql/utils/assert_valid_name.py | 10 +- graphql/utils/ast_from_value.py | 17 +- graphql/utils/ast_to_code.py | 30 +- graphql/utils/ast_to_dict.py | 13 +- graphql/utils/base.py | 44 +- graphql/utils/build_ast_schema.py | 217 ++- graphql/utils/build_client_schema.py | 274 +-- graphql/utils/concat_ast.py | 12 +- graphql/utils/extend_schema.py | 171 +- graphql/utils/get_field_def.py | 36 +- graphql/utils/get_operation_ast.py | 5 + graphql/utils/introspection_query.py | 4 +- graphql/utils/is_valid_literal_value.py | 41 +- graphql/utils/is_valid_value.py | 28 +- graphql/utils/quoted_or_list.py | 15 +- graphql/utils/schema_printer.py | 169 +- graphql/utils/type_comparators.py | 53 +- graphql/utils/type_from_ast.py | 8 +- graphql/utils/type_info.py | 98 +- graphql/utils/undefined.py | 4 +- graphql/utils/value_from_ast.py | 34 +- .../rules/arguments_of_correct_type.py | 30 +- graphql/validation/rules/base.py | 6 +- .../rules/default_values_of_correct_type.py | 49 +- .../rules/fields_on_correct_type.py | 69 +- .../rules/fragments_on_composite_types.py | 43 +- .../validation/rules/known_argument_names.py | 73 +- graphql/validation/rules/known_type_names.py | 12 +- .../rules/lone_anonymous_operation.py | 32 +- .../validation/rules/no_fragment_cycles.py | 35 +- .../rules/no_undefined_variables.py | 40 +- .../validation/rules/no_unused_fragments.py | 34 +- .../validation/rules/no_unused_variables.py | 44 +- .../rules/overlapping_fields_can_be_merged.py | 390 +++-- .../rules/possible_fragment_spreads.py | 60 +- .../rules/provided_non_null_arguments.py | 47 +- graphql/validation/rules/scalar_leafs.py | 38 +- .../validation/rules/unique_argument_names.py | 38 +- .../validation/rules/unique_fragment_names.py | 28 +- .../rules/unique_input_field_names.py | 48 +- .../rules/unique_operation_names.py | 28 +- .../validation/rules/unique_variable_names.py | 28 +- .../rules/variables_in_allowed_position.py | 47 +- graphql/validation/validation.py | 53 +- setup.cfg | 5 +- 124 files changed, 8027 insertions(+), 4532 deletions(-) create mode 100644 conftest.py diff --git a/.gitignore b/.gitignore index af2acb26..8cfb7608 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,7 @@ target/ # OS X .DS_Store +/.mypy_cache +.pyre +/.vscode +/type_info.json diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..a36e6ba1 --- /dev/null +++ b/conftest.py @@ -0,0 +1,30 @@ +# Configuration for pytest to automatically collect types. +# Thanks to Guilherme Salgado. +import pytest + +try: + import pyannotate_runtime + PYANOTATE_PRESENT = True +except ImportError: + PYANOTATE_PRESENT = False + +if PYANOTATE_PRESENT: + def pytest_collection_finish(session): + """Handle the pytest collection finish hook: configure pyannotate. + Explicitly delay importing `collect_types` until all tests have + been collected. This gives gevent a chance to monkey patch the + world before importing pyannotate. + """ + from pyannotate_runtime import collect_types + collect_types.init_types_collection() + + @pytest.fixture(autouse=True) + def collect_types_fixture(): + from pyannotate_runtime import collect_types + collect_types.resume() + yield + collect_types.pause() + + def pytest_sessionfinish(session, exitstatus): + from pyannotate_runtime import collect_types + collect_types.dump_stats("type_info.json") diff --git a/graphql/backend/__init__.py b/graphql/backend/__init__.py index bda60818..b3d714f0 100644 --- a/graphql/backend/__init__.py +++ b/graphql/backend/__init__.py @@ -9,10 +9,14 @@ from .decider import GraphQLDeciderBackend from .cache import GraphQLCachedBackend +if False: + from typing import Union + _default_backend = None def get_default_backend(): + # type: () -> GraphQLCoreBackend global _default_backend if _default_backend is None: _default_backend = GraphQLCoreBackend() @@ -20,6 +24,7 @@ def get_default_backend(): def set_default_backend(backend): + # type: (GraphQLCoreBackend) -> None global _default_backend assert isinstance( backend, GraphQLBackend diff --git a/graphql/backend/base.py b/graphql/backend/base.py index 42598668..909942ac 100644 --- a/graphql/backend/base.py +++ b/graphql/backend/base.py @@ -4,6 +4,11 @@ from abc import ABCMeta, abstractmethod import six +if False: + from typing import Dict, Optional, Union, Callable + from ..language.ast import Document + from ..type.schema import GraphQLSchema + class GraphQLBackend(six.with_metaclass(ABCMeta)): @abstractmethod @@ -15,6 +20,7 @@ def document_from_string(self, schema, request_string): class GraphQLDocument(object): def __init__(self, schema, document_string, document_ast, execute): + # type: (GraphQLSchema, str, Document, Callable) -> None self.schema = schema self.document_string = document_string self.document_ast = document_ast @@ -22,28 +28,30 @@ def __init__(self, schema, document_string, document_ast, execute): @cached_property def operations_map(self): - ''' + # type: () -> Dict[Union[str, None], str] + """ returns a Mapping of operation names and it's associated types. E.g. {'myQuery': 'query', 'myMutation': 'mutation'} - ''' + """ document_ast = self.document_ast - operations = {} + operations = {} # type: Dict[Union[str, None], str] for definition in document_ast.definitions: if isinstance(definition, ast.OperationDefinition): if definition.name: - operation_name = definition.name.value + operations[definition.name.value] = definition.operation else: - operation_name = None - operations[operation_name] = definition.operation + operations[None] = definition.operation + return operations def get_operation_type(self, operation_name): - ''' + # type: (Optional[str]) -> Optional[str] + """ Returns the operation type ('query', 'mutation', 'subscription' or None) for the given operation_name. If no operation_name is provided (and only one operation exists) it will return the operation type for that operation - ''' + """ operations_map = self.operations_map if not operation_name and len(operations_map) == 1: return next(iter(operations_map.values())) diff --git a/graphql/backend/cache.py b/graphql/backend/cache.py index aa1631fb..683d976e 100644 --- a/graphql/backend/cache.py +++ b/graphql/backend/cache.py @@ -4,12 +4,17 @@ from .base import GraphQLBackend -_cached_schemas = {} +if False: + from typing import Any, Dict, Optional, Union, Tuple, Hashable + from .base import GraphQLDocument -_cached_queries = {} +_cached_schemas = {} # type: Dict[GraphQLSchema, str] + +_cached_queries = {} # type: Dict[str, str] def get_unique_schema_id(schema): + # type: (GraphQLSchema) -> str """Get a unique id given a GraphQLSchema""" assert isinstance(schema, GraphQLSchema), ( "Must receive a GraphQLSchema as schema. Received {}" @@ -21,6 +26,7 @@ def get_unique_schema_id(schema): def get_unique_document_id(query_str): + # type: (str) -> str """Get a unique id given a query_string""" assert isinstance(query_str, string_types), ( "Must receive a string as query_str. Received {}" @@ -32,7 +38,13 @@ def get_unique_document_id(query_str): class GraphQLCachedBackend(GraphQLBackend): - def __init__(self, backend, cache_map=None, use_consistent_hash=False): + def __init__( + self, + backend, # type: GraphQLBackend + cache_map=None, # type: Optional[Dict[Hashable, GraphQLDocument]] + use_consistent_hash=False, # type: bool + ): + # type: (...) -> None assert isinstance( backend, GraphQLBackend ), "Provided backend must be an instance of GraphQLBackend" @@ -43,14 +55,16 @@ def __init__(self, backend, cache_map=None, use_consistent_hash=False): self.use_consistent_hash = use_consistent_hash def get_key_for_schema_and_document_string(self, schema, request_string): + # type: (GraphQLSchema, str) -> int """This method returns a unique key given a schema and a request_string""" if self.use_consistent_hash: schema_id = get_unique_schema_id(schema) document_id = get_unique_document_id(request_string) - return (schema_id, document_id) + return hash((schema_id, document_id)) return hash((schema, request_string)) def document_from_string(self, schema, request_string): + # type: (GraphQLSchema, str) -> Optional[GraphQLDocument] """This method returns a GraphQLQuery (from cache if present)""" key = self.get_key_for_schema_and_document_string(schema, request_string) if key not in self.cache_map: diff --git a/graphql/backend/compiled.py b/graphql/backend/compiled.py index f074cecf..d7950bc9 100644 --- a/graphql/backend/compiled.py +++ b/graphql/backend/compiled.py @@ -1,26 +1,38 @@ from six import string_types from .base import GraphQLDocument +if False: + from ..type.schema import GraphQLSchema + from typing import Any, Optional, Dict, Callable, Union + class GraphQLCompiledDocument(GraphQLDocument): @classmethod - def from_code(cls, schema, code, uptodate=None, extra_namespace=None): + def from_code( + cls, + schema, # type: GraphQLSchema + code, # type: Union[str, Any] + uptodate=None, # type: Optional[bool] + extra_namespace=None, # type: Optional[Dict[str, Any]] + ): + # type: (...) -> GraphQLCompiledDocument """Creates a GraphQLDocument object from compiled code and the globals. This is used by the loaders and schema to create a document object. """ if isinstance(code, string_types): - filename = '' - code = compile(code, filename, 'exec') + filename = "" + code = compile(code, filename, "exec") namespace = {"__file__": code.co_filename} exec(code, namespace) if extra_namespace: namespace.update(extra_namespace) rv = cls._from_namespace(schema, namespace) - rv._uptodate = uptodate + # rv._uptodate = uptodate return rv @classmethod def from_module_dict(cls, schema, module_dict): + # type: (GraphQLSchema, Dict[str, Any]) -> GraphQLCompiledDocument """Creates a template object from a module. This is used by the module loader to create a document object. """ @@ -28,12 +40,13 @@ def from_module_dict(cls, schema, module_dict): @classmethod def _from_namespace(cls, schema, namespace): - document_string = namespace.get("document_string", "") - document_ast = namespace.get("document_ast") - execute = namespace["execute"] + # type: (GraphQLSchema, Dict[str, Any]) -> GraphQLCompiledDocument + document_string = namespace.get("document_string", "") # type: str + document_ast = namespace.get("document_ast") # type: ignore + execute = namespace["execute"] # type: Callable namespace["schema"] = schema - return cls( + return cls( # type: ignore schema=schema, document_string=document_string, document_ast=document_ast, diff --git a/graphql/backend/core.py b/graphql/backend/core.py index 7cbb9d3e..53796fa7 100644 --- a/graphql/backend/core.py +++ b/graphql/backend/core.py @@ -8,35 +8,51 @@ from .base import GraphQLBackend, GraphQLDocument - -def execute_and_validate(schema, document_ast, *args, **kwargs): - do_validation = kwargs.get('validate', True) +if False: + from typing import Any, Optional, Union + from .base import GraphQLDocument + from ..language.ast import Document + from ..type.schema import GraphQLSchema + from ..execution.base import ExecutionResult + from rx.core.anonymousobservable import AnonymousObservable + + +def execute_and_validate( + schema, # type: GraphQLSchema + document_ast, # type: Document + *args, # type: Any + **kwargs # type: Any +): + # type: (...) -> Union[ExecutionResult, AnonymousObservable] + do_validation = kwargs.get("validate", True) if do_validation: validation_errors = validate(schema, document_ast) if validation_errors: - return ExecutionResult( - errors=validation_errors, - invalid=True, - ) + return ExecutionResult(errors=validation_errors, invalid=True) return execute(schema, document_ast, *args, **kwargs) class GraphQLCoreBackend(GraphQLBackend): - def __init__(self, executor=None, **kwargs): - super(GraphQLCoreBackend, self).__init__(**kwargs) + def __init__(self, executor=None): + # type: (Optional[Any]) -> None self.execute_params = {"executor": executor} def document_from_string(self, schema, document_string): + # type: (GraphQLSchema, Union[Document, str]) -> GraphQLDocument if isinstance(document_string, ast.Document): document_ast = document_string document_string = print_ast(document_ast) else: - assert isinstance(document_string, string_types), "The query must be a string" + assert isinstance( + document_string, string_types + ), "The query must be a string" document_ast = parse(document_string) return GraphQLDocument( schema=schema, document_string=document_string, document_ast=document_ast, - execute=partial(execute_and_validate, schema, document_ast, **self.execute_params), + execute=partial( + execute_and_validate, schema, document_ast, **self.execute_params + ), ) diff --git a/graphql/backend/decider.py b/graphql/backend/decider.py index e923b0ce..c4d1b3b4 100644 --- a/graphql/backend/decider.py +++ b/graphql/backend/decider.py @@ -1,8 +1,13 @@ -from .base import GraphQLBackend +from .base import GraphQLBackend, GraphQLDocument + +if False: + from typing import List, Union, Any, Optional + from ..type.schema import GraphQLSchema class GraphQLDeciderBackend(GraphQLBackend): - def __init__(self, backends=None): + def __init__(self, backends): + # type: (List[GraphQLBackend], ) -> None if not backends: raise Exception("Need to provide backends to decide into.") if not isinstance(backends, (list, tuple)): @@ -11,6 +16,7 @@ def __init__(self, backends=None): super(GraphQLDeciderBackend, self).__init__() def document_from_string(self, schema, request_string): + # type: (GraphQLSchema, str) -> GraphQLDocument for backend in self.backends: try: return backend.document_from_string(schema, request_string) diff --git a/graphql/backend/tests/test_base.py b/graphql/backend/tests/test_base.py index 063f3e89..c084c91c 100644 --- a/graphql/backend/tests/test_base.py +++ b/graphql/backend/tests/test_base.py @@ -3,11 +3,13 @@ def test_get_default_backend_returns_core_by_default(): + # type: () -> None backend = get_default_backend() assert isinstance(backend, GraphQLCoreBackend) def test_set_default_backend(): + # type: () -> None default_backend = get_default_backend() new_backend = GraphQLCoreBackend() assert new_backend != default_backend @@ -16,6 +18,7 @@ def test_set_default_backend(): def test_set_default_backend_fails_if_invalid_backend(): + # type: () -> None default_backend = get_default_backend() with pytest.raises(Exception) as exc_info: set_default_backend(object()) diff --git a/graphql/backend/tests/test_cache.py b/graphql/backend/tests/test_cache.py index a2814691..3f25345a 100644 --- a/graphql/backend/tests/test_cache.py +++ b/graphql/backend/tests/test_cache.py @@ -11,6 +11,7 @@ def test_cached_backend(): + # type: () -> None cached_backend = GraphQLCachedBackend(GraphQLCoreBackend()) document1 = cached_backend.document_from_string(schema, "{ hello }") document2 = cached_backend.document_from_string(schema, "{ hello }") @@ -18,6 +19,7 @@ def test_cached_backend(): def test_cached_backend_with_use_consistent_hash(): + # type: () -> None cached_backend = GraphQLCachedBackend(GraphQLCoreBackend(), use_consistent_hash=True) document1 = cached_backend.document_from_string(schema, "{ hello }") document2 = cached_backend.document_from_string(schema, "{ hello }") diff --git a/graphql/backend/tests/test_compileddocument.py b/graphql/backend/tests/test_compileddocument.py index d581b7d9..892af9bd 100644 --- a/graphql/backend/tests/test_compileddocument.py +++ b/graphql/backend/tests/test_compileddocument.py @@ -5,6 +5,7 @@ def test_compileddocument_from_module_dict(): + # type: () -> None document_string = '{ hello }' document_ast = parse(document_string) document = GraphQLCompiledDocument.from_module_dict(schema, { @@ -22,6 +23,7 @@ def test_compileddocument_from_module_dict(): def test_compileddocument_from_code(): + # type: () -> None document_string = '{ hello }' document_ast = parse(document_string) code = ''' diff --git a/graphql/backend/tests/test_core.py b/graphql/backend/tests/test_core.py index 43fb8357..89cc2bc0 100644 --- a/graphql/backend/tests/test_core.py +++ b/graphql/backend/tests/test_core.py @@ -8,9 +8,11 @@ from ..base import GraphQLBackend, GraphQLDocument from ..core import GraphQLCoreBackend from .schema import schema +from typing import Any def test_core_backend(): + # type: () -> None """Sample pytest test function with the pytest fixture as an argument.""" backend = GraphQLCoreBackend() assert isinstance(backend, GraphQLBackend) @@ -22,6 +24,7 @@ def test_core_backend(): def test_backend_is_not_cached_by_default(): + # type: () -> None """Sample pytest test function with the pytest fixture as an argument.""" backend = GraphQLCoreBackend() document1 = backend.document_from_string(schema, "{ hello }") @@ -33,11 +36,13 @@ class BaseExecutor(SyncExecutor): executed = False def execute(self, *args, **kwargs): + # type: (*Any, **Any) -> str self.executed = True return super(BaseExecutor, self).execute(*args, **kwargs) def test_backend_can_execute_custom_executor(): + # type: () -> None executor = BaseExecutor() backend = GraphQLCoreBackend(executor=executor) document1 = backend.document_from_string(schema, "{ hello }") diff --git a/graphql/backend/tests/test_decider.py b/graphql/backend/tests/test_decider.py index 7ec38a4b..4e2fa62c 100644 --- a/graphql/backend/tests/test_decider.py +++ b/graphql/backend/tests/test_decider.py @@ -10,24 +10,29 @@ from ..decider import GraphQLDeciderBackend from .schema import schema +from typing import Any class FakeBackend(GraphQLBackend): reached = False def __init__(self, raises=False): + # type: (bool) -> None self.raises = raises def document_from_string(self, *args, **kwargs): + # type: (*Any, **Any) -> None self.reached = True if self.raises: raise Exception("Backend failed") def reset(self): + # type: () -> None self.reached = False def test_decider_backend_healthy_backend(): + # type: () -> None backend1 = FakeBackend() backend2 = FakeBackend() decider_backend = GraphQLDeciderBackend([backend1, backend2]) @@ -38,6 +43,7 @@ def test_decider_backend_healthy_backend(): def test_decider_backend_unhealthy_backend(): + # type: () -> None backend1 = FakeBackend(raises=True) backend2 = FakeBackend() decider_backend = GraphQLDeciderBackend([backend1, backend2]) @@ -48,6 +54,7 @@ def test_decider_backend_unhealthy_backend(): def test_decider_backend_dont_use_cache(): + # type: () -> None backend1 = FakeBackend() backend2 = FakeBackend() decider_backend = GraphQLDeciderBackend([backend1, backend2]) @@ -62,6 +69,7 @@ def test_decider_backend_dont_use_cache(): def test_decider_backend_use_cache_if_provided(): + # type: () -> None backend1 = FakeBackend() backend2 = FakeBackend() decider_backend = GraphQLDeciderBackend( diff --git a/graphql/backend/tests/test_document.py b/graphql/backend/tests/test_document.py index 7f24ecda..aaf4c619 100644 --- a/graphql/backend/tests/test_document.py +++ b/graphql/backend/tests/test_document.py @@ -1,9 +1,11 @@ from ...language.base import parse from ..base import GraphQLDocument from .schema import schema +from graphql.backend.base import GraphQLDocument def create_document(document_string): + # type: (str) -> GraphQLDocument document_ast = parse(document_string) return GraphQLDocument( schema=schema, @@ -14,6 +16,7 @@ def create_document(document_string): def test_document_operations_map_unnamed_operation(): + # type: () -> None document = create_document('{ hello }') assert document.operations_map == { None: 'query' @@ -32,6 +35,7 @@ def test_document_operations_map_multiple_queries(): def test_document_operations_map_multiple_queries(): + # type: () -> None document = create_document(''' query MyQuery { hello } mutation MyMutation { hello } @@ -45,6 +49,7 @@ def test_document_operations_map_multiple_queries(): def test_document_get_operation_type_unnamed_operation(): + # type: () -> None document = create_document(''' query { hello } ''') @@ -53,6 +58,7 @@ def test_document_get_operation_type_unnamed_operation(): def test_document_get_operation_type_multiple_operations(): + # type: () -> None document = create_document(''' query MyQuery { hello } mutation MyMutation {hello} @@ -64,6 +70,7 @@ def test_document_get_operation_type_multiple_operations(): def test_document_get_operation_type_multiple_operations_empty_operation_name(): + # type: () -> None document = create_document(''' query MyQuery { hello } mutation {hello} diff --git a/graphql/error/__init__.py b/graphql/error/__init__.py index fdcf8149..7a627711 100644 --- a/graphql/error/__init__.py +++ b/graphql/error/__init__.py @@ -3,4 +3,4 @@ from .syntax_error import GraphQLSyntaxError from .format_error import format_error -__all__ = ['GraphQLError', 'GraphQLLocatedError', 'GraphQLSyntaxError', 'format_error'] +__all__ = ["GraphQLError", "GraphQLLocatedError", "GraphQLSyntaxError", "format_error"] diff --git a/graphql/error/base.py b/graphql/error/base.py index b894ecd5..d1310acd 100644 --- a/graphql/error/base.py +++ b/graphql/error/base.py @@ -1,11 +1,36 @@ import six from ..language.location import get_location +if False: + from ..language.source import Source + from ..language.location import SourceLocation + from types import TracebackType + from typing import Optional, List, Any, Union + class GraphQLError(Exception): - __slots__ = 'message', 'nodes', 'stack', 'original_error', '_source', '_positions', '_locations', 'path' + __slots__ = ( + "message", + "nodes", + "stack", + "original_error", + "_source", + "_positions", + "_locations", + "path", + ) - def __init__(self, message, nodes=None, stack=None, source=None, positions=None, locations=None, path=None): + def __init__( + self, + message, # type: str + nodes=None, # type: Any + stack=None, # type: Optional[TracebackType] + source=None, # type: Optional[Any] + positions=None, # type: Optional[Any] + locations=None, # type: Optional[Any] + path=None, # type: Union[List[Union[int, str]], List[str], None] + ): + # type: (...) -> None super(GraphQLError, self).__init__(message) self.message = message self.nodes = nodes @@ -14,25 +39,31 @@ def __init__(self, message, nodes=None, stack=None, source=None, positions=None, self._positions = positions self._locations = locations self.path = path + return None @property def source(self): + # type: () -> Optional[Source] if self._source: return self._source if self.nodes: node = self.nodes[0] return node and node.loc and node.loc.source + return None @property def positions(self): + # type: () -> Optional[List[int]] if self._positions: return self._positions if self.nodes is not None: node_positions = [node.loc and node.loc.start for node in self.nodes] if any(node_positions): return node_positions + return None def reraise(self): + # type: () -> None if self.stack: six.reraise(type(self), self, self.stack) else: @@ -40,6 +71,7 @@ def reraise(self): @property def locations(self): + # type: () -> Optional[List[SourceLocation]] if not self._locations: source = self.source if self.positions and source: diff --git a/graphql/error/format_error.py b/graphql/error/format_error.py index ab0b2d80..4592e850 100644 --- a/graphql/error/format_error.py +++ b/graphql/error/format_error.py @@ -2,18 +2,21 @@ from .base import GraphQLError +if False: + from .base import GraphQLError + from .located_error import GraphQLLocatedError + from typing import Any, Dict, Union + def format_error(error): - formatted_error = { - 'message': text_type(error), - } + # type: (Union[GraphQLError, GraphQLLocatedError]) -> Dict[str, Any] + formatted_error = {"message": text_type(error)} if isinstance(error, GraphQLError): if error.locations is not None: - formatted_error['locations'] = [ - {'line': loc.line, 'column': loc.column} - for loc in error.locations + formatted_error["locations"] = [ + {"line": loc.line, "column": loc.column} for loc in error.locations ] if error.path is not None: - formatted_error['path'] = error.path + formatted_error["path"] = error.path return formatted_error diff --git a/graphql/error/located_error.py b/graphql/error/located_error.py index 351989e2..ea4284d4 100644 --- a/graphql/error/located_error.py +++ b/graphql/error/located_error.py @@ -2,29 +2,35 @@ from .base import GraphQLError -__all__ = ['GraphQLLocatedError'] +if False: + from ..language.ast import Field + from typing import List, Union +__all__ = ["GraphQLLocatedError"] -class GraphQLLocatedError(GraphQLError): - def __init__(self, nodes, original_error=None, path=None): +class GraphQLLocatedError(GraphQLError): + def __init__( + self, + nodes, # type: List[Field] + original_error=None, # type: Exception + path=None, # type: Union[List[Union[int, str]], List[str]] + ): + # type: (...) -> None if original_error: try: message = str(original_error) except UnicodeEncodeError: - message = original_error.message.encode('utf-8') + message = original_error.message.encode("utf-8") else: - message = 'An unknown error occurred.' + message = "An unknown error occurred." - if hasattr(original_error, 'stack'): + if hasattr(original_error, "stack"): stack = original_error.stack else: stack = sys.exc_info()[2] super(GraphQLLocatedError, self).__init__( - message=message, - nodes=nodes, - stack=stack, - path=path + message=message, nodes=nodes, stack=stack, path=path ) self.original_error = original_error diff --git a/graphql/error/syntax_error.py b/graphql/error/syntax_error.py index 607467d5..480c1fb7 100644 --- a/graphql/error/syntax_error.py +++ b/graphql/error/syntax_error.py @@ -1,15 +1,19 @@ from ..language.location import get_location from .base import GraphQLError -__all__ = ['GraphQLSyntaxError'] +if False: + from ..language.source import Source + from ..language.location import SourceLocation +__all__ = ["GraphQLSyntaxError"] -class GraphQLSyntaxError(GraphQLError): +class GraphQLSyntaxError(GraphQLError): def __init__(self, source, position, description): + # type: (Source, int, str) -> None location = get_location(source, position) super(GraphQLSyntaxError, self).__init__( - message=u'Syntax Error {} ({}:{}) {}\n\n{}'.format( + message=u"Syntax Error {} ({}:{}) {}\n\n{}".format( source.name, location.line, location.column, @@ -22,16 +26,17 @@ def __init__(self, source, position, description): def highlight_source_at_location(source, location): + # type: (Source, SourceLocation) -> str line = location.line lines = source.body.splitlines() pad_len = len(str(line + 1)) - result = u'' - format = (u'{:>' + str(pad_len) + '}: {}\n').format + result = u"" + format = (u"{:>" + str(pad_len) + "}: {}\n").format if line >= 2: result += format(line - 1, lines[line - 2]) if line <= len(lines): result += format(line, lines[line - 1]) - result += ' ' * (1 + pad_len + location.column) + '^\n' + result += " " * (1 + pad_len + location.column) + "^\n" if line < len(lines): result += format(line + 1, lines[line]) return result diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index c686a0f6..d91b3a18 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -5,12 +5,18 @@ from graphql.language.parser import parse from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString) +from graphql.execution.base import ResolveInfo +from mypy_extensions import NoReturn +from typing import Any +from typing import Optional def test_raise(): + # type: () -> None ast = parse('query Example { a }') def resolver(context, *_): + # type: (Optional[Any], *ResolveInfo) -> NoReturn raise Exception('Failed') Type = GraphQLObjectType('Type', { @@ -22,9 +28,11 @@ def resolver(context, *_): def test_reraise(): + # type: () -> None ast = parse('query Example { a }') def resolver(context, *_): + # type: (Optional[Any], *ResolveInfo) -> NoReturn raise Exception('Failed') Type = GraphQLObjectType('Type', { diff --git a/graphql/execution/__init__.py b/graphql/execution/__init__.py index a2de1f33..d6c2a7f7 100644 --- a/graphql/execution/__init__.py +++ b/graphql/execution/__init__.py @@ -24,10 +24,10 @@ __all__ = [ - 'execute', - 'subscribe', - 'ExecutionResult', - 'ResolveInfo', - 'MiddlewareManager', - 'middlewares' + "execute", + "subscribe", + "ExecutionResult", + "ResolveInfo", + "MiddlewareManager", + "middlewares", ] diff --git a/graphql/execution/base.py b/graphql/execution/base.py index a209dc8b..985c24c3 100644 --- a/graphql/execution/base.py +++ b/graphql/execution/base.py @@ -8,19 +8,26 @@ does_fragment_condition_match, get_field_entry_key, default_resolve_fn, - get_field_def + get_field_def, ) from ..error.format_error import format_error as default_format_error +if False: + from typing import Any, Optional, Dict, List, Union + from ..language.ast import Field, OperationDefinition + from ..type.definition import GraphQLList, GraphQLObjectType, GraphQLScalarType + from ..type.schema import GraphQLSchema + class ExecutionResult(object): """The result of execution. `data` is the result of executing the query, `errors` is null if no errors occurred, and is a non-empty array if an error occurred.""" - __slots__ = 'data', 'errors', 'invalid', 'extensions' + __slots__ = "data", "errors", "invalid", "extensions" def __init__(self, data=None, errors=None, invalid=False, extensions=None): + # type: (Any, Any, bool, Optional[Any]) -> None self.data = data self.errors = errors self.extensions = extensions or dict() @@ -31,13 +38,11 @@ def __init__(self, data=None, errors=None, invalid=False, extensions=None): self.invalid = invalid def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ExecutionResult) and - self.data == other.data and - self.errors == other.errors and - self.invalid == other.invalid - ) + return self is other or ( + isinstance(other, ExecutionResult) + and self.data == other.data + and self.errors == other.errors + and self.invalid == other.invalid ) def to_dict(self, format_error=None, dict_class=dict): @@ -46,20 +51,44 @@ def to_dict(self, format_error=None, dict_class=dict): response = dict_class() if self.errors: - response['errors'] = [format_error(e) for e in self.errors] + response["errors"] = [format_error(e) for e in self.errors] if not self.invalid: - response['data'] = self.data + response["data"] = self.data return response class ResolveInfo(object): - __slots__ = ('field_name', 'field_asts', 'return_type', 'parent_type', - 'schema', 'fragments', 'root_value', 'operation', 'variable_values', 'context', 'path') - - def __init__(self, field_name, field_asts, return_type, parent_type, - schema, fragments, root_value, operation, variable_values, context, path=None): + __slots__ = ( + "field_name", + "field_asts", + "return_type", + "parent_type", + "schema", + "fragments", + "root_value", + "operation", + "variable_values", + "context", + "path", + ) + + def __init__( + self, + field_name, # type: str + field_asts, # type: List[Field] + return_type, # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType] + parent_type, # type: GraphQLObjectType + schema, # type: GraphQLSchema + fragments, # type: Dict + root_value, # type: Optional[type] + operation, # type: OperationDefinition + variable_values, # type: Dict + context, # type: Optional[Any] + path=None, # type: Union[List[Union[int, str]], List[str]] + ): + # type: (...) -> None self.field_name = field_name self.field_asts = field_asts self.return_type = return_type @@ -74,15 +103,15 @@ def __init__(self, field_name, field_asts, return_type, parent_type, __all__ = [ - 'ExecutionResult', - 'ResolveInfo', - 'ExecutionContext', - 'SubscriberExecutionContext', - 'get_operation_root_type', - 'collect_fields', - 'should_include_node', - 'does_fragment_condition_match', - 'get_field_entry_key', - 'default_resolve_fn', - 'get_field_def', + "ExecutionResult", + "ResolveInfo", + "ExecutionContext", + "SubscriberExecutionContext", + "get_operation_root_type", + "collect_fields", + "should_include_node", + "does_fragment_condition_match", + "get_field_entry_key", + "default_resolve_fn", + "get_field_def", ] diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index fd5cea65..82e802bf 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -12,52 +12,84 @@ from ..pyutils.default_ordered_dict import DefaultOrderedDict from ..pyutils.ordereddict import OrderedDict from ..utils.undefined import Undefined -from ..type import (GraphQLEnumType, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, - GraphQLSchema, GraphQLUnionType) -from .base import (ExecutionContext, ExecutionResult, ResolveInfo, - collect_fields, default_resolve_fn, get_field_def, - get_operation_root_type, SubscriberExecutionContext) +from ..type import ( + GraphQLEnumType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLUnionType, +) +from .base import ( + ExecutionContext, + ExecutionResult, + ResolveInfo, + collect_fields, + default_resolve_fn, + get_field_def, + get_operation_root_type, + SubscriberExecutionContext, +) from .executors.sync import SyncExecutor from .middleware import MiddlewareManager +if False: + from typing import Any, Optional, Union, Dict, List, Callable + from rx.core.anonymousobservable import AnonymousObservable + from ..type.schema import GraphQLSchema + from ..language.ast import Document, OperationDefinition, Field + logger = logging.getLogger(__name__) def subscribe(*args, **kwargs): - allow_subscriptions = kwargs.pop('allow_subscriptions', True) + # type: (*Any, **Any) -> Union[ExecutionResult, AnonymousObservable] + allow_subscriptions = kwargs.pop("allow_subscriptions", True) return execute(*args, allow_subscriptions=allow_subscriptions, **kwargs) -def execute(schema, document_ast, root=None, context=None, - variables=None, operation_name=None, executor=None, - return_promise=False, middleware=None, allow_subscriptions=False, **options): - - if root is None and 'root_value' in options: +def execute( + schema, # type: GraphQLSchema + document_ast, # type: Document + root=None, # type: Any + context=None, # type: Optional[Any] + variables=None, # type: Optional[Any] + operation_name=None, # type: Optional[str] + executor=None, # type: Any + return_promise=False, # type: bool + middleware=None, # type: Optional[Any] + allow_subscriptions=False, # type: bool + **options # type: Any +): + # type: (...) -> ExecutionResult + + if root is None and "root_value" in options: warnings.warn( - 'root_value has been deprecated. Please use root=... instead.', + "root_value has been deprecated. Please use root=... instead.", category=DeprecationWarning, - stacklevel=2 + stacklevel=2, ) - root = options['root_value'] - if context is None and 'context_value' in options: + root = options["root_value"] + if context is None and "context_value" in options: warnings.warn( - 'context_value has been deprecated. Please use context=... instead.', + "context_value has been deprecated. Please use context=... instead.", category=DeprecationWarning, - stacklevel=2 + stacklevel=2, ) - context = options['context_value'] - if variables is None and 'variable_values' in options: + context = options["context_value"] + if variables is None and "variable_values" in options: warnings.warn( - 'variable_values has been deprecated. Please use values=... instead.', + "variable_values has been deprecated. Please use values=... instead.", category=DeprecationWarning, - stacklevel=2 + stacklevel=2, ) - variables = options['variable_values'] - assert schema, 'Must provide schema' + variables = options["variable_values"] + assert schema, "Must provide schema" assert isinstance(schema, GraphQLSchema), ( - 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + - 'not multiple versions of GraphQL installed in your node_modules directory.' + "Schema must be an instance of GraphQLSchema. Also ensure that there are " + + "not multiple versions of GraphQL installed in your node_modules directory." ) if middleware: @@ -65,7 +97,7 @@ def execute(schema, document_ast, root=None, context=None, middleware = MiddlewareManager(*middleware) assert isinstance(middleware, MiddlewareManager), ( - 'middlewares have to be an instance' + "middlewares have to be an instance" ' of MiddlewareManager. Received "{}".'.format(middleware) ) @@ -81,17 +113,20 @@ def execute(schema, document_ast, root=None, context=None, operation_name, executor, middleware, - allow_subscriptions + allow_subscriptions, ) - def executor(v): + def executor(v): # type: Optional[Any] + # type: (...) -> Union[OrderedDict, Promise, AnonymousObservable] return execute_operation(exe_context, exe_context.operation, root) - def on_rejected(error): + def on_rejected(error): # type: Union[Exception, GraphQLError, GraphQLLocatedError] + # type: (...) -> Optional[Any] exe_context.errors.append(error) return None - def on_resolve(data): + def on_resolve(data): # type: Union[None, OrderedDict, AnonymousObservable] + # type: (...) -> Union[ExecutionResult, AnonymousObservable] if isinstance(data, Observable): return data @@ -106,40 +141,49 @@ def on_resolve(data): exe_context.executor.wait_until_finished() return promise.get() else: - clean = getattr(exe_context.executor, 'clean', None) + clean = getattr(exe_context.executor, "clean", None) if clean: clean() return promise -def execute_operation(exe_context, operation, root_value): +def execute_operation( + exe_context, # type: ExecutionContext + operation, # type: OperationDefinition + root_value, # type: Union[None, Data, type] +): + # type: (...) -> Union[OrderedDict, Promise] type = get_operation_root_type(exe_context.schema, operation) fields = collect_fields( - exe_context, - type, - operation.selection_set, - DefaultOrderedDict(list), - set() + exe_context, type, operation.selection_set, DefaultOrderedDict(list), set() ) - if operation.operation == 'mutation': + if operation.operation == "mutation": return execute_fields_serially(exe_context, type, root_value, [], fields) - if operation.operation == 'subscription': + if operation.operation == "subscription": if not exe_context.allow_subscriptions: raise Exception( "Subscriptions are not allowed. " "You will need to either use the subscribe function " "or pass allow_subscriptions=True" ) - return subscribe_fields(exe_context, type, root_value, fields,) + return subscribe_fields(exe_context, type, root_value, fields) return execute_fields(exe_context, type, root_value, fields, [], None) -def execute_fields_serially(exe_context, parent_type, source_value, path, fields): +def execute_fields_serially( + exe_context, # type: ExecutionContext + parent_type, # type: GraphQLObjectType + source_value, # type: Any + path, # type: List + fields, # type: DefaultOrderedDict +): + # type: (...) -> Promise def execute_field_callback(results, response_name): + # type: (OrderedDict, str) -> Union[OrderedDict, Promise] field_asts = fields[response_name] result = resolve_field( exe_context, @@ -147,13 +191,15 @@ def execute_field_callback(results, response_name): source_value, field_asts, None, - path+[response_name] + path + [response_name], ) if result is Undefined: return results if is_thenable(result): + def collect_result(resolved_result): + # type: (OrderedDict) -> OrderedDict results[response_name] = resolved_result return results @@ -163,18 +209,38 @@ def collect_result(resolved_result): return results def execute_field(prev_promise, response_name): - return prev_promise.then(lambda results: execute_field_callback(results, response_name)) + # type: (Promise, str) -> Promise + return prev_promise.then( + lambda results: execute_field_callback(results, response_name) + ) - return functools.reduce(execute_field, fields.keys(), Promise.resolve(collections.OrderedDict())) + return functools.reduce( + execute_field, fields.keys(), Promise.resolve(collections.OrderedDict()) + ) -def execute_fields(exe_context, parent_type, source_value, fields, path, info): +def execute_fields( + exe_context, # type: ExecutionContext + parent_type, # type: GraphQLObjectType + source_value, # type: Any + fields, # type: DefaultOrderedDict + path, # type: Union[List[Union[int, str]], List[str]] + info, # type: Optional[ResolveInfo] +): + # type: (...) -> Union[OrderedDict, Promise] contains_promise = False final_results = OrderedDict() for response_name, field_asts in fields.items(): - result = resolve_field(exe_context, parent_type, source_value, field_asts, info, path + [response_name]) + result = resolve_field( + exe_context, + parent_type, + source_value, + field_asts, + info, + path + [response_name], + ) if result is Undefined: continue @@ -188,13 +254,22 @@ def execute_fields(exe_context, parent_type, source_value, fields, path, info): return promise_for_dict(final_results) -def subscribe_fields(exe_context, parent_type, source_value, fields): +def subscribe_fields( + exe_context, # type: ExecutionContext + parent_type, # type: GraphQLObjectType + source_value, # type: Union[None, Data, type] + fields, # type: DefaultOrderedDict +): + # type: (...) -> AnonymousObservable exe_context = SubscriberExecutionContext(exe_context) def on_error(error): exe_context.report_error(error) - def map_result(data): + def map_result( + data # type: Union[Dict[str, None], Dict[str, OrderedDict], Dict[str, str]] + ): + # type: (...) -> ExecutionResult if exe_context.errors: result = ExecutionResult(data=data, errors=exe_context.errors) else: @@ -207,7 +282,9 @@ def map_result(data): # assert len(fields) == 1, "Can only subscribe one element at a time." for response_name, field_asts in fields.items(): - result = subscribe_field(exe_context, parent_type, source_value, field_asts, [response_name]) + result = subscribe_field( + exe_context, parent_type, source_value, field_asts, [response_name] + ) if result is Undefined: continue @@ -217,14 +294,23 @@ def catch_error(error): # Map observable results observable = result.catch_exception(catch_error).map( - lambda data: map_result({response_name: data})) + lambda data: map_result({response_name: data}) + ) return observable observables.append(observable) return Observable.merge(observables) -def resolve_field(exe_context, parent_type, source, field_asts, parent_info, field_path): +def resolve_field( + exe_context, # type: ExecutionContext + parent_type, # type: GraphQLObjectType + source, # type: Union[None, Cat, Dog] + field_asts, # type: List[Field] + parent_info, # type: Optional[ResolveInfo] + field_path, # type: Union[List[Union[int, str]], List[str]] +): + # type: (...) -> Any field_ast = field_asts[0] field_name = field_ast.name.value @@ -260,23 +346,25 @@ def resolve_field(exe_context, parent_type, source, field_asts, parent_info, fie operation=exe_context.operation, variable_values=exe_context.variable_values, context=context, - path=field_path + path=field_path, ) executor = exe_context.executor result = resolve_or_error(resolve_fn_middleware, source, info, args, executor) return complete_value_catching_error( - exe_context, - return_type, - field_asts, - info, - field_path, - result + exe_context, return_type, field_asts, info, field_path, result ) -def subscribe_field(exe_context, parent_type, source, field_asts, path): +def subscribe_field( + exe_context, # type: SubscriberExecutionContext + parent_type, # type: GraphQLObjectType + source, # type: Union[None, Data, type] + field_asts, # type: List[Field] + path, # type: List[str] +): + # type: (...) -> AnonymousObservable field_ast = field_asts[0] field_name = field_ast.name.value @@ -312,42 +400,63 @@ def subscribe_field(exe_context, parent_type, source, field_asts, path): operation=exe_context.operation, variable_values=exe_context.variable_values, context=context, - path=path + path=path, ) executor = exe_context.executor - result = resolve_or_error(resolve_fn_middleware, - source, info, args, executor) + result = resolve_or_error(resolve_fn_middleware, source, info, args, executor) if isinstance(result, Exception): raise result if not isinstance(result, Observable): raise GraphQLError( - 'Subscription must return Async Iterable or Observable. Received: {}'.format(repr(result))) + "Subscription must return Async Iterable or Observable. Received: {}".format( + repr(result) + ) + ) - return result.map(functools.partial( - complete_value_catching_error, - exe_context, - return_type, - field_asts, - info, - path, - )) + return result.map( + functools.partial( + complete_value_catching_error, + exe_context, + return_type, + field_asts, + info, + path, + ) + ) -def resolve_or_error(resolve_fn, source, info, args, executor): +def resolve_or_error( + resolve_fn, # type: Callable + source, # type: Union[None, Cat, Dog] + info, # type: ResolveInfo + args, # type: Dict + executor, # type: Union[BaseExecutor, SyncExecutor] +): + # type: (...) -> Union[List[Union[Cat, Dog]], bool, str] try: return executor.execute(resolve_fn, source, info, **args) except Exception as e: - logger.exception("An error occurred while resolving field {}.{}".format( - info.parent_type.name, info.field_name - )) + logger.exception( + "An error occurred while resolving field {}.{}".format( + info.parent_type.name, info.field_name + ) + ) e.stack = sys.exc_info()[2] return e -def complete_value_catching_error(exe_context, return_type, field_asts, info, path, result): +def complete_value_catching_error( + exe_context, # type: ExecutionContext + return_type, # type: Any + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: Union[List[Union[int, str]], List[str]] + result, # type: Any +): + # type: (...) -> Union[bool, str] # If the field type is non-nullable, then it is resolved without any # protection from errors. if isinstance(return_type, GraphQLNonNull): @@ -356,9 +465,13 @@ def complete_value_catching_error(exe_context, return_type, field_asts, info, pa # Otherwise, error protection is applied, logging the error and # resolving a null value for this field if one is encountered. try: - completed = complete_value(exe_context, return_type, field_asts, info, path, result) + completed = complete_value( + exe_context, return_type, field_asts, info, path, result + ) if is_thenable(completed): + def handle_error(error): + # type: (Union[GraphQLError, GraphQLLocatedError]) -> Optional[Any] traceback = completed._traceback exe_context.report_error(error, traceback) return None @@ -372,7 +485,15 @@ def handle_error(error): return None -def complete_value(exe_context, return_type, field_asts, info, path, result): +def complete_value( + exe_context, # type: ExecutionContext + return_type, # type: Any + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: Union[List[Union[int, str]], List[str]] + result, # type: Any +): + # type: (...) -> Union[bool, str] """ Implements the instructions for completeValue as defined in the "Field entries" section of the spec. @@ -396,15 +517,11 @@ def complete_value(exe_context, return_type, field_asts, info, path, result): if is_thenable(result): return Promise.resolve(result).then( lambda resolved: complete_value( - exe_context, - return_type, - field_asts, - info, - path, - resolved + exe_context, return_type, field_asts, info, path, resolved ), lambda error: Promise.rejected( - GraphQLLocatedError(field_asts, original_error=error, path=path)) + GraphQLLocatedError(field_asts, original_error=error, path=path) + ), ) # print return_type, type(result) @@ -412,7 +529,9 @@ def complete_value(exe_context, return_type, field_asts, info, path, result): raise GraphQLLocatedError(field_asts, original_error=result, path=path) if isinstance(return_type, GraphQLNonNull): - return complete_nonnull_value(exe_context, return_type, field_asts, info, path, result) + return complete_nonnull_value( + exe_context, return_type, field_asts, info, path, result + ) # If result is null-like, return null. if result is None: @@ -420,7 +539,9 @@ def complete_value(exe_context, return_type, field_asts, info, path, result): # If field type is List, complete each item in the list with the inner type if isinstance(return_type, GraphQLList): - return complete_list_value(exe_context, return_type, field_asts, info, path, result) + return complete_list_value( + exe_context, return_type, field_asts, info, path, result + ) # If field type is Scalar or Enum, serialize to a valid value, returning # null if coercion is not possible. @@ -428,22 +549,33 @@ def complete_value(exe_context, return_type, field_asts, info, path, result): return complete_leaf_value(return_type, path, result) if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)): - return complete_abstract_value(exe_context, return_type, field_asts, info, path, result) + return complete_abstract_value( + exe_context, return_type, field_asts, info, path, result + ) if isinstance(return_type, GraphQLObjectType): - return complete_object_value(exe_context, return_type, field_asts, info, path, result) + return complete_object_value( + exe_context, return_type, field_asts, info, path, result + ) - assert False, u'Cannot complete value of unexpected type "{}".'.format( - return_type) + assert False, u'Cannot complete value of unexpected type "{}".'.format(return_type) -def complete_list_value(exe_context, return_type, field_asts, info, path, result): +def complete_list_value( + exe_context, # type: ExecutionContext + return_type, # type: GraphQLList + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: List[str] + result, # type: Any +): + # type: (...) -> Any """ Complete a list value by completing each item in the list with the inner type """ - assert isinstance(result, collections.Iterable), \ - ('User Error: expected iterable, but did not find one ' + - 'for field {}.{}.').format(info.parent_type, info.field_name) + assert isinstance(result, collections.Iterable), ( + "User Error: expected iterable, but did not find one " + "for field {}.{}." + ).format(info.parent_type, info.field_name) item_type = return_type.of_type completed_results = [] @@ -451,7 +583,9 @@ def complete_list_value(exe_context, return_type, field_asts, info, path, result index = 0 for item in result: - completed_item = complete_value_catching_error(exe_context, item_type, field_asts, info, path + [index], item, ) + completed_item = complete_value_catching_error( + exe_context, item_type, field_asts, info, path + [index], item + ) if not contains_promise and is_thenable(completed_item): contains_promise = True @@ -461,23 +595,37 @@ def complete_list_value(exe_context, return_type, field_asts, info, path, result return Promise.all(completed_results) if contains_promise else completed_results -def complete_leaf_value(return_type, path, result): +def complete_leaf_value( + return_type, # type: Union[GraphQLEnumType, GraphQLScalarType] + path, # type: Union[List[Union[int, str]], List[str]] + result, # type: Union[int, str] +): + # type: (...) -> Union[int, str] """ Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible. """ - assert hasattr(return_type, 'serialize'), 'Missing serialize method on type' + assert hasattr(return_type, "serialize"), "Missing serialize method on type" serialized_result = return_type.serialize(result) if serialized_result is None: raise GraphQLError( - ('Expected a value of type "{}" but ' + - 'received: {}').format(return_type, result), - path=path + ('Expected a value of type "{}" but ' + "received: {}").format( + return_type, result + ), + path=path, ) return serialized_result -def complete_abstract_value(exe_context, return_type, field_asts, info, path, result): +def complete_abstract_value( + exe_context, # type: ExecutionContext + return_type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: List[Union[int, str]] + result, # type: Any +): + # type: (...) -> OrderedDict """ Complete an value of an abstract type by determining the runtime type of that value, then completing based on that type. @@ -489,51 +637,65 @@ def complete_abstract_value(exe_context, return_type, field_asts, info, path, re if return_type.resolve_type: runtime_type = return_type.resolve_type(result, info) else: - runtime_type = get_default_resolve_type_fn( - result, info, return_type) + runtime_type = get_default_resolve_type_fn(result, info, return_type) if isinstance(runtime_type, string_types): runtime_type = info.schema.get_type(runtime_type) if not isinstance(runtime_type, GraphQLObjectType): raise GraphQLError( - ('Abstract type {} must resolve to an Object type at runtime ' + - 'for field {}.{} with value "{}", received "{}".').format( - return_type, - info.parent_type, - info.field_name, - result, - runtime_type, + ( + "Abstract type {} must resolve to an Object type at runtime " + + 'for field {}.{} with value "{}", received "{}".' + ).format( + return_type, info.parent_type, info.field_name, result, runtime_type ), - field_asts + field_asts, ) if not exe_context.schema.is_possible_type(return_type, runtime_type): raise GraphQLError( u'Runtime Object type "{}" is not a possible type for "{}".'.format( - runtime_type, return_type), - field_asts + runtime_type, return_type + ), + field_asts, ) - return complete_object_value(exe_context, runtime_type, field_asts, info, path, result) + return complete_object_value( + exe_context, runtime_type, field_asts, info, path, result + ) -def get_default_resolve_type_fn(value, info, abstract_type): +def get_default_resolve_type_fn( + value, # type: Any + info, # type: ResolveInfo + abstract_type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] +): + # type: (...) -> GraphQLObjectType possible_types = info.schema.get_possible_types(abstract_type) for type in possible_types: if callable(type.is_type_of) and type.is_type_of(value, info): return type -def complete_object_value(exe_context, return_type, field_asts, info, path, result): +def complete_object_value( + exe_context, # type: ExecutionContext + return_type, # type: GraphQLObjectType + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: Union[List[Union[int, str]], List[str]] + result, # type: Any +): + # type: (...) -> Union[OrderedDict, Promise] """ Complete an Object value by evaluating all sub-selections. """ if return_type.is_type_of and not return_type.is_type_of(result, info): raise GraphQLError( u'Expected value of type "{}" but got: {}.'.format( - return_type, type(result).__name__), - field_asts + return_type, type(result).__name__ + ), + field_asts, ) # Collect sub-fields to execute to complete this value. @@ -541,7 +703,15 @@ def complete_object_value(exe_context, return_type, field_asts, info, path, resu return execute_fields(exe_context, return_type, result, subfield_asts, path, info) -def complete_nonnull_value(exe_context, return_type, field_asts, info, path, result): +def complete_nonnull_value( + exe_context, # type: ExecutionContext + return_type, # type: GraphQLNonNull + field_asts, # type: List[Field] + info, # type: ResolveInfo + path, # type: Union[List[Union[int, str]], List[str]] + result, # type: Any +): + # type: (...) -> Any """ Complete a NonNull value by completing the inner type """ @@ -550,10 +720,11 @@ def complete_nonnull_value(exe_context, return_type, field_asts, info, path, res ) if completed is None: raise GraphQLError( - 'Cannot return null for non-nullable field {}.{}.'.format( - info.parent_type, info.field_name), + "Cannot return null for non-nullable field {}.{}.".format( + info.parent_type, info.field_name + ), field_asts, - path=path + path=path, ) return completed diff --git a/graphql/execution/executors/asyncio.py b/graphql/execution/executors/asyncio.py index 13f19028..afb8a968 100644 --- a/graphql/execution/executors/asyncio.py +++ b/graphql/execution/executors/asyncio.py @@ -4,6 +4,10 @@ from promise import Promise +if False: + from asyncio.unix_events import _UnixSelectorEventLoop + from typing import Optional, Any, Callable + try: from asyncio import ensure_future except ImportError: @@ -15,7 +19,7 @@ def ensure_future(coro_or_future, loop=None): """ if isinstance(coro_or_future, Future): if loop is not None and loop is not coro_or_future._loop: - raise ValueError('loop argument must agree with Future') + raise ValueError("loop argument must agree with Future") return coro_or_future elif iscoroutine(coro_or_future): if loop is None: @@ -25,26 +29,30 @@ def ensure_future(coro_or_future, loop=None): del task._source_traceback[-1] return task else: - raise TypeError( - 'A Future, a coroutine or an awaitable is required') + raise TypeError("A Future, a coroutine or an awaitable is required") + try: from .asyncio_utils import asyncgen_to_observable, isasyncgen except Exception: - def isasyncgen(obj): False - def asyncgen_to_observable(asyncgen): pass + def isasyncgen(obj): + False + def asyncgen_to_observable(asyncgen): + pass -class AsyncioExecutor(object): +class AsyncioExecutor(object): def __init__(self, loop=None): + # type: (Optional[_UnixSelectorEventLoop]) -> None if loop is None: loop = get_event_loop() self.loop = loop self.futures = [] def wait_until_finished(self): + # type: () -> None # if there are futures to wait for while self.futures: # wait for the futures to finish @@ -56,6 +64,7 @@ def clean(self): self.futures = [] def execute(self, fn, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Any result = fn(*args, **kwargs) if isinstance(result, Future) or iscoroutine(result): future = ensure_future(result, loop=self.loop) diff --git a/graphql/execution/executors/asyncio_utils.py b/graphql/execution/executors/asyncio_utils.py index 077f2299..363e8a55 100644 --- a/graphql/execution/executors/asyncio_utils.py +++ b/graphql/execution/executors/asyncio_utils.py @@ -1,13 +1,11 @@ -from inspect import isasyncgen +from inspect import isasyncgen # type: ignore from asyncio import ensure_future, wait, CancelledError from rx import AnonymousObservable def asyncgen_to_observable(asyncgen, loop=None): def emit(observer): - task = ensure_future( - iterate_asyncgen(asyncgen, observer), - loop=loop) + task = ensure_future(iterate_asyncgen(asyncgen, observer), loop=loop) def dispose(): async def await_task(): diff --git a/graphql/execution/executors/gevent.py b/graphql/execution/executors/gevent.py index cae187e1..4bc5ac4e 100644 --- a/graphql/execution/executors/gevent.py +++ b/graphql/execution/executors/gevent.py @@ -7,7 +7,6 @@ class GeventExecutor(object): - def __init__(self): self.jobs = [] diff --git a/graphql/execution/executors/process.py b/graphql/execution/executors/process.py index 36782b81..948279ae 100644 --- a/graphql/execution/executors/process.py +++ b/graphql/execution/executors/process.py @@ -11,7 +11,6 @@ def queue_process(q): class ProcessExecutor(object): - def __init__(self): self.processes = [] self.q = Queue() diff --git a/graphql/execution/executors/sync.py b/graphql/execution/executors/sync.py index 9f8eff21..58295d1a 100644 --- a/graphql/execution/executors/sync.py +++ b/graphql/execution/executors/sync.py @@ -1,10 +1,15 @@ -class SyncExecutor(object): +if False: + from typing import Any, Callable + +class SyncExecutor(object): def wait_until_finished(self): + # type: () -> None pass def clean(self): pass def execute(self, fn, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Any return fn(*args, **kwargs) diff --git a/graphql/execution/executors/thread.py b/graphql/execution/executors/thread.py index b23d4d4c..9d682b64 100644 --- a/graphql/execution/executors/thread.py +++ b/graphql/execution/executors/thread.py @@ -2,15 +2,18 @@ from threading import Thread from promise import Promise - from .utils import process +if False: + from typing import Any, Callable + class ThreadExecutor(object): pool = None def __init__(self, pool=False): + # type: (bool) -> None self.threads = [] if pool: self.execute = self.execute_in_pool @@ -19,6 +22,7 @@ def __init__(self, pool=False): self.execute = self.execute_in_thread def wait_until_finished(self): + # type: () -> None while self.threads: threads = self.threads self.threads = [] @@ -28,6 +32,7 @@ def clean(self): self.threads = [] def execute_in_thread(self, fn, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Promise promise = Promise() thread = Thread(target=process, args=(promise, fn, args, kwargs)) thread.start() diff --git a/graphql/execution/executors/utils.py b/graphql/execution/executors/utils.py index 5cad2e3c..1cab3ff4 100644 --- a/graphql/execution/executors/utils.py +++ b/graphql/execution/executors/utils.py @@ -1,7 +1,18 @@ from sys import exc_info +if False: + from ..base import ResolveInfo + from promise import Promise + from typing import Callable, Dict, Tuple, Union -def process(p, f, args, kwargs): + +def process( + p, # type: Promise + f, # type: Callable + args, # type: Tuple[Any, ResolveInfo] + kwargs, # type: Dict[str, Any] +): + # type: (...) -> None try: val = f(*args, **kwargs) p.do_resolve(val) diff --git a/graphql/execution/middleware.py b/graphql/execution/middleware.py index ce81da47..0c7f82d3 100644 --- a/graphql/execution/middleware.py +++ b/graphql/execution/middleware.py @@ -4,19 +4,32 @@ from promise import Promise -MIDDLEWARE_RESOLVER_FUNCTION = 'resolve' +if False: + from .base import ResolveInfo + from typing import Any, Callable, Iterator, Tuple, Union, List, Dict + +MIDDLEWARE_RESOLVER_FUNCTION = "resolve" class MiddlewareManager(object): - __slots__ = "middlewares", "wrap_in_promise", "_middleware_resolvers", "_cached_resolvers" + __slots__ = ( + "middlewares", + "wrap_in_promise", + "_middleware_resolvers", + "_cached_resolvers", + ) def __init__(self, *middlewares, **kwargs): + # type: (*Any, **Dict[str, bool]) -> None self.middlewares = middlewares - self.wrap_in_promise = kwargs.get('wrap_in_promise', True) - self._middleware_resolvers = list(get_middleware_resolvers(middlewares)) if middlewares else [] + self.wrap_in_promise = kwargs.get("wrap_in_promise", True) + self._middleware_resolvers = ( + list(get_middleware_resolvers(middlewares)) if middlewares else [] + ) self._cached_resolvers = {} def get_field_resolver(self, field_resolver): + # type: (Callable[[Any, ResolveInfo, ...], Any]) -> Callable[[Any, ResolveInfo, ...], Any] if field_resolver not in self._cached_resolvers: self._cached_resolvers[field_resolver] = middleware_chain( field_resolver, @@ -31,6 +44,7 @@ def get_field_resolver(self, field_resolver): def get_middleware_resolvers(middlewares): + # type: (Tuple[Any]) -> Iterator[Callable] for middleware in middlewares: # If the middleware is a function instead of a class if inspect.isfunction(middleware): @@ -41,6 +55,7 @@ def get_middleware_resolvers(middlewares): def middleware_chain(func, middlewares, wrap_in_promise): + # type: (Callable, List[Callable], bool) -> Callable if not middlewares: return func if wrap_in_promise: @@ -55,4 +70,5 @@ def middleware_chain(func, middlewares, wrap_in_promise): def make_it_promise(next, *a, **b): + # type: (Callable, *Any, **Any) -> Promise return Promise.resolve(next(*a, **b)) diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py index dedd6e44..b8f8b3ee 100644 --- a/graphql/execution/tests/test_abstract.py +++ b/graphql/execution/tests/test_abstract.py @@ -1,35 +1,44 @@ +# type: ignore from graphql import graphql from graphql.type import GraphQLBoolean, GraphQLSchema, GraphQLString -from graphql.type.definition import (GraphQLField, GraphQLInterfaceType, - GraphQLList, GraphQLObjectType, - GraphQLUnionType) +from graphql.type.definition import ( + GraphQLField, + GraphQLInterfaceType, + GraphQLList, + GraphQLObjectType, + GraphQLUnionType, +) class Dog(object): - def __init__(self, name, woofs): + # type: (str, bool) -> None self.name = name self.woofs = woofs class Cat(object): - def __init__(self, name, meows): + # type: (str, bool) -> None self.name = name self.meows = meows class Human(object): - def __init__(self, name): + # type: (str) -> None self.name = name -def is_type_of(type): return lambda obj, info: isinstance(obj, type) +def is_type_of(type): + # type: (type) -> Callable + return lambda obj, info: isinstance(obj, type) def make_type_resolver(types): + # type: (Callable) -> Callable def resolve_type(obj, info): + # type: (Union[Cat, Dog, Human], ResolveInfo) -> GraphQLObjectType if callable(types): t = types() else: @@ -45,47 +54,45 @@ def resolve_type(obj, info): def test_is_type_of_used_to_resolve_runtime_type_for_interface(): + # type: () -> None PetType = GraphQLInterfaceType( - name='Pet', - fields={ - 'name': GraphQLField(GraphQLString) - } + name="Pet", fields={"name": GraphQLField(GraphQLString)} ) DogType = GraphQLObjectType( - name='Dog', + name="Dog", interfaces=[PetType], is_type_of=is_type_of(Dog), fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "woofs": GraphQLField(GraphQLBoolean), + }, ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", interfaces=[PetType], is_type_of=is_type_of(Cat), fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "meows": GraphQLField(GraphQLBoolean), + }, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'pets': GraphQLField( + "pets": GraphQLField( GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)] + resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)], ) - } + }, ), - types=[CatType, DogType] + types=[CatType, DogType], ) - query = ''' + query = """ { pets { name @@ -97,51 +104,51 @@ def test_is_type_of_used_to_resolve_runtime_type_for_interface(): } } } - ''' + """ result = graphql(schema, query) assert not result.errors - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]} + assert result.data == { + "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}] + } def test_is_type_of_used_to_resolve_runtime_type_for_union(): + # type: () -> None DogType = GraphQLObjectType( - name='Dog', + name="Dog", is_type_of=is_type_of(Dog), fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "woofs": GraphQLField(GraphQLBoolean), + }, ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", is_type_of=is_type_of(Cat), fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "meows": GraphQLField(GraphQLBoolean), + }, ) - PetType = GraphQLUnionType( - name='Pet', - types=[CatType, DogType] - ) + PetType = GraphQLUnionType(name="Pet", types=[CatType, DogType]) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'pets': GraphQLField( + "pets": GraphQLField( GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)] + resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)], ) - } + }, ), - types=[CatType, DogType] + types=[CatType, DogType], ) - query = ''' + query = """ { pets { ... on Dog { @@ -154,65 +161,65 @@ def test_is_type_of_used_to_resolve_runtime_type_for_union(): } } } - ''' + """ result = graphql(schema, query) assert not result.errors - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]} + assert result.data == { + "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}] + } def test_resolve_type_on_interface_yields_useful_error(): + # type: () -> None PetType = GraphQLInterfaceType( - name='Pet', - fields={ - 'name': GraphQLField(GraphQLString) - }, - resolve_type=make_type_resolver(lambda: [ - (Dog, DogType), - (Cat, CatType), - (Human, HumanType) - ]) + name="Pet", + fields={"name": GraphQLField(GraphQLString)}, + resolve_type=make_type_resolver( + lambda: [(Dog, DogType), (Cat, CatType), (Human, HumanType)] + ), ) DogType = GraphQLObjectType( - name='Dog', + name="Dog", interfaces=[PetType], fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "woofs": GraphQLField(GraphQLBoolean), + }, ) HumanType = GraphQLObjectType( - name='Human', - fields={ - 'name': GraphQLField(GraphQLString), - } + name="Human", fields={"name": GraphQLField(GraphQLString)} ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", interfaces=[PetType], fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "meows": GraphQLField(GraphQLBoolean), + }, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'pets': GraphQLField( + "pets": GraphQLField( GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')] + resolver=lambda *_: [ + Dog("Odie", True), + Cat("Garfield", False), + Human("Jon"), + ], ) - } + }, ), - types=[DogType, CatType] + types=[DogType, CatType], ) - query = ''' + query = """ { pets { name @@ -224,60 +231,69 @@ def test_resolve_type_on_interface_yields_useful_error(): } } } - ''' + """ result = graphql(schema, query) - assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".' - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]} + assert ( + result.errors[0].message + == 'Runtime Object type "Human" is not a possible type for "Pet".' + ) + assert result.data == { + "pets": [ + {"woofs": True, "name": "Odie"}, + {"name": "Garfield", "meows": False}, + None, + ] + } def test_resolve_type_on_union_yields_useful_error(): + # type: () -> None DogType = GraphQLObjectType( - name='Dog', + name="Dog", fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "woofs": GraphQLField(GraphQLBoolean), + }, ) HumanType = GraphQLObjectType( - name='Human', - fields={ - 'name': GraphQLField(GraphQLString), - } + name="Human", fields={"name": GraphQLField(GraphQLString)} ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "meows": GraphQLField(GraphQLBoolean), + }, ) PetType = GraphQLUnionType( - name='Pet', + name="Pet", types=[DogType, CatType], - resolve_type=make_type_resolver(lambda: [ - (Dog, DogType), - (Cat, CatType), - (Human, HumanType) - ]) + resolve_type=make_type_resolver( + lambda: [(Dog, DogType), (Cat, CatType), (Human, HumanType)] + ), ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'pets': GraphQLField( + "pets": GraphQLField( GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')] + resolver=lambda *_: [ + Dog("Odie", True), + Cat("Garfield", False), + Human("Jon"), + ], ) - } + }, ) ) - query = ''' + query = """ { pets { ... on Dog { @@ -290,61 +306,70 @@ def test_resolve_type_on_union_yields_useful_error(): } } } - ''' + """ result = graphql(schema, query) - assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".' - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]} + assert ( + result.errors[0].message + == 'Runtime Object type "Human" is not a possible type for "Pet".' + ) + assert result.data == { + "pets": [ + {"woofs": True, "name": "Odie"}, + {"name": "Garfield", "meows": False}, + None, + ] + } def test_resolve_type_can_use_type_string(): + # type: () -> None def type_string_resolver(obj, *_): + # type: (Union[Cat, Dog], *ResolveInfo) -> str if isinstance(obj, Dog): - return 'Dog' + return "Dog" if isinstance(obj, Cat): - return 'Cat' + return "Cat" PetType = GraphQLInterfaceType( - name='Pet', - fields={ - 'name': GraphQLField(GraphQLString) - }, - resolve_type=type_string_resolver + name="Pet", + fields={"name": GraphQLField(GraphQLString)}, + resolve_type=type_string_resolver, ) DogType = GraphQLObjectType( - name='Dog', + name="Dog", interfaces=[PetType], fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "woofs": GraphQLField(GraphQLBoolean), + }, ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", interfaces=[PetType], fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } + "name": GraphQLField(GraphQLString), + "meows": GraphQLField(GraphQLBoolean), + }, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'pets': GraphQLField( + "pets": GraphQLField( GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)] + resolver=lambda *_: [Dog("Odie", True), Cat("Garfield", False)], ) - } + }, ), - types=[CatType, DogType] + types=[CatType, DogType], ) - query = ''' + query = """ { pets { name @@ -356,8 +381,11 @@ def type_string_resolver(obj, *_): } } } - ''' + """ result = graphql(schema, query) assert not result.errors - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]} + assert result.data == { + "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}] + } + diff --git a/graphql/execution/tests/test_benchmark.py b/graphql/execution/tests/test_benchmark.py index 8c5e8d75..04b51089 100644 --- a/graphql/execution/tests/test_benchmark.py +++ b/graphql/execution/tests/test_benchmark.py @@ -1,25 +1,37 @@ +# type: ignore from collections import namedtuple from functools import partial -from graphql import (GraphQLField, GraphQLInt, GraphQLList, GraphQLObjectType, - GraphQLSchema, Source, execute, parse) +from graphql import ( + GraphQLField, + GraphQLInt, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + Source, + execute, + parse, +) + # from graphql.execution import executor # executor.use_experimental_executor = True SIZE = 10000 # set global fixtures -Container = namedtuple('Container', 'x y z o') +Container = namedtuple("Container", "x y z o") big_int_list = [x for x in range(SIZE)] big_container_list = [Container(x=x, y=x, z=x, o=x) for x in range(SIZE)] -ContainerType = GraphQLObjectType('Container', +ContainerType = GraphQLObjectType( + "Container", fields={ - 'x': GraphQLField(GraphQLInt), - 'y': GraphQLField(GraphQLInt), - 'z': GraphQLField(GraphQLInt), - 'o': GraphQLField(GraphQLInt), - }) + "x": GraphQLField(GraphQLInt), + "y": GraphQLField(GraphQLInt), + "z": GraphQLField(GraphQLInt), + "o": GraphQLField(GraphQLInt), + }, +) def resolve_all_containers(root, info, **args): @@ -31,14 +43,14 @@ def resolve_all_ints(root, info, **args): def test_big_list_of_ints(benchmark): - Query = GraphQLObjectType('Query', fields={ - 'allInts': GraphQLField( - GraphQLList(GraphQLInt), - resolver=resolve_all_ints - ) - }) + Query = GraphQLObjectType( + "Query", + fields={ + "allInts": GraphQLField(GraphQLList(GraphQLInt), resolver=resolve_all_ints) + }, + ) schema = GraphQLSchema(Query) - source = Source('{ allInts }') + source = Source("{ allInts }") ast = parse(source) @benchmark @@ -55,14 +67,16 @@ def serialize(): def test_big_list_objecttypes_with_one_int_field(benchmark): - Query = GraphQLObjectType('Query', fields={ - 'allContainers': GraphQLField( - GraphQLList(ContainerType), - resolver=resolve_all_containers - ) - }) + Query = GraphQLObjectType( + "Query", + fields={ + "allContainers": GraphQLField( + GraphQLList(ContainerType), resolver=resolve_all_containers + ) + }, + ) schema = GraphQLSchema(Query) - source = Source('{ allContainers { x } }') + source = Source("{ allContainers { x } }") ast = parse(source) @benchmark @@ -71,15 +85,17 @@ def b(): def test_big_list_objecttypes_with_two_int_fields(benchmark): - Query = GraphQLObjectType('Query', fields={ - 'allContainers': GraphQLField( - GraphQLList(ContainerType), - resolver=resolve_all_containers - ) - }) + Query = GraphQLObjectType( + "Query", + fields={ + "allContainers": GraphQLField( + GraphQLList(ContainerType), resolver=resolve_all_containers + ) + }, + ) schema = GraphQLSchema(Query) - source = Source('{ allContainers { x, y } }') + source = Source("{ allContainers { x, y } }") ast = parse(source) @benchmark diff --git a/graphql/execution/tests/test_dataloader.py b/graphql/execution/tests/test_dataloader.py index 7fd4611e..88f292d1 100644 --- a/graphql/execution/tests/test_dataloader.py +++ b/graphql/execution/tests/test_dataloader.py @@ -1,34 +1,55 @@ +# type: ignore import pytest from promise import Promise from promise.dataloader import DataLoader -from graphql import GraphQLObjectType, GraphQLField, GraphQLID, GraphQLArgument, GraphQLNonNull, GraphQLSchema, parse, execute +from graphql import ( + GraphQLObjectType, + GraphQLField, + GraphQLID, + GraphQLArgument, + GraphQLNonNull, + GraphQLSchema, + parse, + execute, +) from graphql.execution.executors.sync import SyncExecutor from graphql.execution.executors.thread import ThreadExecutor -@pytest.mark.parametrize("executor", [ - SyncExecutor(), - # ThreadExecutor(), -]) +@pytest.mark.parametrize( + "executor", + [ + SyncExecutor(), + # ThreadExecutor(), + ], +) def test_batches_correctly(executor): + # type: (SyncExecutor) -> None - Business = GraphQLObjectType('Business', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), - }) - - Query = GraphQLObjectType('Query', lambda: { - 'getBusiness': GraphQLField(Business, - args={ - 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)), - }, - resolver=lambda root, info, **args: info.context.business_data_loader.load(args.get('id')) - ), - }) + Business = GraphQLObjectType( + "Business", + lambda: { + "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root) + }, + ) + + Query = GraphQLObjectType( + "Query", + lambda: { + "getBusiness": GraphQLField( + Business, + args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))}, + resolver=lambda root, info, **args: info.context.business_data_loader.load( + args.get("id") + ), + ) + }, + ) schema = GraphQLSchema(query=Query) - doc = ''' + doc = """ { business1: getBusiness(id: "1") { id @@ -37,13 +58,14 @@ def test_batches_correctly(executor): id } } - ''' + """ doc_ast = parse(doc) load_calls = [] class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): + # type: (List[str]) -> Promise load_calls.append(keys) return Promise.resolve(keys) @@ -52,49 +74,56 @@ class Context(object): result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors - assert result.data == { - 'business1': { - 'id': '1' - }, - 'business2': { - 'id': '2' - }, - } - assert load_calls == [['1', '2']] + assert result.data == {"business1": {"id": "1"}, "business2": {"id": "2"}} + assert load_calls == [["1", "2"]] -@pytest.mark.parametrize("executor", [ - SyncExecutor(), - # ThreadExecutor(), # Fails on pypy :O -]) +@pytest.mark.parametrize( + "executor", + [ + SyncExecutor(), + # ThreadExecutor(), # Fails on pypy :O + ], +) def test_batches_multiple_together(executor): + # type: (SyncExecutor) -> None - Location = GraphQLObjectType('Location', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), - }) - - Business = GraphQLObjectType('Business', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), - 'location': GraphQLField( - Location, - resolver=lambda root, info, **args: info.context.location_data_loader.load( - 'location-{}'.format(root) + Location = GraphQLObjectType( + "Location", + lambda: { + "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root) + }, + ) + + Business = GraphQLObjectType( + "Business", + lambda: { + "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), + "location": GraphQLField( + Location, + resolver=lambda root, info, **args: info.context.location_data_loader.load( + "location-{}".format(root) + ), + ), + }, + ) + + Query = GraphQLObjectType( + "Query", + lambda: { + "getBusiness": GraphQLField( + Business, + args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))}, + resolver=lambda root, info, **args: info.context.business_data_loader.load( + args.get("id") + ), ) - ), - }) - - Query = GraphQLObjectType('Query', lambda: { - 'getBusiness': GraphQLField(Business, - args={ - 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)), - }, - resolver=lambda root, info, **args: info.context.business_data_loader.load(args.get('id')) - ), - }) + }, + ) schema = GraphQLSchema(query=Query) - doc = ''' + doc = """ { business1: getBusiness(id: "1") { id @@ -109,13 +138,14 @@ def test_batches_multiple_together(executor): } } } - ''' + """ doc_ast = parse(doc) business_load_calls = [] class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): + # type: (List[str]) -> Promise business_load_calls.append(keys) return Promise.resolve(keys) @@ -123,6 +153,7 @@ def batch_load_fn(self, keys): class LocationDataLoader(DataLoader): def batch_load_fn(self, keys): + # type: (List[str]) -> Promise location_load_calls.append(keys) return Promise.resolve(keys) @@ -133,18 +164,8 @@ class Context(object): result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors assert result.data == { - 'business1': { - 'id': '1', - 'location': { - 'id': 'location-1' - } - }, - 'business2': { - 'id': '2', - 'location': { - 'id': 'location-2' - } - }, + "business1": {"id": "1", "location": {"id": "location-1"}}, + "business2": {"id": "2", "location": {"id": "location-2"}}, } - assert business_load_calls == [['1', '2']] - assert location_load_calls == [['location-1', 'location-2']] + assert business_load_calls == [["1", "2"]] + assert location_load_calls == [["location-1", "location-2"]] diff --git a/graphql/execution/tests/test_directives.py b/graphql/execution/tests/test_directives.py index 059a8050..7ab221e1 100644 --- a/graphql/execution/tests/test_directives.py +++ b/graphql/execution/tests/test_directives.py @@ -1,60 +1,64 @@ +# type: ignore from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString schema = GraphQLSchema( query=GraphQLObjectType( - name='TestType', - fields={ - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - } + name="TestType", + fields={"a": GraphQLField(GraphQLString), "b": GraphQLField(GraphQLString)}, ) ) class Data(object): - a = 'a' - b = 'b' + a = "a" + b = "b" def execute_test_query(doc): + # type: (str) -> ExecutionResult return execute(schema, parse(doc), Data) def test_basic_query_works(): - result = execute_test_query('{ a, b }') + # type: () -> None + result = execute_test_query("{ a, b }") assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_if_true_includes_scalar(): - result = execute_test_query('{ a, b @include(if: true) }') + # type: () -> None + result = execute_test_query("{ a, b @include(if: true) }") assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_if_false_omits_on_scalar(): - result = execute_test_query('{ a, b @include(if: false) }') + # type: () -> None + result = execute_test_query("{ a, b @include(if: false) }") assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_skip_false_includes_scalar(): - result = execute_test_query('{ a, b @skip(if: false) }') + # type: () -> None + result = execute_test_query("{ a, b @skip(if: false) }") assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_skip_true_omits_scalar(): - result = execute_test_query('{ a, b @skip(if: true) }') + # type: () -> None + result = execute_test_query("{ a, b @skip(if: true) }") assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_if_false_omits_fragment_spread(): - q = ''' + # type: () -> None + q = """ query Q { a ...Frag @include(if: false) @@ -62,14 +66,15 @@ def test_if_false_omits_fragment_spread(): fragment Frag on TestType { b } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_if_true_includes_fragment_spread(): - q = ''' + # type: () -> None + q = """ query Q { a ...Frag @include(if: true) @@ -77,14 +82,15 @@ def test_if_true_includes_fragment_spread(): fragment Frag on TestType { b } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_skip_false_includes_fragment_spread(): - q = ''' + # type: () -> None + q = """ query Q { a ...Frag @skip(if: false) @@ -92,14 +98,15 @@ def test_skip_false_includes_fragment_spread(): fragment Frag on TestType { b } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_skip_true_omits_fragment_spread(): - q = ''' + # type: () -> None + q = """ query Q { a ...Frag @skip(if: true) @@ -107,70 +114,75 @@ def test_skip_true_omits_fragment_spread(): fragment Frag on TestType { b } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_if_false_omits_inline_fragment(): - q = ''' + # type: () -> None + q = """ query Q { a ... on TestType @include(if: false) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_if_true_includes_inline_fragment(): - q = ''' + # type: () -> None + q = """ query Q { a ... on TestType @include(if: true) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_skip_false_includes_inline_fragment(): - q = ''' + # type: () -> None + q = """ query Q { a ... on TestType @skip(if: false) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_skip_true_omits_inline_fragment(): - q = ''' + # type: () -> None + q = """ query Q { a ... on TestType @skip(if: true) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_skip_true_omits_fragment(): - q = ''' + # type: () -> None + q = """ query Q { a ...Frag @@ -178,81 +190,89 @@ def test_skip_true_omits_fragment(): fragment Frag on TestType @skip(if: true) { b } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_skip_on_inline_anonymous_fragment_omits_field(): - q = ''' + # type: () -> None + q = """ query Q { a ... @skip(if: true) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_skip_on_inline_anonymous_fragment_does_not_omit_field(): - q = ''' + # type: () -> None + q = """ query Q { a ... @skip(if: false) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_include_on_inline_anonymous_fragment_omits_field(): - q = ''' + # type: () -> None + q = """ query Q { a ... @include(if: false) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_include_on_inline_anonymous_fragment_does_not_omit_field(): - q = ''' + # type: () -> None + q = """ query Q { a ... @include(if: true) { b } } - ''' + """ result = execute_test_query(q) assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_works_directives_include_and_no_skip(): - result = execute_test_query('{ a, b @include(if: true) @skip(if: false) }') + # type: () -> None + result = execute_test_query("{ a, b @include(if: true) @skip(if: false) }") assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} + assert result.data == {"a": "a", "b": "b"} def test_works_directives_include_and_skip(): - result = execute_test_query('{ a, b @include(if: true) @skip(if: true) }') + # type: () -> None + result = execute_test_query("{ a, b @include(if: true) @skip(if: true) }") assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} def test_works_directives_no_include_or_skip(): - result = execute_test_query('{ a, b @include(if: false) @skip(if: false) }') + # type: () -> None + result = execute_test_query("{ a, b @include(if: false) @skip(if: false) }") assert not result.errors - assert result.data == {'a': 'a'} + assert result.data == {"a": "a"} + diff --git a/graphql/execution/tests/test_execute_schema.py b/graphql/execution/tests/test_execute_schema.py index 16e46465..0c7e1033 100644 --- a/graphql/execution/tests/test_execute_schema.py +++ b/graphql/execution/tests/test_execute_schema.py @@ -1,81 +1,112 @@ +# type: ignore + from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLBoolean, GraphQLField, - GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLField, + GraphQLID, + GraphQLInt, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) def test_executes_using_a_schema(): - BlogImage = GraphQLObjectType('BlogImage', { - 'url': GraphQLField(GraphQLString), - 'width': GraphQLField(GraphQLInt), - 'height': GraphQLField(GraphQLInt), - }) + # type: () -> None + BlogImage = GraphQLObjectType( + "BlogImage", + { + "url": GraphQLField(GraphQLString), + "width": GraphQLField(GraphQLInt), + "height": GraphQLField(GraphQLInt), + }, + ) - BlogAuthor = GraphQLObjectType('Author', lambda: { - 'id': GraphQLField(GraphQLString), - 'name': GraphQLField(GraphQLString), - 'pic': GraphQLField(BlogImage, - args={ - 'width': GraphQLArgument(GraphQLInt), - 'height': GraphQLArgument(GraphQLInt), - }, - resolver=lambda obj, info, **args: - obj.pic(args['width'], args['height']) - ), - 'recentArticle': GraphQLField(BlogArticle), - }) + BlogAuthor = GraphQLObjectType( + "Author", + lambda: { + "id": GraphQLField(GraphQLString), + "name": GraphQLField(GraphQLString), + "pic": GraphQLField( + BlogImage, + args={ + "width": GraphQLArgument(GraphQLInt), + "height": GraphQLArgument(GraphQLInt), + }, + resolver=lambda obj, info, **args: obj.pic( + args["width"], args["height"] + ), + ), + "recentArticle": GraphQLField(BlogArticle), + }, + ) - BlogArticle = GraphQLObjectType('Article', { - 'id': GraphQLField(GraphQLNonNull(GraphQLString)), - 'isPublished': GraphQLField(GraphQLBoolean), - 'author': GraphQLField(BlogAuthor), - 'title': GraphQLField(GraphQLString), - 'body': GraphQLField(GraphQLString), - 'keywords': GraphQLField(GraphQLList(GraphQLString)), - }) + BlogArticle = GraphQLObjectType( + "Article", + { + "id": GraphQLField(GraphQLNonNull(GraphQLString)), + "isPublished": GraphQLField(GraphQLBoolean), + "author": GraphQLField(BlogAuthor), + "title": GraphQLField(GraphQLString), + "body": GraphQLField(GraphQLString), + "keywords": GraphQLField(GraphQLList(GraphQLString)), + }, + ) - BlogQuery = GraphQLObjectType('Query', { - 'article': GraphQLField( - BlogArticle, - args={'id': GraphQLArgument(GraphQLID)}, - resolver=lambda obj, info, **args: Article(args['id'])), - 'feed': GraphQLField( - GraphQLList(BlogArticle), - resolver=lambda *_: map(Article, range(1, 10 + 1))), - }) + BlogQuery = GraphQLObjectType( + "Query", + { + "article": GraphQLField( + BlogArticle, + args={"id": GraphQLArgument(GraphQLID)}, + resolver=lambda obj, info, **args: Article(args["id"]), + ), + "feed": GraphQLField( + GraphQLList(BlogArticle), + resolver=lambda *_: map(Article, range(1, 10 + 1)), + ), + }, + ) BlogSchema = GraphQLSchema(BlogQuery) class Article(object): - def __init__(self, id): + # type: (int) -> None self.id = id self.isPublished = True self.author = Author() - self.title = 'My Article {}'.format(id) - self.body = 'This is a post' - self.hidden = 'This data is not exposed in the schema' - self.keywords = ['foo', 'bar', 1, True, None] + self.title = "My Article {}".format(id) + self.body = "This is a post" + self.hidden = "This data is not exposed in the schema" + self.keywords = ["foo", "bar", 1, True, None] class Author(object): id = 123 - name = 'John Smith' + name = "John Smith" def pic(self, width, height): + # type: (int, int) -> Pic return Pic(123, width, height) @property - def recentArticle(self): return Article(1) + def recentArticle(self): + # type: () -> Article + return Article(1) class Pic(object): - def __init__(self, uid, width, height): - self.url = 'cdn://{}'.format(uid) + # type: (int, int, int) -> None + self.url = "cdn://{}".format(uid) self.width = str(width) self.height = str(height) - request = ''' + request = """ { feed { id, @@ -106,82 +137,41 @@ def __init__(self, uid, width, height): hidden, notdefined } - ''' + """ # Note: this is intentionally not validating to ensure appropriate # behavior occurs when executing an invalid query. result = execute(BlogSchema, parse(request)) assert not result.errors - assert result.data == \ - { - "feed": [ - { + assert result.data == { + "feed": [ + {"id": "1", "title": "My Article 1"}, + {"id": "2", "title": "My Article 2"}, + {"id": "3", "title": "My Article 3"}, + {"id": "4", "title": "My Article 4"}, + {"id": "5", "title": "My Article 5"}, + {"id": "6", "title": "My Article 6"}, + {"id": "7", "title": "My Article 7"}, + {"id": "8", "title": "My Article 8"}, + {"id": "9", "title": "My Article 9"}, + {"id": "10", "title": "My Article 10"}, + ], + "article": { + "id": "1", + "isPublished": True, + "title": "My Article 1", + "body": "This is a post", + "author": { + "id": "123", + "name": "John Smith", + "pic": {"url": "cdn://123", "width": 640, "height": 480}, + "recentArticle": { "id": "1", - "title": "My Article 1" + "isPublished": True, + "title": "My Article 1", + "body": "This is a post", + "keywords": ["foo", "bar", "1", "true", None], }, - { - "id": "2", - "title": "My Article 2" - }, - { - "id": "3", - "title": "My Article 3" - }, - { - "id": "4", - "title": "My Article 4" - }, - { - "id": "5", - "title": "My Article 5" - }, - { - "id": "6", - "title": "My Article 6" - }, - { - "id": "7", - "title": "My Article 7" - }, - { - "id": "8", - "title": "My Article 8" - }, - { - "id": "9", - "title": "My Article 9" - }, - { - "id": "10", - "title": "My Article 10" - } - ], - "article": { - "id": "1", - "isPublished": True, - "title": "My Article 1", - "body": "This is a post", - "author": { - "id": "123", - "name": "John Smith", - "pic": { - "url": "cdn://123", - "width": 640, - "height": 480 - }, - "recentArticle": { - "id": "1", - "isPublished": True, - "title": "My Article 1", - "body": "This is a post", - "keywords": [ - "foo", - "bar", - "1", - "true", - None - ] - } - } - } - } + }, + }, + } diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index 706c1f9a..6d72e494 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -1,3 +1,4 @@ +# type: ignore import json from pytest import raises @@ -12,6 +13,7 @@ def test_executes_arbitary_code(): + # type: () -> None class Data(object): a = 'Apple' b = 'Banana' @@ -21,12 +23,15 @@ class Data(object): f = 'Fish' def pic(self, size=50): + # type: (int) -> str return 'Pic of size: {}'.format(size) def deep(self): + # type: () -> DeepData return DeepData() def promise(self): + # type: () -> Data # FIXME: promise is unsupported return Data() @@ -36,6 +41,7 @@ class DeepData(object): c = ['Contrived', None, 'Confusing'] def deeper(self): + # type: () -> List[Optional[Data]] return [Data(), None, Data()] doc = ''' @@ -119,6 +125,7 @@ def deeper(self): def test_merges_parallel_fragments(): + # type: () -> None ast = parse(''' { a, deep {...FragOne, ...FragTwo} } @@ -162,6 +169,7 @@ def test_merges_parallel_fragments(): def test_threads_root_value_context_correctly(): + # type: () -> None doc = 'query Example { a }' class Data(object): @@ -170,6 +178,7 @@ class Data(object): ast = parse(doc) def resolver(root_value, *_): + # type: (Data, *ResolveInfo) -> None assert root_value.context_thing == 'thing' resolver.got_here = True @@ -186,6 +195,7 @@ def resolver(root_value, *_): def test_correctly_threads_arguments(): + # type: () -> None doc = ''' query Example { b(numArg: 123, stringArg: "foo") @@ -193,6 +203,7 @@ def test_correctly_threads_arguments(): ''' def resolver(source, info, numArg, stringArg): + # type: (Optional[Any], ResolveInfo, int, str) -> None assert numArg == 123 assert stringArg == 'foo' resolver.got_here = True @@ -218,6 +229,7 @@ def resolver(source, info, numArg, stringArg): def test_nulls_out_error_subtrees(): + # type: () -> None doc = '''{ ok, error @@ -226,9 +238,11 @@ def test_nulls_out_error_subtrees(): class Data(object): def ok(self): + # type: () -> str return 'ok' def error(self): + # type: () -> NoReturn raise Exception('Error getting error') doc_ast = parse(doc) @@ -246,6 +260,7 @@ def error(self): def test_uses_the_inline_operation_if_no_operation_name_is_provided(): + # type: () -> None doc = '{ a }' class Data(object): @@ -261,6 +276,7 @@ class Data(object): def test_uses_the_only_operation_if_no_operation_name_is_provided(): + # type: () -> None doc = 'query Example { a }' class Data(object): @@ -276,6 +292,7 @@ class Data(object): def test_uses_the_named_operation_if_operation_name_is_provided(): + # type: () -> None doc = 'query Example { first: a } query OtherExample { second: a }' class Data(object): @@ -292,6 +309,7 @@ class Data(object): def test_raises_if_no_operation_is_provided(): + # type: () -> None doc = 'fragment Example on Type { a }' class Data(object): @@ -307,6 +325,7 @@ class Data(object): def test_raises_if_no_operation_name_is_provided_with_multiple_operations(): + # type: () -> None doc = 'query Example { a } query OtherExample { a }' class Data(object): @@ -323,6 +342,7 @@ class Data(object): def test_raises_if_unknown_operation_name_is_provided(): + # type: () -> None doc = 'query Example { a } query OtherExample { a }' class Data(object): @@ -339,6 +359,7 @@ class Data(object): def test_uses_the_query_schema_for_queries(): + # type: () -> None doc = 'query Q { a } mutation M { c } subscription S { a }' class Data(object): @@ -361,6 +382,7 @@ class Data(object): def test_uses_the_mutation_schema_for_queries(): + # type: () -> None doc = 'query Q { a } mutation M { c }' class Data(object): @@ -380,6 +402,7 @@ class Data(object): def test_uses_the_subscription_schema_for_subscriptions(): + # type: () -> None from rx import Observable doc = 'query Q { a } subscription S { a }' @@ -405,6 +428,7 @@ class Data(object): def test_avoids_recursion(): + # type: () -> None doc = ''' query Q { a @@ -430,6 +454,7 @@ class Data(object): def test_does_not_include_illegal_fields_in_output(): + # type: () -> None doc = 'mutation M { thisIsIllegalDontIncludeMe }' ast = parse(doc) Q = GraphQLObjectType('Q', { @@ -444,6 +469,7 @@ def test_does_not_include_illegal_fields_in_output(): def test_does_not_include_arguments_that_were_not_set(): + # type: () -> None schema = GraphQLSchema(GraphQLObjectType( 'Type', { @@ -470,14 +496,17 @@ def test_does_not_include_arguments_that_were_not_set(): def test_fails_when_an_is_type_of_check_is_not_met(): + # type: () -> None class Special(object): def __init__(self, value): + # type: (str) -> None self.value = value class NotSpecial(object): def __init__(self, value): + # type: (str) -> None self.value = value SpecialType = GraphQLObjectType( @@ -519,6 +548,7 @@ def __init__(self, value): def test_fails_to_execute_a_query_containing_a_type_definition(): + # type: () -> None query = parse(''' { foo } @@ -541,6 +571,7 @@ def test_fails_to_execute_a_query_containing_a_type_definition(): def test_exceptions_are_reraised_if_specified(mocker): + # type: (MockFixture) -> None logger = mocker.patch('graphql.execution.executor.logger') @@ -549,6 +580,7 @@ def test_exceptions_are_reraised_if_specified(mocker): ''') def resolver(*_): + # type: (*Any) -> NoReturn raise Exception("UH OH!") schema = GraphQLSchema( @@ -566,6 +598,7 @@ def resolver(*_): def test_middleware(): + # type: () -> None doc = '''{ ok not_ok @@ -574,9 +607,11 @@ def test_middleware(): class Data(object): def ok(self): + # type: () -> str return 'ok' def not_ok(self): + # type: () -> str return 'not_ok' doc_ast = parse(doc) @@ -587,6 +622,7 @@ def not_ok(self): }) def reversed_middleware(next, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Promise p = next(*args, **kwargs) return p.then(lambda x: x[::-1]) @@ -597,6 +633,7 @@ def reversed_middleware(next, *args, **kwargs): def test_middleware_class(): + # type: () -> None doc = '''{ ok not_ok @@ -605,9 +642,11 @@ def test_middleware_class(): class Data(object): def ok(self): + # type: () -> str return 'ok' def not_ok(self): + # type: () -> str return 'not_ok' doc_ast = parse(doc) @@ -619,6 +658,7 @@ def not_ok(self): class MyMiddleware(object): def resolve(self, next, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Promise p = next(*args, **kwargs) return p.then(lambda x: x[::-1]) @@ -629,6 +669,7 @@ def resolve(self, next, *args, **kwargs): def test_middleware_skip_promise_wrap(): + # type: () -> None doc = '''{ ok not_ok @@ -637,9 +678,11 @@ def test_middleware_skip_promise_wrap(): class Data(object): def ok(self): + # type: () -> str return 'ok' def not_ok(self): + # type: () -> str return 'not_ok' doc_ast = parse(doc) @@ -651,10 +694,12 @@ def not_ok(self): class MyPromiseMiddleware(object): def resolve(self, next, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Promise return Promise.resolve(next(*args, **kwargs)) class MyEmptyMiddleware(object): def resolve(self, next, *args, **kwargs): + # type: (Callable, *Any, **Any) -> str return next(*args, **kwargs) middlewares_with_promise = MiddlewareManager( @@ -671,6 +716,7 @@ def resolve(self, next, *args, **kwargs): def test_executor_properly_propogates_path_data(mocker): + # type: (MockFixture) -> None time_mock = mocker.patch('time.time') time_mock.side_effect = range(0, 10000) @@ -718,6 +764,7 @@ def test_executor_properly_propogates_path_data(mocker): class Article(object): def __init__(self, id): + # type: (int) -> None self.id = id self.isPublished = True self.author = Author() @@ -744,9 +791,17 @@ def __init__(self, uid, width, height): class PathCollectorMiddleware(object): def __init__(self): + # type: () -> None self.paths = [] - def resolve(self, _next, root, info, *args, **kwargs): + def resolve(self, + _next, # type: Callable + root, # type: Optional[Article] + info, # type: ResolveInfo + *args, # type: Any + **kwargs # type: Any + ): + # type: (...) -> Promise self.paths.append(info.path) return _next(root, info, *args, **kwargs) diff --git a/graphql/execution/tests/test_executor_asyncio.py b/graphql/execution/tests/test_executor_asyncio.py index ded4132b..714f59ee 100644 --- a/graphql/execution/tests/test_executor_asyncio.py +++ b/graphql/execution/tests/test_executor_asyncio.py @@ -1,98 +1,122 @@ """ isort:skip_file """ +# type: ignore # flake8: noqa import pytest + asyncio = pytest.importorskip("asyncio") from graphql.error import format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString from ..executors.asyncio import AsyncioExecutor from .test_mutations import assert_evaluate_mutations_serially def test_asyncio_executor(): + # type: () -> None def resolver(context, *_): + # type: (Optional[Any], *ResolveInfo) -> str asyncio.sleep(0.001) - return 'hey' + return "hey" @asyncio.coroutine def resolver_2(context, *_): + # type: (Optional[Any], *ResolveInfo) -> str asyncio.sleep(0.003) - return 'hey2' + return "hey2" def resolver_3(contest, *_): - return 'hey3' - - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2), - 'c': GraphQLField(GraphQLString, resolver=resolver_3) - }) - - ast = parse('{ a b c }') + # type: (Optional[Any], *ResolveInfo) -> str + return "hey3" + + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + "c": GraphQLField(GraphQLString, resolver=resolver_3), + }, + ) + + ast = parse("{ a b c }") result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor()) assert not result.errors - assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'} + assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"} def test_asyncio_executor_custom_loop(): + # type: () -> None loop = asyncio.get_event_loop() def resolver(context, *_): + # type: (Optional[Any], *ResolveInfo) -> str asyncio.sleep(0.001, loop=loop) - return 'hey' + return "hey" @asyncio.coroutine def resolver_2(context, *_): + # type: (Optional[Any], *ResolveInfo) -> str asyncio.sleep(0.003, loop=loop) - return 'hey2' + return "hey2" def resolver_3(contest, *_): - return 'hey3' - - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2), - 'c': GraphQLField(GraphQLString, resolver=resolver_3) - }) - - ast = parse('{ a b c }') + # type: (Optional[Any], *ResolveInfo) -> str + return "hey3" + + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + "c": GraphQLField(GraphQLString, resolver=resolver_3), + }, + ) + + ast = parse("{ a b c }") result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop=loop)) assert not result.errors - assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'} + assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"} def test_asyncio_executor_with_error(): - ast = parse('query Example { a, b }') + # type: () -> None + ast = parse("query Example { a, b }") def resolver(context, *_): + # type: (Optional[Any], *ResolveInfo) -> str asyncio.sleep(0.001) - return 'hey' + return "hey" def resolver_2(context, *_): + # type: (Optional[Any], *ResolveInfo) -> NoReturn asyncio.sleep(0.003) - raise Exception('resolver_2 failed!') + raise Exception("resolver_2 failed!") - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2) - }) + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + }, + ) result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor()) formatted_errors = list(map(format_error, result.errors)) - assert formatted_errors == [{ - 'locations': [{'line': 1, 'column': 20}], - 'path': ['b'], - 'message': 'resolver_2 failed!' - }] - assert result.data == {'a': 'hey', 'b': None} + assert formatted_errors == [ + { + "locations": [{"line": 1, "column": 20}], + "path": ["b"], + "message": "resolver_2 failed!", + } + ] + assert result.data == {"a": "hey", "b": None} def test_evaluates_mutations_serially(): + # type: () -> None assert_evaluate_mutations_serially(executor=AsyncioExecutor()) diff --git a/graphql/execution/tests/test_executor_gevent.py b/graphql/execution/tests/test_executor_gevent.py index 04d164f7..9256a018 100644 --- a/graphql/execution/tests/test_executor_gevent.py +++ b/graphql/execution/tests/test_executor_gevent.py @@ -1,17 +1,18 @@ """ isort:skip_file """ +# type: ignore # flake8: noqa import pytest + gevent = pytest.importorskip("gevent") from graphql.error import format_error from graphql.execution import execute from graphql.language.location import SourceLocation from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString from ..executors.gevent import GeventExecutor from .test_mutations import assert_evaluate_mutations_serially @@ -20,51 +21,59 @@ def test_gevent_executor(): def resolver(context, *_): gevent.sleep(0.001) - return 'hey' + return "hey" def resolver_2(context, *_): gevent.sleep(0.003) - return 'hey2' + return "hey2" def resolver_3(contest, *_): - return 'hey3' - - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2), - 'c': GraphQLField(GraphQLString, resolver=resolver_3) - }) - - ast = parse('{ a b c }') + return "hey3" + + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + "c": GraphQLField(GraphQLString, resolver=resolver_3), + }, + ) + + ast = parse("{ a b c }") result = execute(GraphQLSchema(Type), ast, executor=GeventExecutor()) assert not result.errors - assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'} + assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"} def test_gevent_executor_with_error(): - ast = parse('query Example { a, b }') + ast = parse("query Example { a, b }") def resolver(context, *_): gevent.sleep(0.001) - return 'hey' + return "hey" def resolver_2(context, *_): gevent.sleep(0.003) - raise Exception('resolver_2 failed!') + raise Exception("resolver_2 failed!") - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - 'b': GraphQLField(GraphQLString, resolver=resolver_2) - }) + Type = GraphQLObjectType( + "Type", + { + "a": GraphQLField(GraphQLString, resolver=resolver), + "b": GraphQLField(GraphQLString, resolver=resolver_2), + }, + ) result = execute(GraphQLSchema(Type), ast, executor=GeventExecutor()) formatted_errors = list(map(format_error, result.errors)) - assert formatted_errors == [{ - 'locations': [{'line': 1, 'column': 20}], - 'path': ['b'], - 'message': 'resolver_2 failed!' - }] - assert result.data == {'a': 'hey', 'b': None} + assert formatted_errors == [ + { + "locations": [{"line": 1, "column": 20}], + "path": ["b"], + "message": "resolver_2 failed!", + } + ] + assert result.data == {"a": "hey", "b": None} def test_evaluates_mutations_serially(): diff --git a/graphql/execution/tests/test_executor_thread.py b/graphql/execution/tests/test_executor_thread.py index 5b44255d..6eaaf47e 100644 --- a/graphql/execution/tests/test_executor_thread.py +++ b/graphql/execution/tests/test_executor_thread.py @@ -1,10 +1,16 @@ - +# type: ignore from graphql.error import format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLField, GraphQLInt, - GraphQLList, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLField, + GraphQLInt, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) from ..executors.thread import ThreadExecutor from .test_mutations import assert_evaluate_mutations_serially @@ -12,35 +18,42 @@ def test_executes_arbitary_code(): + # type: () -> None class Data(object): - a = 'Apple' - b = 'Banana' - c = 'Cookie' - d = 'Donut' - e = 'Egg' + a = "Apple" + b = "Banana" + c = "Cookie" + d = "Donut" + e = "Egg" @property def f(self): - return resolved('Fish') + # type: () -> Promise + return resolved("Fish") def pic(self, size=50): - return resolved('Pic of size: {}'.format(size)) + # type: (int) -> Promise + return resolved("Pic of size: {}".format(size)) def deep(self): + # type: () -> DeepData return DeepData() def promise(self): + # type: () -> Promise return resolved(Data()) class DeepData(object): - a = 'Already Been Done' - b = 'Boring' - c = ['Contrived', None, resolved('Confusing')] + a = "Already Been Done" + b = "Boring" + c = ["Contrived", None, resolved("Confusing")] def deeper(self): + # type: () -> List[Union[None, Data, Promise]] return [Data(), None, resolved(Data())] - ast = parse(''' + ast = parse( + """ query Example($size: Int) { a, b, @@ -67,53 +80,63 @@ def deeper(self): d e } - ''') + """ + ) expected = { - 'a': 'Apple', - 'b': 'Banana', - 'x': 'Cookie', - 'd': 'Donut', - 'e': 'Egg', - 'f': 'Fish', - 'pic': 'Pic of size: 100', - 'promise': {'a': 'Apple'}, - 'deep': { - 'a': 'Already Been Done', - 'b': 'Boring', - 'c': ['Contrived', None, 'Confusing'], - 'deeper': [ - {'a': 'Apple', 'b': 'Banana'}, + "a": "Apple", + "b": "Banana", + "x": "Cookie", + "d": "Donut", + "e": "Egg", + "f": "Fish", + "pic": "Pic of size: 100", + "promise": {"a": "Apple"}, + "deep": { + "a": "Already Been Done", + "b": "Boring", + "c": ["Contrived", None, "Confusing"], + "deeper": [ + {"a": "Apple", "b": "Banana"}, None, - {'a': 'Apple', 'b': 'Banana'}]} + {"a": "Apple", "b": "Banana"}, + ], + }, } - DataType = GraphQLObjectType('DataType', lambda: { - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - 'c': GraphQLField(GraphQLString), - 'd': GraphQLField(GraphQLString), - 'e': GraphQLField(GraphQLString), - 'f': GraphQLField(GraphQLString), - 'pic': GraphQLField( - args={'size': GraphQLArgument(GraphQLInt)}, - type=GraphQLString, - resolver=lambda obj, info, **args: obj.pic(args['size']), - ), - 'deep': GraphQLField(DeepDataType), - 'promise': GraphQLField(DataType), - }) - - DeepDataType = GraphQLObjectType('DeepDataType', { - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - 'c': GraphQLField(GraphQLList(GraphQLString)), - 'deeper': GraphQLField(GraphQLList(DataType)), - }) + DataType = GraphQLObjectType( + "DataType", + lambda: { + "a": GraphQLField(GraphQLString), + "b": GraphQLField(GraphQLString), + "c": GraphQLField(GraphQLString), + "d": GraphQLField(GraphQLString), + "e": GraphQLField(GraphQLString), + "f": GraphQLField(GraphQLString), + "pic": GraphQLField( + args={"size": GraphQLArgument(GraphQLInt)}, + type=GraphQLString, + resolver=lambda obj, info, **args: obj.pic(args["size"]), + ), + "deep": GraphQLField(DeepDataType), + "promise": GraphQLField(DataType), + }, + ) + + DeepDataType = GraphQLObjectType( + "DeepDataType", + { + "a": GraphQLField(GraphQLString), + "b": GraphQLField(GraphQLString), + "c": GraphQLField(GraphQLList(GraphQLString)), + "deeper": GraphQLField(GraphQLList(DataType)), + }, + ) schema = GraphQLSchema(query=DataType) def handle_result(result): + # type: (ExecutionResult) -> None assert not result.errors assert result.data == expected @@ -122,15 +145,22 @@ def handle_result(result): schema, ast, Data(), - variable_values={ - 'size': 100}, - operation_name='Example', - executor=ThreadExecutor())) - handle_result(execute(schema, ast, Data(), variable_values={'size': 100}, operation_name='Example')) + variable_values={"size": 100}, + operation_name="Example", + executor=ThreadExecutor(), + ) + ) + handle_result( + execute( + schema, ast, Data(), variable_values={"size": 100}, operation_name="Example" + ) + ) def test_synchronous_error_nulls_out_error_subtrees(): - ast = parse(''' + # type: () -> None + ast = parse( + """ { sync syncError @@ -141,82 +171,124 @@ def test_synchronous_error_nulls_out_error_subtrees(): asyncEmptyReject asyncReturnError } - ''') + """ + ) class Data: - def sync(self): - return 'sync' + # type: () -> str + return "sync" def syncError(self): - raise Exception('Error getting syncError') + # type: () -> NoReturn + raise Exception("Error getting syncError") def syncReturnError(self): + # type: () -> Exception return Exception("Error getting syncReturnError") def syncReturnErrorList(self): + # type: () -> List[Union[Exception, str]] return [ - 'sync0', - Exception('Error getting syncReturnErrorList1'), - 'sync2', - Exception('Error getting syncReturnErrorList3') + "sync0", + Exception("Error getting syncReturnErrorList1"), + "sync2", + Exception("Error getting syncReturnErrorList3"), ] def async(self): - return resolved('async') + # type: () -> Promise + return resolved("async") def asyncReject(self): - return rejected(Exception('Error getting asyncReject')) + # type: () -> Promise + return rejected(Exception("Error getting asyncReject")) def asyncEmptyReject(self): - return rejected(Exception('An unknown error occurred.')) + # type: () -> Promise + return rejected(Exception("An unknown error occurred.")) def asyncReturnError(self): - return resolved(Exception('Error getting asyncReturnError')) + # type: () -> Promise + return resolved(Exception("Error getting asyncReturnError")) schema = GraphQLSchema( query=GraphQLObjectType( - name='Type', + name="Type", fields={ - 'sync': GraphQLField(GraphQLString), - 'syncError': GraphQLField(GraphQLString), - 'syncReturnError': GraphQLField(GraphQLString), - 'syncReturnErrorList': GraphQLField(GraphQLList(GraphQLString)), - 'async': GraphQLField(GraphQLString), - 'asyncReject': GraphQLField(GraphQLString), - 'asyncEmptyReject': GraphQLField(GraphQLString), - 'asyncReturnError': GraphQLField(GraphQLString), - } + "sync": GraphQLField(GraphQLString), + "syncError": GraphQLField(GraphQLString), + "syncReturnError": GraphQLField(GraphQLString), + "syncReturnErrorList": GraphQLField(GraphQLList(GraphQLString)), + "async": GraphQLField(GraphQLString), + "asyncReject": GraphQLField(GraphQLString), + "asyncEmptyReject": GraphQLField(GraphQLString), + "asyncReturnError": GraphQLField(GraphQLString), + }, ) ) def sort_key(item): - locations = item['locations'][0] - return (locations['line'], locations['column']) + # type: (Dict[str, Any]) -> Tuple[int, int] + locations = item["locations"][0] + return (locations["line"], locations["column"]) def handle_results(result): + # type: (ExecutionResult) -> None assert result.data == { - 'async': 'async', - 'asyncEmptyReject': None, - 'asyncReject': None, - 'asyncReturnError': None, - 'sync': 'sync', - 'syncError': None, - 'syncReturnError': None, - 'syncReturnErrorList': ['sync0', None, 'sync2', None] + "async": "async", + "asyncEmptyReject": None, + "asyncReject": None, + "asyncReturnError": None, + "sync": "sync", + "syncError": None, + "syncReturnError": None, + "syncReturnErrorList": ["sync0", None, "sync2", None], } - assert sorted(list(map(format_error, result.errors)), key=sort_key) == sorted([ - {'locations': [{'line': 4, 'column': 9}], 'path':['syncError'], 'message': 'Error getting syncError'}, - {'locations': [{'line': 5, 'column': 9}], 'path':['syncReturnError'], 'message': 'Error getting syncReturnError'}, - {'locations': [{'line': 6, 'column': 9}], 'path':['syncReturnErrorList', 1], 'message': 'Error getting syncReturnErrorList1'}, - {'locations': [{'line': 6, 'column': 9}], 'path':['syncReturnErrorList', 3], 'message': 'Error getting syncReturnErrorList3'}, - {'locations': [{'line': 8, 'column': 9}], 'path':['asyncReject'], 'message': 'Error getting asyncReject'}, - {'locations': [{'line': 9, 'column': 9}], 'path':['asyncEmptyReject'], 'message': 'An unknown error occurred.'}, - {'locations': [{'line': 10, 'column': 9}], 'path':['asyncReturnError'], 'message': 'Error getting asyncReturnError'} - ], key=sort_key) + assert sorted(list(map(format_error, result.errors)), key=sort_key) == sorted( + [ + { + "locations": [{"line": 4, "column": 9}], + "path": ["syncError"], + "message": "Error getting syncError", + }, + { + "locations": [{"line": 5, "column": 9}], + "path": ["syncReturnError"], + "message": "Error getting syncReturnError", + }, + { + "locations": [{"line": 6, "column": 9}], + "path": ["syncReturnErrorList", 1], + "message": "Error getting syncReturnErrorList1", + }, + { + "locations": [{"line": 6, "column": 9}], + "path": ["syncReturnErrorList", 3], + "message": "Error getting syncReturnErrorList3", + }, + { + "locations": [{"line": 8, "column": 9}], + "path": ["asyncReject"], + "message": "Error getting asyncReject", + }, + { + "locations": [{"line": 9, "column": 9}], + "path": ["asyncEmptyReject"], + "message": "An unknown error occurred.", + }, + { + "locations": [{"line": 10, "column": 9}], + "path": ["asyncReturnError"], + "message": "Error getting asyncReturnError", + }, + ], + key=sort_key, + ) handle_results(execute(schema, ast, Data(), executor=ThreadExecutor())) def test_evaluates_mutations_serially(): + # type: () -> None assert_evaluate_mutations_serially(executor=ThreadExecutor()) diff --git a/graphql/execution/tests/test_lists.py b/graphql/execution/tests/test_lists.py index c0874776..20bb33f1 100644 --- a/graphql/execution/tests/test_lists.py +++ b/graphql/execution/tests/test_lists.py @@ -1,28 +1,36 @@ +# type: ignore from collections import namedtuple from graphql.error import format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLInt, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLSchema) +from graphql.type import ( + GraphQLField, + GraphQLInt, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, +) from .utils import rejected, resolved -Data = namedtuple('Data', 'test') -ast = parse('{ nest { test } }') +Data = namedtuple("Data", "test") +ast = parse("{ nest { test } }") def check(test_data, expected): def run_check(self): + # type: (Any) -> None test_type = self.type data = Data(test=test_data) DataType = GraphQLObjectType( - name='DataType', + name="DataType", fields=lambda: { - 'test': GraphQLField(test_type), - 'nest': GraphQLField(DataType, resolver=lambda *_: data) - } + "test": GraphQLField(test_type), + "nest": GraphQLField(DataType, resolver=lambda *_: data), + }, ) schema = GraphQLSchema(query=DataType) @@ -30,13 +38,11 @@ def run_check(self): if response.errors: result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] + "data": response.data, + "errors": [format_error(e) for e in response.errors], } else: - result = { - 'data': response.data - } + result = {"data": response.data} assert result == expected @@ -46,208 +52,339 @@ def run_check(self): class Test_ListOfT_Array_T: # [T] Array type = GraphQLList(GraphQLInt) - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(None, {'data': {'nest': {'test': None}}}) + test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check([1, None, 2], {"data": {"nest": {"test": [1, None, 2]}}}) + test_returns_null = check(None, {"data": {"nest": {"test": None}}}) class Test_ListOfT_Promise_Array_T: # [T] Promise> type = GraphQLList(GraphQLInt) - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), {'data': {'nest': {'test': None}}}) - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': {'test': None}}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'bad' - }] - }) + test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}} + ) + test_returns_null = check(resolved(None), {"data": {"nest": {"test": None}}}) + test_rejected = check( + lambda: rejected(Exception("bad")), + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "bad", + } + ], + }, + ) class Test_ListOfT_Array_Promise_T: # [T] Array> type = GraphQLList(GraphQLInt) - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], {'data': {'nest': {'test': [1, None, 2]}}}) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': [1, None, 2]}}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'bad' - }] - }) + test_contains_values = check( + [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}} + ) + test_contains_null = check( + [resolved(1), resolved(None), resolved(2)], + {"data": {"nest": {"test": [1, None, 2]}}}, + ) + test_contains_reject = check( + lambda: [resolved(1), rejected(Exception("bad")), resolved(2)], + { + "data": {"nest": {"test": [1, None, 2]}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "bad", + } + ], + }, + ) class Test_NotNullListOfT_Array_T: # [T]! Array type = GraphQLNonNull(GraphQLList(GraphQLInt)) - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) + test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}} + ) + test_returns_null = check( + resolved(None), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) class Test_NotNullListOfT_Promise_Array_T: # [T]! Promise>> type = GraphQLNonNull(GraphQLList(GraphQLInt)) - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': None}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'bad' - }] - }) + test_contains_values = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + resolved([1, None, 2]), {"data": {"nest": {"test": [1, None, 2]}}} + ) + test_returns_null = check( + resolved(None), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + + test_rejected = check( + lambda: rejected(Exception("bad")), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "bad", + } + ], + }, + ) class Test_NotNullListOfT_Array_Promise_T: # [T]! Promise>> type = GraphQLNonNull(GraphQLList(GraphQLInt)) - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], {'data': {'nest': {'test': [1, None, 2]}}}) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': [1, None, 2]}}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'bad' - }] - }) + test_contains_values = check( + [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}} + ) + test_contains_null = check( + [resolved(1), resolved(None), resolved(2)], + {"data": {"nest": {"test": [1, None, 2]}}}, + ) + test_contains_reject = check( + lambda: [resolved(1), rejected(Exception("bad")), resolved(2)], + { + "data": {"nest": {"test": [1, None, 2]}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "bad", + } + ], + }, + ) class TestListOfNotNullT_Array_T: # [T!] Array type = GraphQLList(GraphQLNonNull(GraphQLInt)) - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_returns_null = check(None, {'data': {'nest': {'test': None}}}) + test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + [1, None, 2], + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + test_returns_null = check(None, {"data": {"nest": {"test": None}}}) class TestListOfNotNullT_Promise_Array_T: # [T!] Promise> type = GraphQLList(GraphQLNonNull(GraphQLInt)) - test_contains_value = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_returns_null = check(resolved(None), {'data': {'nest': {'test': None}}}) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': {'test': None}}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'bad' - }] - }) + test_contains_value = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + resolved([1, None, 2]), + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + + test_returns_null = check(resolved(None), {"data": {"nest": {"test": None}}}) + + test_rejected = check( + lambda: rejected(Exception("bad")), + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "bad", + } + ], + }, + ) class TestListOfNotNullT_Array_Promise_T: # [T!] Array> type = GraphQLList(GraphQLNonNull(GraphQLInt)) - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': None}}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'bad' - }] - }) + test_contains_values = check( + [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}} + ) + test_contains_null = check( + [resolved(1), resolved(None), resolved(2)], + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + test_contains_reject = check( + lambda: [resolved(1), rejected(Exception("bad")), resolved(2)], + { + "data": {"nest": {"test": None}}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "bad", + } + ], + }, + ) class TestNotNullListOfNotNullT_Array_T: # [T!]! Array type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_returns_null = check(None, { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) + test_contains_values = check([1, 2], {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + [1, None, 2], + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + test_returns_null = check( + None, + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) class TestNotNullListOfNotNullT_Promise_Array_T: # [T!]! Promise> type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - test_contains_value = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': None}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test'], - 'message': 'bad' - }] - }) + test_contains_value = check(resolved([1, 2]), {"data": {"nest": {"test": [1, 2]}}}) + test_contains_null = check( + resolved([1, None, 2]), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + + test_returns_null = check( + resolved(None), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + + test_rejected = check( + lambda: rejected(Exception("bad")), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test"], + "message": "bad", + } + ], + }, + ) class TestNotNullListOfNotNullT_Array_Promise_T: # [T!]! Array> type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': None}, - 'errors': [{ - 'locations': [{'column': 10, 'line': 1}], - 'path': ['nest', 'test', 1], - 'message': 'bad' - }] - }) + test_contains_values = check( + [resolved(1), resolved(2)], {"data": {"nest": {"test": [1, 2]}}} + ) + test_contains_null = check( + [resolved(1), resolved(None), resolved(2)], + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "Cannot return null for non-nullable field DataType.test.", + } + ], + }, + ) + test_contains_reject = check( + lambda: [resolved(1), rejected(Exception("bad")), resolved(2)], + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 10, "line": 1}], + "path": ["nest", "test", 1], + "message": "bad", + } + ], + }, + ) + diff --git a/graphql/execution/tests/test_located_error.py b/graphql/execution/tests/test_located_error.py index df61f257..1676312c 100644 --- a/graphql/execution/tests/test_located_error.py +++ b/graphql/execution/tests/test_located_error.py @@ -1,3 +1,4 @@ +# type: ignore # coding: utf-8 from graphql import GraphQLField @@ -10,14 +11,16 @@ def test_unicode_error_message(): - ast = parse('query Example { unicode }') + # type: () -> None + ast = parse("query Example { unicode }") def resolver(context, *_): - raise Exception(u'UNIÇODÉ!') + # type: (Optional[Any], *ResolveInfo) -> NoReturn + raise Exception(u"UNIÇODÉ!") - Type = GraphQLObjectType('Type', { - 'unicode': GraphQLField(GraphQLString, resolver=resolver), - }) + Type = GraphQLObjectType( + "Type", {"unicode": GraphQLField(GraphQLString, resolver=resolver)} + ) result = execute(GraphQLSchema(Type), ast) assert isinstance(result.errors[0], GraphQLLocatedError) diff --git a/graphql/execution/tests/test_mutations.py b/graphql/execution/tests/test_mutations.py index 3a71dfbb..d7ef530b 100644 --- a/graphql/execution/tests/test_mutations.py +++ b/graphql/execution/tests/test_mutations.py @@ -1,73 +1,99 @@ +# type: ignore from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLField, GraphQLInt, - GraphQLList, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLField, + GraphQLInt, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) +from mypy_extensions import NoReturn + +# from graphql.execution.executors.asyncio import AsyncioExecutor +# from graphql.execution.executors.thread import ThreadExecutor +# from typing import Union class NumberHolder(object): - def __init__(self, n): + # type: (int) -> None self.theNumber = n class Root(object): - def __init__(self, n): + # type: (int) -> None self.numberHolder = NumberHolder(n) def immediately_change_the_number(self, n): + # type: (int) -> NumberHolder self.numberHolder.theNumber = n return self.numberHolder def promise_to_change_the_number(self, n): + # type: (int) -> NumberHolder # TODO: async return self.immediately_change_the_number(n) def fail_to_change_the_number(self, n): - raise Exception('Cannot change the number') + # type: (int) -> NoReturn + raise Exception("Cannot change the number") def promise_and_fail_to_change_the_number(self, n): + # type: (int) -> NoReturn # TODO: async self.fail_to_change_the_number(n) -NumberHolderType = GraphQLObjectType('NumberHolder', { - 'theNumber': GraphQLField(GraphQLInt) -}) - -QueryType = GraphQLObjectType('Query', { - 'numberHolder': GraphQLField(NumberHolderType) -}) - -MutationType = GraphQLObjectType('Mutation', { - 'immediatelyChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, info, **args: - obj.immediately_change_the_number(args['newNumber'])), - 'promiseToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, info, **args: - obj.promise_to_change_the_number(args['newNumber'])), - 'failToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, info, **args: - obj.fail_to_change_the_number(args['newNumber'])), - 'promiseAndFailToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, info, **args: - obj.promise_and_fail_to_change_the_number(args['newNumber'])), -}) +NumberHolderType = GraphQLObjectType( + "NumberHolder", {"theNumber": GraphQLField(GraphQLInt)} +) + +QueryType = GraphQLObjectType("Query", {"numberHolder": GraphQLField(NumberHolderType)}) + +MutationType = GraphQLObjectType( + "Mutation", + { + "immediatelyChangeTheNumber": GraphQLField( + NumberHolderType, + args={"newNumber": GraphQLArgument(GraphQLInt)}, + resolver=lambda obj, info, **args: obj.immediately_change_the_number( + args["newNumber"] + ), + ), + "promiseToChangeTheNumber": GraphQLField( + NumberHolderType, + args={"newNumber": GraphQLArgument(GraphQLInt)}, + resolver=lambda obj, info, **args: obj.promise_to_change_the_number( + args["newNumber"] + ), + ), + "failToChangeTheNumber": GraphQLField( + NumberHolderType, + args={"newNumber": GraphQLArgument(GraphQLInt)}, + resolver=lambda obj, info, **args: obj.fail_to_change_the_number( + args["newNumber"] + ), + ), + "promiseAndFailToChangeTheNumber": GraphQLField( + NumberHolderType, + args={"newNumber": GraphQLArgument(GraphQLInt)}, + resolver=lambda obj, info, **args: obj.promise_and_fail_to_change_the_number( + args["newNumber"] + ), + ), + }, +) schema = GraphQLSchema(QueryType, MutationType) def assert_evaluate_mutations_serially(executor=None): - doc = '''mutation M { + # type: (Union[None, AsyncioExecutor, ThreadExecutor]) -> None + doc = """mutation M { first: immediatelyChangeTheNumber(newNumber: 1) { theNumber }, @@ -83,26 +109,27 @@ def assert_evaluate_mutations_serially(executor=None): fifth: immediatelyChangeTheNumber(newNumber: 5) { theNumber } - }''' + }""" ast = parse(doc) - result = execute(schema, ast, Root(6), operation_name='M', executor=executor) + result = execute(schema, ast, Root(6), operation_name="M", executor=executor) assert not result.errors - assert result.data == \ - { - 'first': {'theNumber': 1}, - 'second': {'theNumber': 2}, - 'third': {'theNumber': 3}, - 'fourth': {'theNumber': 4}, - 'fifth': {'theNumber': 5}, - } + assert result.data == { + "first": {"theNumber": 1}, + "second": {"theNumber": 2}, + "third": {"theNumber": 3}, + "fourth": {"theNumber": 4}, + "fifth": {"theNumber": 5}, + } def test_evaluates_mutations_serially(): + # type: () -> None assert_evaluate_mutations_serially() def test_evaluates_mutations_correctly_in_the_presense_of_a_failed_mutation(): - doc = '''mutation M { + # type: () -> None + doc = """mutation M { first: immediatelyChangeTheNumber(newNumber: 1) { theNumber }, @@ -121,19 +148,18 @@ def test_evaluates_mutations_correctly_in_the_presense_of_a_failed_mutation(): sixth: promiseAndFailToChangeTheNumber(newNumber: 6) { theNumber } - }''' + }""" ast = parse(doc) - result = execute(schema, ast, Root(6), operation_name='M') - assert result.data == \ - { - 'first': {'theNumber': 1}, - 'second': {'theNumber': 2}, - 'third': None, - 'fourth': {'theNumber': 4}, - 'fifth': {'theNumber': 5}, - 'sixth': None, - } + result = execute(schema, ast, Root(6), operation_name="M") + assert result.data == { + "first": {"theNumber": 1}, + "second": {"theNumber": 2}, + "third": None, + "fourth": {"theNumber": 4}, + "fifth": {"theNumber": 5}, + "sixth": None, + } assert len(result.errors) == 2 # TODO: check error location - assert result.errors[0].message == 'Cannot change the number' - assert result.errors[1].message == 'Cannot change the number' + assert result.errors[0].message == "Cannot change the number" + assert result.errors[1].message == "Cannot change the number" diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py index b72e2f30..c764c6ca 100644 --- a/graphql/execution/tests/test_nonnull.py +++ b/graphql/execution/tests/test_nonnull.py @@ -1,220 +1,303 @@ - +# type: ignore from graphql.error import format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLNonNull, GraphQLObjectType, - GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLField, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) from .utils import rejected, resolved -sync_error = Exception('sync') -non_null_sync_error = Exception('nonNullSync') -promise_error = Exception('promise') -non_null_promise_error = Exception('nonNullPromise') +# from mypy_extensions import NoReturn +# from promise.promise import Promise +# from typing import Any +# from typing import Optional +# from typing import Dict +# from typing import Tuple +# from typing import Union +sync_error = Exception("sync") +non_null_sync_error = Exception("nonNullSync") +promise_error = Exception("promise") +non_null_promise_error = Exception("nonNullPromise") -class ThrowingData(object): +class ThrowingData(object): def sync(self): + # type: () -> NoReturn raise sync_error def nonNullSync(self): + # type: () -> NoReturn raise non_null_sync_error def promise(self): + # type: () -> Promise return rejected(promise_error) def nonNullPromise(self): + # type: () -> Promise return rejected(non_null_promise_error) def nest(self): + # type: () -> ThrowingData return ThrowingData() def nonNullNest(self): + # type: () -> ThrowingData return ThrowingData() def promiseNest(self): + # type: () -> Promise return resolved(ThrowingData()) def nonNullPromiseNest(self): + # type: () -> Promise return resolved(ThrowingData()) class NullingData(object): - def sync(self): + # type: () -> Optional[Any] return None def nonNullSync(self): + # type: () -> Optional[Any] return None def promise(self): + # type: () -> Promise return resolved(None) def nonNullPromise(self): + # type: () -> Promise return resolved(None) def nest(self): + # type: () -> NullingData return NullingData() def nonNullNest(self): + # type: () -> NullingData return NullingData() def promiseNest(self): + # type: () -> Promise return resolved(NullingData()) def nonNullPromiseNest(self): + # type: () -> Promise return resolved(NullingData()) -DataType = GraphQLObjectType('DataType', lambda: { - 'sync': GraphQLField(GraphQLString), - 'nonNullSync': GraphQLField(GraphQLNonNull(GraphQLString)), - 'promise': GraphQLField(GraphQLString), - 'nonNullPromise': GraphQLField(GraphQLNonNull(GraphQLString)), - 'nest': GraphQLField(DataType), - 'nonNullNest': GraphQLField(GraphQLNonNull(DataType)), - 'promiseNest': GraphQLField(DataType), - 'nonNullPromiseNest': GraphQLField(GraphQLNonNull(DataType)) -}) +DataType = GraphQLObjectType( + "DataType", + lambda: { + "sync": GraphQLField(GraphQLString), + "nonNullSync": GraphQLField(GraphQLNonNull(GraphQLString)), + "promise": GraphQLField(GraphQLString), + "nonNullPromise": GraphQLField(GraphQLNonNull(GraphQLString)), + "nest": GraphQLField(DataType), + "nonNullNest": GraphQLField(GraphQLNonNull(DataType)), + "promiseNest": GraphQLField(DataType), + "nonNullPromiseNest": GraphQLField(GraphQLNonNull(DataType)), + }, +) schema = GraphQLSchema(DataType) def order_errors(error): - locations = error['locations'] - return (locations[0]['column'], locations[0]['line']) + # type: (Dict[str, Any]) -> Tuple[int, int] + locations = error["locations"] + return (locations[0]["column"], locations[0]["line"]) def check(doc, data, expected): + # type: (str, Union[NullingData, ThrowingData], Dict[str, Any]) -> None ast = parse(doc) response = execute(schema, ast, data) if response.errors: result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] + "data": response.data, + "errors": [format_error(e) for e in response.errors], } - if result['errors'] != expected['errors']: - assert result['data'] == expected['data'] + if result["errors"] != expected["errors"]: + assert result["data"] == expected["data"] # Sometimes the fields resolves asynchronously, so # we need to check that the errors are the same, but might be # raised in a different order. - assert sorted(result['errors'], key=order_errors) == sorted(expected['errors'], key=order_errors) + assert sorted(result["errors"], key=order_errors) == sorted( + expected["errors"], key=order_errors + ) else: assert result == expected else: - result = { - 'data': response.data - } + result = {"data": response.data} assert result == expected def test_nulls_a_nullable_field_that_throws_sync(): - doc = ''' + # type: () -> None + doc = """ query Q { sync } - ''' - - check(doc, ThrowingData(), { - 'data': {'sync': None}, - 'errors': [{ - 'locations': [{'column': 13, 'line': 3}], - 'path': ['sync'], - 'message': str(sync_error) - }] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"sync": None}, + "errors": [ + { + "locations": [{"column": 13, "line": 3}], + "path": ["sync"], + "message": str(sync_error), + } + ], + }, + ) def test_nulls_a_nullable_field_that_throws_in_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { promise } - ''' - - check(doc, ThrowingData(), { - 'data': {'promise': None}, - 'errors': [{ - 'locations': [{'column': 13, 'line': 3}], - 'path': ['promise'], - 'message': str(promise_error) - }] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"promise": None}, + "errors": [ + { + "locations": [{"column": 13, "line": 3}], + "path": ["promise"], + "message": str(promise_error), + } + ], + }, + ) def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_throws(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullSync, } } - ''' - - check(doc, ThrowingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['nest', 'nonNullSync'], - 'message': str(non_null_sync_error)}] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["nest", "nonNullSync"], + "message": str(non_null_sync_error), + } + ], + }, + ) def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_throws_in_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullPromise, } } - ''' - - check(doc, ThrowingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['nest', 'nonNullPromise'], - 'message': str(non_null_promise_error)}] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["nest", "nonNullPromise"], + "message": str(non_null_promise_error), + } + ], + }, + ) def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_synchronously(): - doc = ''' + # type: () -> None + doc = """ query Q { promiseNest { nonNullSync, } } - ''' - - check(doc, ThrowingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['promiseNest', 'nonNullSync'], - 'message': str(non_null_sync_error)}] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"promiseNest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["promiseNest", "nonNullSync"], + "message": str(non_null_sync_error), + } + ], + }, + ) def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_in_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { promiseNest { nonNullPromise, } } - ''' - - check(doc, ThrowingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['promiseNest', 'nonNullPromise'], - 'message': str(non_null_promise_error)}] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": {"promiseNest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["promiseNest", "nonNullPromise"], + "message": str(non_null_promise_error), + } + ], + }, + ) def test_nulls_a_complex_tree_of_nullable_fields_that_throw(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { sync @@ -241,33 +324,94 @@ def test_nulls_a_complex_tree_of_nullable_fields_that_throw(): } } } - ''' - check(doc, ThrowingData(), { - 'data': {'nest': {'nest': {'promise': None, 'sync': None}, - 'promise': None, - 'promiseNest': {'promise': None, 'sync': None}, - 'sync': None}, - 'promiseNest': {'nest': {'promise': None, 'sync': None}, - 'promise': None, - 'promiseNest': {'promise': None, 'sync': None}, - 'sync': None}}, - 'errors': [{'locations': [{'column': 11, 'line': 4}], 'path': ['nest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 11, 'line': 5}], 'path': ['nest', 'promise'], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 7}], 'path': ['nest', 'nest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 8}], 'path': ['nest', 'nest', 'promise'], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 11}], 'path': ['nest', 'promiseNest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 12}], 'path': ['nest', 'promiseNest', 'promise'], 'message': str(promise_error)}, - {'locations': [{'column': 11, 'line': 16}], 'path': ['promiseNest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 11, 'line': 17}], 'path': ['promiseNest', 'promise'], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 19}], 'path': ['promiseNest', 'nest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 20}], 'path': ['promiseNest', 'nest', 'promise'], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 23}], 'path': ['promiseNest', 'promiseNest', 'sync'], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 24}], 'path': ['promiseNest', 'promiseNest', 'promise'], 'message': str(promise_error)}] - }) + """ + check( + doc, + ThrowingData(), + { + "data": { + "nest": { + "nest": {"promise": None, "sync": None}, + "promise": None, + "promiseNest": {"promise": None, "sync": None}, + "sync": None, + }, + "promiseNest": { + "nest": {"promise": None, "sync": None}, + "promise": None, + "promiseNest": {"promise": None, "sync": None}, + "sync": None, + }, + }, + "errors": [ + { + "locations": [{"column": 11, "line": 4}], + "path": ["nest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 11, "line": 5}], + "path": ["nest", "promise"], + "message": str(promise_error), + }, + { + "locations": [{"column": 13, "line": 7}], + "path": ["nest", "nest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 13, "line": 8}], + "path": ["nest", "nest", "promise"], + "message": str(promise_error), + }, + { + "locations": [{"column": 13, "line": 11}], + "path": ["nest", "promiseNest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 13, "line": 12}], + "path": ["nest", "promiseNest", "promise"], + "message": str(promise_error), + }, + { + "locations": [{"column": 11, "line": 16}], + "path": ["promiseNest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 11, "line": 17}], + "path": ["promiseNest", "promise"], + "message": str(promise_error), + }, + { + "locations": [{"column": 13, "line": 19}], + "path": ["promiseNest", "nest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 13, "line": 20}], + "path": ["promiseNest", "nest", "promise"], + "message": str(promise_error), + }, + { + "locations": [{"column": 13, "line": 23}], + "path": ["promiseNest", "promiseNest", "sync"], + "message": str(sync_error), + }, + { + "locations": [{"column": 13, "line": 24}], + "path": ["promiseNest", "promiseNest", "promise"], + "message": str(promise_error), + }, + ], + }, + ) def test_nulls_the_first_nullable_object_after_a_field_throws_in_a_long_chain_of_fields_that_are_non_null(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullNest { @@ -314,129 +458,197 @@ def test_nulls_the_first_nullable_object_after_a_field_throws_in_a_long_chain_of } } } - ''' - check(doc, ThrowingData(), { - 'data': {'nest': None, 'promiseNest': None, 'anotherNest': None, 'anotherPromiseNest': None}, - 'errors': [{'locations': [{'column': 19, 'line': 8}], - 'path': [ - 'nest', 'nonNullNest', 'nonNullPromiseNest', - 'nonNullNest', 'nonNullPromiseNest', 'nonNullSync' + """ + check( + doc, + ThrowingData(), + { + "data": { + "nest": None, + "promiseNest": None, + "anotherNest": None, + "anotherPromiseNest": None, + }, + "errors": [ + { + "locations": [{"column": 19, "line": 8}], + "path": [ + "nest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullSync", ], - 'message': str(non_null_sync_error)}, - {'locations': [{'column': 19, 'line': 19}], - 'path': [ - 'promiseNest', 'nonNullNest', 'nonNullPromiseNest', - 'nonNullNest', 'nonNullPromiseNest', 'nonNullSync' + "message": str(non_null_sync_error), + }, + { + "locations": [{"column": 19, "line": 19}], + "path": [ + "promiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullSync", ], - 'message': str(non_null_sync_error)}, - {'locations': [{'column': 19, 'line': 30}], - 'path': [ - 'anotherNest', 'nonNullNest', 'nonNullPromiseNest', - 'nonNullNest', 'nonNullPromiseNest', 'nonNullPromise' + "message": str(non_null_sync_error), + }, + { + "locations": [{"column": 19, "line": 30}], + "path": [ + "anotherNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullPromise", ], - 'message': str(non_null_promise_error)}, - {'locations': [{'column': 19, 'line': 41}], - 'path': [ - 'anotherPromiseNest', 'nonNullNest', 'nonNullPromiseNest', - 'nonNullNest', 'nonNullPromiseNest', 'nonNullPromise' + "message": str(non_null_promise_error), + }, + { + "locations": [{"column": 19, "line": 41}], + "path": [ + "anotherPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullPromise", ], - 'message': str(non_null_promise_error)}] - }) + "message": str(non_null_promise_error), + }, + ], + }, + ) def test_nulls_a_nullable_field_that_returns_null(): - doc = ''' + # type: () -> None + doc = """ query Q { sync } - ''' + """ - check(doc, NullingData(), { - 'data': {'sync': None} - }) + check(doc, NullingData(), {"data": {"sync": None}}) def test_nulls_a_nullable_field_that_returns_null_in_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { promise } - ''' + """ - check(doc, NullingData(), { - 'data': {'promise': None} - }) + check(doc, NullingData(), {"data": {"promise": None}}) def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_returns_null_synchronously(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullSync, } } - ''' - check(doc, NullingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['nest', 'nonNullSync'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}] - }) + """ + check( + doc, + NullingData(), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["nest", "nonNullSync"], + "message": "Cannot return null for non-nullable field DataType.nonNullSync.", + } + ], + }, + ) def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_returns_null_in_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullPromise, } } - ''' - check(doc, NullingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['nest', 'nonNullPromise'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'}] - }) + """ + check( + doc, + NullingData(), + { + "data": {"nest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["nest", "nonNullPromise"], + "message": "Cannot return null for non-nullable field DataType.nonNullPromise.", + } + ], + }, + ) def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_synchronously(): - doc = ''' + # type: () -> None + doc = """ query Q { promiseNest { nonNullSync, } } - ''' - check(doc, NullingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'path': ['promiseNest', 'nonNullSync'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}] - }) + """ + check( + doc, + NullingData(), + { + "data": {"promiseNest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["promiseNest", "nonNullSync"], + "message": "Cannot return null for non-nullable field DataType.nonNullSync.", + } + ], + }, + ) def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_ina_a_promise(): - doc = ''' + # type: () -> None + doc = """ query Q { promiseNest { nonNullPromise } } - ''' - - check(doc, NullingData(), { - 'data': {'promiseNest': None}, - 'errors': [ - {'locations': [{'column': 17, 'line': 4}], - 'path': ['promiseNest', 'nonNullPromise'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) + """ + + check( + doc, + NullingData(), + { + "data": {"promiseNest": None}, + "errors": [ + { + "locations": [{"column": 17, "line": 4}], + "path": ["promiseNest", "nonNullPromise"], + "message": "Cannot return null for non-nullable field DataType.nonNullPromise.", + } + ], + }, + ) def test_nulls_a_complex_tree_of_nullable_fields_that_returns_null(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { sync @@ -463,39 +675,32 @@ def test_nulls_a_complex_tree_of_nullable_fields_that_returns_null(): } } } - ''' - check(doc, NullingData(), { - 'data': { - 'nest': { - 'sync': None, - 'promise': None, - 'nest': { - 'sync': None, - 'promise': None, + """ + check( + doc, + NullingData(), + { + "data": { + "nest": { + "sync": None, + "promise": None, + "nest": {"sync": None, "promise": None}, + "promiseNest": {"sync": None, "promise": None}, }, - 'promiseNest': { - 'sync': None, - 'promise': None, - } - }, - 'promiseNest': { - 'sync': None, - 'promise': None, - 'nest': { - 'sync': None, - 'promise': None, + "promiseNest": { + "sync": None, + "promise": None, + "nest": {"sync": None, "promise": None}, + "promiseNest": {"sync": None, "promise": None}, }, - 'promiseNest': { - 'sync': None, - 'promise': None, - } } - } - }) + }, + ) def test_nulls_the_first_nullable_object_after_a_field_returns_null_in_a_long_chain_of_fields_that_are_non_null(): - doc = ''' + # type: () -> None + doc = """ query Q { nest { nonNullNest { @@ -542,104 +747,153 @@ def test_nulls_the_first_nullable_object_after_a_field_returns_null_in_a_long_ch } } } - ''' - - check(doc, NullingData(), { - 'data': { - 'nest': None, - 'promiseNest': None, - 'anotherNest': None, - 'anotherPromiseNest': None + """ + + check( + doc, + NullingData(), + { + "data": { + "nest": None, + "promiseNest": None, + "anotherNest": None, + "anotherPromiseNest": None, + }, + "errors": [ + { + "locations": [{"column": 19, "line": 8}], + "path": [ + "nest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullSync", + ], + "message": "Cannot return null for non-nullable field DataType.nonNullSync.", + }, + { + "locations": [{"column": 19, "line": 19}], + "path": [ + "promiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullSync", + ], + "message": "Cannot return null for non-nullable field DataType.nonNullSync.", + }, + { + "locations": [{"column": 19, "line": 30}], + "path": [ + "anotherNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullPromise", + ], + "message": "Cannot return null for non-nullable field DataType.nonNullPromise.", + }, + { + "locations": [{"column": 19, "line": 41}], + "path": [ + "anotherPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullNest", + "nonNullPromiseNest", + "nonNullPromise", + ], + "message": "Cannot return null for non-nullable field DataType.nonNullPromise.", + }, + ], }, - 'errors': [ - {'locations': [{'column': 19, 'line': 8}], - 'path': ['nest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullSync'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}, - {'locations': [{'column': 19, 'line': 19}], - 'path': ['promiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullSync'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}, - {'locations': [{'column': 19, 'line': 30}], - 'path': ['anotherNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullPromise'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'}, - {'locations': [{'column': 19, 'line': 41}], - 'path': ['anotherPromiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullNest', - 'nonNullPromiseNest', - 'nonNullPromise'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) + ) def test_nulls_the_top_level_if_sync_non_nullable_field_throws(): - doc = ''' + # type: () -> None + doc = """ query Q { nonNullSync } - ''' - check(doc, ThrowingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'path': ['nonNullSync'], - 'message': str(non_null_sync_error)} - ] - }) + """ + check( + doc, + ThrowingData(), + { + "data": None, + "errors": [ + { + "locations": [{"column": 19, "line": 2}], + "path": ["nonNullSync"], + "message": str(non_null_sync_error), + } + ], + }, + ) def test_nulls_the_top_level_if_async_non_nullable_field_errors(): - doc = ''' + # type: () -> None + doc = """ query Q { nonNullPromise } - ''' - - check(doc, ThrowingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'path': ['nonNullPromise'], - 'message': str(non_null_promise_error)} - ] - }) + """ + + check( + doc, + ThrowingData(), + { + "data": None, + "errors": [ + { + "locations": [{"column": 19, "line": 2}], + "path": ["nonNullPromise"], + "message": str(non_null_promise_error), + } + ], + }, + ) def test_nulls_the_top_level_if_sync_non_nullable_field_returns_null(): - doc = ''' + # type: () -> None + doc = """ query Q { nonNullSync } - ''' - check(doc, NullingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'path': ['nonNullSync'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'} - ] - }) + """ + check( + doc, + NullingData(), + { + "data": None, + "errors": [ + { + "locations": [{"column": 19, "line": 2}], + "path": ["nonNullSync"], + "message": "Cannot return null for non-nullable field DataType.nonNullSync.", + } + ], + }, + ) def test_nulls_the_top_level_if_async_non_nullable_field_resolves_null(): - doc = ''' + # type: () -> None + doc = """ query Q { nonNullPromise } - ''' - check(doc, NullingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'path': ['nonNullPromise'], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) + """ + check( + doc, + NullingData(), + { + "data": None, + "errors": [ + { + "locations": [{"column": 19, "line": 2}], + "path": ["nonNullPromise"], + "message": "Cannot return null for non-nullable field DataType.nonNullPromise.", + } + ], + }, + ) + diff --git a/graphql/execution/tests/test_resolve.py b/graphql/execution/tests/test_resolve.py index 5850063d..d6788f38 100644 --- a/graphql/execution/tests/test_resolve.py +++ b/graphql/execution/tests/test_resolve.py @@ -1,17 +1,34 @@ +# type: ignore import json from collections import OrderedDict from graphql import graphql -from graphql.type import (GraphQLArgument, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInt, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLField, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) from promise import Promise +# from graphql.execution.base import ResolveInfo +# from typing import Any +# from typing import Optional +# from promise.promise import Promise +# from graphql.type.definition import GraphQLField +# from graphql.type.schema import GraphQLSchema + class CustomPromise(Promise): @classmethod def fulfilled(cls, x): + # type: (str) -> CustomPromise p = cls() p.fulfill(x) return p @@ -26,154 +43,184 @@ def rejected(cls, reason): def _test_schema(test_field): + # type: (GraphQLField) -> GraphQLSchema return GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'test': test_field - } - ) + query=GraphQLObjectType(name="Query", fields={"test": test_field}) ) def test_default_function_accesses_properties(): + # type: () -> None schema = _test_schema(GraphQLField(GraphQLString)) class source: - test = 'testValue' + test = "testValue" - result = graphql(schema, '{ test }', source) + result = graphql(schema, "{ test }", source) assert not result.errors - assert result.data == {'test': 'testValue'} + assert result.data == {"test": "testValue"} def test_default_function_calls_methods(): + # type: () -> None schema = _test_schema(GraphQLField(GraphQLString)) class source: - _secret = 'testValue' + _secret = "testValue" def test(self): + # type: () -> str return self._secret - result = graphql(schema, '{ test }', source()) + result = graphql(schema, "{ test }", source()) assert not result.errors - assert result.data == {'test': 'testValue'} + assert result.data == {"test": "testValue"} def test_uses_provided_resolve_function(): + # type: () -> None def resolver(source, info, **args): - return json.dumps([source, args], separators=(',', ':')) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aStr', GraphQLArgument(GraphQLString)), - ('aInt', GraphQLArgument(GraphQLInt)), - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) + # type: (Optional[str], ResolveInfo, **Any) -> str + return json.dumps([source, args], separators=(",", ":")) + + schema = _test_schema( + GraphQLField( + GraphQLString, + args=OrderedDict( + [ + ("aStr", GraphQLArgument(GraphQLString)), + ("aInt", GraphQLArgument(GraphQLInt)), + ] + ), + resolver=resolver, + ) + ) + + result = graphql(schema, "{ test }", None) assert not result.errors - assert result.data == {'test': '[null,{}]'} + assert result.data == {"test": "[null,{}]"} - result = graphql(schema, '{ test(aStr: "String!") }', 'Source!') + result = graphql(schema, '{ test(aStr: "String!") }', "Source!") assert not result.errors - assert result.data == {'test': '["Source!",{"aStr":"String!"}]'} + assert result.data == {"test": '["Source!",{"aStr":"String!"}]'} - result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', 'Source!') + result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', "Source!") assert not result.errors assert result.data in [ - {'test': '["Source!",{"aStr":"String!","aInt":-123}]'}, - {'test': '["Source!",{"aInt":-123,"aStr":"String!"}]'} + {"test": '["Source!",{"aStr":"String!","aInt":-123}]'}, + {"test": '["Source!",{"aInt":-123,"aStr":"String!"}]'}, ] def test_handles_resolved_promises(): + # type: () -> None def resolver(source, info, **args): - return Promise.resolve('foo') + # type: (Optional[Any], ResolveInfo, **Any) -> Promise + return Promise.resolve("foo") - schema = _test_schema(GraphQLField( - GraphQLString, - resolver=resolver - )) + schema = _test_schema(GraphQLField(GraphQLString, resolver=resolver)) - result = graphql(schema, '{ test }', None) + result = graphql(schema, "{ test }", None) assert not result.errors - assert result.data == {'test': 'foo'} + assert result.data == {"test": "foo"} def test_handles_resolved_custom_promises(): + # type: () -> None def resolver(source, info, **args): - return CustomPromise.resolve('custom_foo') + # type: (Optional[Any], ResolveInfo, **Any) -> CustomPromise + return CustomPromise.resolve("custom_foo") - schema = _test_schema(GraphQLField( - GraphQLString, - resolver=resolver - )) + schema = _test_schema(GraphQLField(GraphQLString, resolver=resolver)) - result = graphql(schema, '{ test }', None) + result = graphql(schema, "{ test }", None) assert not result.errors - assert result.data == {'test': 'custom_foo'} + assert result.data == {"test": "custom_foo"} def test_maps_argument_out_names_well(): + # type: () -> None def resolver(source, info, **args): - return json.dumps([source, args], separators=(',', ':')) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aStr', GraphQLArgument(GraphQLString, out_name="a_str")), - ('aInt', GraphQLArgument(GraphQLInt, out_name="a_int")), - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) + # type: (Optional[str], ResolveInfo, **Any) -> str + return json.dumps([source, args], separators=(",", ":")) + + schema = _test_schema( + GraphQLField( + GraphQLString, + args=OrderedDict( + [ + ("aStr", GraphQLArgument(GraphQLString, out_name="a_str")), + ("aInt", GraphQLArgument(GraphQLInt, out_name="a_int")), + ] + ), + resolver=resolver, + ) + ) + + result = graphql(schema, "{ test }", None) assert not result.errors - assert result.data == {'test': '[null,{}]'} + assert result.data == {"test": "[null,{}]"} - result = graphql(schema, '{ test(aStr: "String!") }', 'Source!') + result = graphql(schema, '{ test(aStr: "String!") }', "Source!") assert not result.errors - assert result.data == {'test': '["Source!",{"a_str":"String!"}]'} + assert result.data == {"test": '["Source!",{"a_str":"String!"}]'} - result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', 'Source!') + result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', "Source!") assert not result.errors assert result.data in [ - {'test': '["Source!",{"a_str":"String!","a_int":-123}]'}, - {'test': '["Source!",{"a_int":-123,"a_str":"String!"}]'} + {"test": '["Source!",{"a_str":"String!","a_int":-123}]'}, + {"test": '["Source!",{"a_int":-123,"a_str":"String!"}]'}, ] def test_maps_argument_out_names_well_with_input(): + # type: () -> None def resolver(source, info, **args): - return json.dumps([source, args], separators=(',', ':')) - - TestInputObject = GraphQLInputObjectType('TestInputObject', lambda: OrderedDict([ - ('inputOne', GraphQLInputObjectField(GraphQLString, out_name="input_one")), - ('inputRecursive', GraphQLInputObjectField(TestInputObject, out_name="input_recursive")), - ])) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aInput', GraphQLArgument(TestInputObject, out_name="a_input")) - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) + # type: (Optional[str], ResolveInfo, **Any) -> str + return json.dumps([source, args], separators=(",", ":")) + + TestInputObject = GraphQLInputObjectType( + "TestInputObject", + lambda: OrderedDict( + [ + ( + "inputOne", + GraphQLInputObjectField(GraphQLString, out_name="input_one"), + ), + ( + "inputRecursive", + GraphQLInputObjectField( + TestInputObject, out_name="input_recursive" + ), + ), + ] + ), + ) + + schema = _test_schema( + GraphQLField( + GraphQLString, + args=OrderedDict( + [("aInput", GraphQLArgument(TestInputObject, out_name="a_input"))] + ), + resolver=resolver, + ) + ) + + result = graphql(schema, "{ test }", None) assert not result.errors - assert result.data == {'test': '[null,{}]'} + assert result.data == {"test": "[null,{}]"} - result = graphql(schema, '{ test(aInput: {inputOne: "String!"} ) }', 'Source!') + result = graphql(schema, '{ test(aInput: {inputOne: "String!"} ) }', "Source!") assert not result.errors - assert result.data == {'test': '["Source!",{"a_input":{"input_one":"String!"}}]'} + assert result.data == {"test": '["Source!",{"a_input":{"input_one":"String!"}}]'} - result = graphql(schema, '{ test(aInput: {inputRecursive:{inputOne: "SourceRecursive!"}} ) }', 'Source!') + result = graphql( + schema, + '{ test(aInput: {inputRecursive:{inputOne: "SourceRecursive!"}} ) }', + "Source!", + ) assert not result.errors assert result.data == { - 'test': '["Source!",{"a_input":{"input_recursive":{"input_one":"SourceRecursive!"}}}]' + "test": '["Source!",{"a_input":{"input_recursive":{"input_one":"SourceRecursive!"}}}]' } diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py index 2acb56a9..6175dc80 100644 --- a/graphql/execution/tests/test_subscribe.py +++ b/graphql/execution/tests/test_subscribe.py @@ -1,58 +1,97 @@ +# type: ignore from collections import OrderedDict, namedtuple from rx import Observable, Observer from rx.subjects import Subject -from graphql import parse, GraphQLObjectType, GraphQLString, GraphQLBoolean, GraphQLInt, GraphQLField, GraphQLList, GraphQLSchema, graphql, subscribe +from graphql import ( + parse, + GraphQLObjectType, + GraphQLString, + GraphQLBoolean, + GraphQLInt, + GraphQLField, + GraphQLList, + GraphQLSchema, + graphql, + subscribe, +) + +# from graphql.execution.base import ResolveInfo +# from rx.core.anonymousobservable import AnonymousObservable +# from rx.subjects.subject import Subject +# from typing import Optional +# from typing import Union +# from mypy_extensions import NoReturn +# from typing import Any +# from typing import Callable +# from graphql.type.schema import GraphQLSchema +# from graphql.execution.base import ExecutionResult +# from typing import Tuple -Email = namedtuple('Email', 'from_,subject,message,unread') +Email = namedtuple("Email", "from_,subject,message,unread") EmailType = GraphQLObjectType( - name='Email', - fields=OrderedDict([ - ('from', GraphQLField(GraphQLString, resolver=lambda x, info: x.from_)), - ('subject', GraphQLField(GraphQLString)), - ('message', GraphQLField(GraphQLString)), - ('unread', GraphQLField(GraphQLBoolean)), - ]) + name="Email", + fields=OrderedDict( + [ + ("from", GraphQLField(GraphQLString, resolver=lambda x, info: x.from_)), + ("subject", GraphQLField(GraphQLString)), + ("message", GraphQLField(GraphQLString)), + ("unread", GraphQLField(GraphQLBoolean)), + ] + ), ) InboxType = GraphQLObjectType( - name='Inbox', - fields=OrderedDict([ - ('total', GraphQLField(GraphQLInt, - resolver=lambda inbox, context: len(inbox.emails))), - ('unread', GraphQLField(GraphQLInt, - resolver=lambda inbox, context: len([e for e in inbox.emails if e.unread]))), - ('emails', GraphQLField(GraphQLList(EmailType))), - ]) + name="Inbox", + fields=OrderedDict( + [ + ( + "total", + GraphQLField( + GraphQLInt, resolver=lambda inbox, context: len(inbox.emails) + ), + ), + ( + "unread", + GraphQLField( + GraphQLInt, + resolver=lambda inbox, context: len( + [e for e in inbox.emails if e.unread] + ), + ), + ), + ("emails", GraphQLField(GraphQLList(EmailType))), + ] + ), ) QueryType = GraphQLObjectType( - name='Query', - fields=OrderedDict([ - ('inbox', GraphQLField(InboxType)), - ]) + name="Query", fields=OrderedDict([("inbox", GraphQLField(InboxType))]) ) EmailEventType = GraphQLObjectType( - name='EmailEvent', - fields=OrderedDict([ - ('email', GraphQLField(EmailType, - resolver=lambda root, info: root[0])), - ('inbox', GraphQLField(InboxType, - resolver=lambda root, info: root[1])), - ]) + name="EmailEvent", + fields=OrderedDict( + [ + ("email", GraphQLField(EmailType, resolver=lambda root, info: root[0])), + ("inbox", GraphQLField(InboxType, resolver=lambda root, info: root[1])), + ] + ), ) def get_unbound_function(func): - if not getattr(func, '__self__', True): + # type: (Callable) -> Callable + if not getattr(func, "__self__", True): return func.__func__ return func def email_schema_with_resolvers(resolve_fn=None): + # type: (Callable) -> GraphQLSchema def default_resolver(root, info): - func = getattr(root, 'importantEmail', None) + # type: (Any, ResolveInfo) -> Union[AnonymousObservable, Subject] + func = getattr(root, "importantEmail", None) if func: func = get_unbound_function(func) return func() @@ -61,14 +100,18 @@ def default_resolver(root, info): return GraphQLSchema( query=QueryType, subscription=GraphQLObjectType( - name='Subscription', - fields=OrderedDict([ - ('importantEmail', GraphQLField( - EmailEventType, - resolver=resolve_fn or default_resolver, - )) - ]) - ) + name="Subscription", + fields=OrderedDict( + [ + ( + "importantEmail", + GraphQLField( + EmailEventType, resolver=resolve_fn or default_resolver + ), + ) + ] + ), + ), ) @@ -86,14 +129,20 @@ def on_completed(self): self.has_on_completed = True -def create_subscription(stream, schema=email_schema, ast=None, vars=None): +def create_subscription( + stream, # type: Subject + schema=email_schema, # type: GraphQLSchema + ast=None, # type: Optional[Any] + vars=None, # type: Optional[Any] +): + # type: (...) -> Tuple[Callable, Union[ExecutionResult, AnonymousObservable]] class Root(object): class inbox(object): emails = [ Email( - from_='joe@graphql.org', - subject='Hello', - message='Hello World', + from_="joe@graphql.org", + subject="Hello", + message="Hello World", unread=False, ) ] @@ -102,11 +151,13 @@ def importantEmail(): return stream def send_important_email(new_email): + # type: (Email) -> None Root.inbox.emails.append(new_email) stream.on_next((new_email, Root.inbox)) # stream.on_completed() - default_ast = parse(''' + default_ast = parse( + """ subscription { importantEmail { email { @@ -119,53 +170,48 @@ def send_important_email(new_email): } } } - ''') - - return send_important_email, graphql( - schema, - ast or default_ast, - Root, - None, - vars, - allow_subscriptions=True, + """ + ) + + return ( + send_important_email, + graphql(schema, ast or default_ast, Root, None, vars, allow_subscriptions=True), ) def test_accepts_an_object_with_named_properties_as_arguments(): - document = parse(''' + # type: () -> None + document = parse( + """ subscription { importantEmail } - ''') - result = subscribe( - email_schema, - document, - root_value=None + """ ) + result = subscribe(email_schema, document, root_value=None) assert isinstance(result, Observable) def test_accepts_multiple_subscription_fields_defined_in_schema(): + # type: () -> None SubscriptionTypeMultiple = GraphQLObjectType( - name='Subscription', - fields=OrderedDict([ - ('importantEmail', GraphQLField(EmailEventType)), - ('nonImportantEmail', GraphQLField(EmailEventType)), - ]) - ) - test_schema = GraphQLSchema( - query=QueryType, - subscription=SubscriptionTypeMultiple + name="Subscription", + fields=OrderedDict( + [ + ("importantEmail", GraphQLField(EmailEventType)), + ("nonImportantEmail", GraphQLField(EmailEventType)), + ] + ), ) + test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionTypeMultiple) stream = Subject() - send_important_email, subscription = create_subscription( - stream, test_schema) + send_important_email, subscription = create_subscription(stream, test_schema) email = Email( - from_='yuzhi@graphql.org', - subject='Alright', - message='Tests are good', + from_="yuzhi@graphql.org", + subject="Alright", + message="Tests are good", unread=True, ) l = [] @@ -175,26 +221,29 @@ def test_accepts_multiple_subscription_fields_defined_in_schema(): def test_accepts_type_definition_with_sync_subscribe_function(): + # type: () -> None SubscriptionType = GraphQLObjectType( - name='Subscription', - fields=OrderedDict([ - ('importantEmail', GraphQLField( - EmailEventType, resolver=lambda *_: Observable.from_([None]))), - ]) - ) - test_schema = GraphQLSchema( - query=QueryType, - subscription=SubscriptionType + name="Subscription", + fields=OrderedDict( + [ + ( + "importantEmail", + GraphQLField( + EmailEventType, resolver=lambda *_: Observable.from_([None]) + ), + ) + ] + ), ) + test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType) stream = Subject() - send_important_email, subscription = create_subscription( - stream, test_schema) + send_important_email, subscription = create_subscription(stream, test_schema) email = Email( - from_='yuzhi@graphql.org', - subject='Alright', - message='Tests are good', + from_="yuzhi@graphql.org", + subject="Alright", + message="Tests are good", unread=True, ) l = [] @@ -205,44 +254,50 @@ def test_accepts_type_definition_with_sync_subscribe_function(): def test_throws_an_error_if_subscribe_does_not_return_an_iterator(): + # type: () -> None SubscriptionType = GraphQLObjectType( - name='Subscription', - fields=OrderedDict([ - ('importantEmail', GraphQLField( - EmailEventType, resolver=lambda *_: None)), - ]) - ) - test_schema = GraphQLSchema( - query=QueryType, - subscription=SubscriptionType + name="Subscription", + fields=OrderedDict( + [("importantEmail", GraphQLField(EmailEventType, resolver=lambda *_: None))] + ), ) + test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType) stream = Subject() - _, subscription = create_subscription( - stream, test_schema) + _, subscription = create_subscription(stream, test_schema) - assert str( - subscription.errors[0]) == 'Subscription must return Async Iterable or Observable. Received: None' + assert ( + str(subscription.errors[0]) + == "Subscription must return Async Iterable or Observable. Received: None" + ) def test_returns_an_error_if_subscribe_function_returns_error(): + # type: () -> None exc = Exception("Throw!") def thrower(root, info): + # type: (Optional[Any], ResolveInfo) -> NoReturn raise exc erroring_email_schema = email_schema_with_resolvers(thrower) - result = subscribe(erroring_email_schema, parse(''' + result = subscribe( + erroring_email_schema, + parse( + """ subscription { importantEmail } - ''')) + """ + ), + ) assert result.errors == [exc] # Subscription Publish Phase def test_produces_a_payload_for_multiple_subscribe_in_same_subscription(): + # type: () -> None stream = Subject() send_important_email, subscription1 = create_subscription(stream) subscription2 = create_subscription(stream)[1] @@ -254,23 +309,17 @@ def test_produces_a_payload_for_multiple_subscribe_in_same_subscription(): subscription2.subscribe(payload2.append) email = Email( - from_='yuzhi@graphql.org', - subject='Alright', - message='Tests are good', + from_="yuzhi@graphql.org", + subject="Alright", + message="Tests are good", unread=True, ) send_important_email(email) expected_payload = { - 'importantEmail': { - 'email': { - 'from': 'yuzhi@graphql.org', - 'subject': 'Alright', - }, - 'inbox': { - 'unread': 1, - 'total': 2, - }, + "importantEmail": { + "email": {"from": "yuzhi@graphql.org", "subject": "Alright"}, + "inbox": {"unread": 1, "total": 2}, } } @@ -280,50 +329,43 @@ def test_produces_a_payload_for_multiple_subscribe_in_same_subscription(): # Subscription Publish Phase def test_produces_a_payload_per_subscription_event(): + # type: () -> None stream = Subject() send_important_email, subscription = create_subscription(stream) payload = [] subscription.subscribe(payload.append) - send_important_email(Email( - from_='yuzhi@graphql.org', - subject='Alright', - message='Tests are good', - unread=True, - )) + send_important_email( + Email( + from_="yuzhi@graphql.org", + subject="Alright", + message="Tests are good", + unread=True, + ) + ) expected_payload = { - 'importantEmail': { - 'email': { - 'from': 'yuzhi@graphql.org', - 'subject': 'Alright', - }, - 'inbox': { - 'unread': 1, - 'total': 2, - }, + "importantEmail": { + "email": {"from": "yuzhi@graphql.org", "subject": "Alright"}, + "inbox": {"unread": 1, "total": 2}, } } assert len(payload) == 1 assert payload[0].data == expected_payload - send_important_email(Email( - from_='hyo@graphql.org', - subject='Tools', - message='I <3 making things', - unread=True, - )) + send_important_email( + Email( + from_="hyo@graphql.org", + subject="Tools", + message="I <3 making things", + unread=True, + ) + ) expected_payload = { - 'importantEmail': { - 'email': { - 'from': 'hyo@graphql.org', - 'subject': 'Tools', - }, - 'inbox': { - 'unread': 2, - 'total': 3, - }, + "importantEmail": { + "email": {"from": "hyo@graphql.org", "subject": "Tools"}, + "inbox": {"unread": 2, "total": 3}, } } @@ -333,59 +375,54 @@ def test_produces_a_payload_per_subscription_event(): # The client decides to disconnect stream.on_completed() - send_important_email(Email( - from_='adam@graphql.org', - subject='Important', - message='Read me please', - unread=True, - )) + send_important_email( + Email( + from_="adam@graphql.org", + subject="Important", + message="Read me please", + unread=True, + ) + ) assert len(payload) == 2 def test_event_order_is_correct_for_multiple_publishes(): + # type: () -> None stream = Subject() send_important_email, subscription = create_subscription(stream) payload = [] subscription.subscribe(payload.append) - send_important_email(Email( - from_='yuzhi@graphql.org', - subject='Message', - message='Tests are good', - unread=True, - )) - send_important_email(Email( - from_='yuzhi@graphql.org', - subject='Message 2', - message='Tests are good 2', - unread=True, - )) + send_important_email( + Email( + from_="yuzhi@graphql.org", + subject="Message", + message="Tests are good", + unread=True, + ) + ) + send_important_email( + Email( + from_="yuzhi@graphql.org", + subject="Message 2", + message="Tests are good 2", + unread=True, + ) + ) expected_payload1 = { - 'importantEmail': { - 'email': { - 'from': 'yuzhi@graphql.org', - 'subject': 'Message', - }, - 'inbox': { - 'unread': 1, - 'total': 2, - }, + "importantEmail": { + "email": {"from": "yuzhi@graphql.org", "subject": "Message"}, + "inbox": {"unread": 1, "total": 2}, } } expected_payload2 = { - 'importantEmail': { - 'email': { - 'from': 'yuzhi@graphql.org', - 'subject': 'Message 2', - }, - 'inbox': { - 'unread': 2, - 'total': 3, - }, + "importantEmail": { + "email": {"from": "yuzhi@graphql.org", "subject": "Message 2"}, + "inbox": {"unread": 2, "total": 3}, } } diff --git a/graphql/execution/tests/test_union_interface.py b/graphql/execution/tests/test_union_interface.py index d45d2625..bd61ba30 100644 --- a/graphql/execution/tests/test_union_interface.py +++ b/graphql/execution/tests/test_union_interface.py @@ -1,90 +1,96 @@ +# type: ignore from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLBoolean, GraphQLField, GraphQLInterfaceType, - GraphQLList, GraphQLObjectType, GraphQLSchema, - GraphQLString, GraphQLUnionType) +from graphql.type import ( + GraphQLBoolean, + GraphQLField, + GraphQLInterfaceType, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) +# from typing import List +# from graphql.execution.base import ResolveInfo +# from graphql.type.definition import GraphQLObjectType +# from typing import Union -class Dog(object): +class Dog(object): def __init__(self, name, barks): self.name = name self.barks = barks class Cat(object): - def __init__(self, name, meows): self.name = name self.meows = meows class Person(object): - def __init__(self, name, pets, friends): + # type: (str, List, List[Person]) -> None self.name = name self.pets = pets self.friends = friends -NamedType = GraphQLInterfaceType('Named', { - 'name': GraphQLField(GraphQLString) -}) +NamedType = GraphQLInterfaceType("Named", {"name": GraphQLField(GraphQLString)}) DogType = GraphQLObjectType( - name='Dog', + name="Dog", interfaces=[NamedType], - fields={ - 'name': GraphQLField(GraphQLString), - 'barks': GraphQLField(GraphQLBoolean), - }, - is_type_of=lambda value, info: isinstance(value, Dog) + fields={"name": GraphQLField(GraphQLString), "barks": GraphQLField(GraphQLBoolean)}, + is_type_of=lambda value, info: isinstance(value, Dog), ) CatType = GraphQLObjectType( - name='Cat', + name="Cat", interfaces=[NamedType], - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean), - }, - is_type_of=lambda value, info: isinstance(value, Cat) + fields={"name": GraphQLField(GraphQLString), "meows": GraphQLField(GraphQLBoolean)}, + is_type_of=lambda value, info: isinstance(value, Cat), ) def resolve_pet_type(value, info): + # type: (Union[Cat, Dog], ResolveInfo) -> GraphQLObjectType if isinstance(value, Dog): return DogType if isinstance(value, Cat): return CatType -PetType = GraphQLUnionType('Pet', [DogType, CatType], - resolve_type=resolve_pet_type) +PetType = GraphQLUnionType("Pet", [DogType, CatType], resolve_type=resolve_pet_type) PersonType = GraphQLObjectType( - name='Person', + name="Person", interfaces=[NamedType], fields={ - 'name': GraphQLField(GraphQLString), - 'pets': GraphQLField(GraphQLList(PetType)), - 'friends': GraphQLField(GraphQLList(NamedType)), + "name": GraphQLField(GraphQLString), + "pets": GraphQLField(GraphQLList(PetType)), + "friends": GraphQLField(GraphQLList(NamedType)), }, - is_type_of=lambda value, info: isinstance(value, Person) + is_type_of=lambda value, info: isinstance(value, Person), ) schema = GraphQLSchema(query=PersonType, types=[PetType]) -garfield = Cat('Garfield', False) -odie = Dog('Odie', True) -liz = Person('Liz', [], []) -john = Person('John', [garfield, odie], [liz, odie]) +garfield = Cat("Garfield", False) +odie = Dog("Odie", True) +liz = Person("Liz", [], []) +john = Person("John", [garfield, odie], [liz, odie]) # Execute: Union and intersection types + def test_can_introspect_on_union_and_intersection_types(): - ast = parse(''' + # type: () -> None + ast = parse( + """ { Named: __type(name: "Named") { kind @@ -104,35 +110,38 @@ def test_can_introspect_on_union_and_intersection_types(): enumValues { name } inputFields { name } } - }''') + }""" + ) result = execute(schema, ast) assert not result.errors assert result.data == { - 'Named': { - 'enumValues': None, - 'name': 'Named', - 'kind': 'INTERFACE', - 'interfaces': None, - 'fields': [{'name': 'name'}], - 'possibleTypes': [{'name': 'Person'}, {'name': 'Dog'}, {'name': 'Cat'}], - 'inputFields': None + "Named": { + "enumValues": None, + "name": "Named", + "kind": "INTERFACE", + "interfaces": None, + "fields": [{"name": "name"}], + "possibleTypes": [{"name": "Person"}, {"name": "Dog"}, {"name": "Cat"}], + "inputFields": None, + }, + "Pet": { + "enumValues": None, + "name": "Pet", + "kind": "UNION", + "interfaces": None, + "fields": None, + "possibleTypes": [{"name": "Dog"}, {"name": "Cat"}], + "inputFields": None, }, - 'Pet': { - 'enumValues': None, - 'name': 'Pet', - 'kind': 'UNION', - 'interfaces': None, - 'fields': None, - 'possibleTypes': [{'name': 'Dog'}, {'name': 'Cat'}], - 'inputFields': None - } } def test_executes_using_union_types(): + # type: () -> None # NOTE: This is an *invalid* query, but it should be an *executable* query. - ast = parse(''' + ast = parse( + """ { __typename name @@ -143,22 +152,25 @@ def test_executes_using_union_types(): meows } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] + "__typename": "Person", + "name": "John", + "pets": [ + {"__typename": "Cat", "name": "Garfield", "meows": False}, + {"__typename": "Dog", "name": "Odie", "barks": True}, + ], } def test_executes_union_types_with_inline_fragment(): + # type: () -> None # This is the valid version of the query in the above test. - ast = parse(''' + ast = parse( + """ { __typename name @@ -174,22 +186,25 @@ def test_executes_union_types_with_inline_fragment(): } } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] + "__typename": "Person", + "name": "John", + "pets": [ + {"__typename": "Cat", "name": "Garfield", "meows": False}, + {"__typename": "Dog", "name": "Odie", "barks": True}, + ], } def test_executes_using_interface_types(): + # type: () -> None # NOTE: This is an *invalid* query, but it should be an *executable* query. - ast = parse(''' + ast = parse( + """ { __typename name @@ -200,22 +215,25 @@ def test_executes_using_interface_types(): meows } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] + "__typename": "Person", + "name": "John", + "friends": [ + {"__typename": "Person", "name": "Liz"}, + {"__typename": "Dog", "name": "Odie", "barks": True}, + ], } def test_executes_interface_types_with_inline_fragment(): + # type: () -> None # This is the valid version of the query in the above test. - ast = parse(''' + ast = parse( + """ { __typename name @@ -230,21 +248,24 @@ def test_executes_interface_types_with_inline_fragment(): } } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] + "__typename": "Person", + "name": "John", + "friends": [ + {"__typename": "Person", "name": "Liz"}, + {"__typename": "Dog", "name": "Odie", "barks": True}, + ], } def test_allows_fragment_conditions_to_be_abstract_types(): - ast = parse(''' + # type: () -> None + ast = parse( + """ { __typename name @@ -272,25 +293,28 @@ def test_allows_fragment_conditions_to_be_abstract_types(): meows } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} + "__typename": "Person", + "name": "John", + "pets": [ + {"__typename": "Cat", "name": "Garfield", "meows": False}, + {"__typename": "Dog", "name": "Odie", "barks": True}, + ], + "friends": [ + {"__typename": "Person", "name": "Liz"}, + {"__typename": "Dog", "name": "Odie", "barks": True}, ], - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] } def test_only_include_fields_from_matching_fragment_condition(): - ast = parse(''' + # type: () -> None + ast = parse( + """ { pets { ...PetFields } } @@ -300,56 +324,52 @@ def test_only_include_fields_from_matching_fragment_condition(): name } } - ''') + """ + ) result = execute(schema, ast, john) assert not result.errors assert result.data == { - 'pets': [ - {'__typename': 'Cat'}, - {'__typename': 'Dog', 'name': 'Odie'} - ], + "pets": [{"__typename": "Cat"}, {"__typename": "Dog", "name": "Odie"}] } def test_gets_execution_info_in_resolver(): + # type: () -> None class encountered: schema = None root_value = None context = None def resolve_type(obj, info): + # type: (Person, ResolveInfo) -> GraphQLObjectType encountered.schema = info.schema encountered.root_value = info.root_value encountered.context = context return PersonType2 NamedType2 = GraphQLInterfaceType( - name='Named', - fields={ - 'name': GraphQLField(GraphQLString) - }, - resolve_type=resolve_type + name="Named", + fields={"name": GraphQLField(GraphQLString)}, + resolve_type=resolve_type, ) PersonType2 = GraphQLObjectType( - name='Person', + name="Person", interfaces=[NamedType2], fields={ - 'name': GraphQLField(GraphQLString), - 'friends': GraphQLField(GraphQLList(NamedType2)) - } + "name": GraphQLField(GraphQLString), + "friends": GraphQLField(GraphQLList(NamedType2)), + }, ) schema2 = GraphQLSchema(query=PersonType2) - john2 = Person('John', [], [liz]) - context = {'hey'} - ast = parse('''{ name, friends { name } }''') + john2 = Person("John", [], [liz]) + context = {"hey"} + ast = parse("""{ name, friends { name } }""") result = execute(schema2, ast, john2, context_value=context) assert not result.errors - assert result.data == { - 'name': 'John', 'friends': [{'name': 'Liz'}] - } + assert result.data == {"name": "John", "friends": [{"name": "Liz"}]} assert encountered.schema == schema2 assert encountered.root_value == john2 diff --git a/graphql/execution/tests/test_variables.py b/graphql/execution/tests/test_variables.py index 7f001caa..19b86283 100644 --- a/graphql/execution/tests/test_variables.py +++ b/graphql/execution/tests/test_variables.py @@ -1,3 +1,4 @@ +# type: ignore import json from collections import OrderedDict @@ -6,16 +7,33 @@ from graphql.error import GraphQLError, format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLField, GraphQLBoolean, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLList, GraphQLNonNull, GraphQLObjectType, - GraphQLScalarType, GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLField, + GraphQLBoolean, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLString, +) + +# from typing import Any +# from graphql.execution.base import ResolveInfo +# from typing import Optional +# from typing import Dict +# from typing import Union TestComplexScalar = GraphQLScalarType( - name='ComplexScalar', - serialize=lambda v: 'SerializedValue' if v == 'DeserializedValue' else None, - parse_value=lambda v: 'DeserializedValue' if v == 'SerializedValue' else None, - parse_literal=lambda v: 'DeserializedValue' if v.value == 'SerializedValue' else None + name="ComplexScalar", + serialize=lambda v: "SerializedValue" if v == "DeserializedValue" else None, + parse_value=lambda v: "DeserializedValue" if v == "SerializedValue" else None, + parse_literal=lambda v: "DeserializedValue" + if v.value == "SerializedValue" + else None, ) @@ -23,675 +41,745 @@ class my_special_dict(dict): pass -TestInputObject = GraphQLInputObjectType('TestInputObject', OrderedDict([ - ('a', GraphQLInputObjectField(GraphQLString)), - ('b', GraphQLInputObjectField(GraphQLList(GraphQLString))), - ('c', GraphQLInputObjectField(GraphQLNonNull(GraphQLString))), - ('d', GraphQLInputObjectField(TestComplexScalar)) -])) +TestInputObject = GraphQLInputObjectType( + "TestInputObject", + OrderedDict( + [ + ("a", GraphQLInputObjectField(GraphQLString)), + ("b", GraphQLInputObjectField(GraphQLList(GraphQLString))), + ("c", GraphQLInputObjectField(GraphQLNonNull(GraphQLString))), + ("d", GraphQLInputObjectField(TestComplexScalar)), + ] + ), +) -TestCustomInputObject = GraphQLInputObjectType('TestCustomInputObject', OrderedDict([ - ('a', GraphQLInputObjectField(GraphQLString)), -]), container_type=my_special_dict) +TestCustomInputObject = GraphQLInputObjectType( + "TestCustomInputObject", + OrderedDict([("a", GraphQLInputObjectField(GraphQLString))]), + container_type=my_special_dict, +) -def stringify(obj): return json.dumps(obj, sort_keys=True) +def stringify(obj): + # type: (Any) -> str + return json.dumps(obj, sort_keys=True) def input_to_json(obj, info, **args): - input = args.get('input') + # type: (Optional[Any], ResolveInfo, **Any) -> Optional[str] + input = args.get("input") if input: return stringify(input) TestNestedInputObject = GraphQLInputObjectType( - name='TestNestedInputObject', + name="TestNestedInputObject", fields={ - 'na': GraphQLInputObjectField(GraphQLNonNull(TestInputObject)), - 'nb': GraphQLInputObjectField(GraphQLNonNull(GraphQLString)) - } + "na": GraphQLInputObjectField(GraphQLNonNull(TestInputObject)), + "nb": GraphQLInputObjectField(GraphQLNonNull(GraphQLString)), + }, ) -TestType = GraphQLObjectType('TestType', { - 'fieldWithObjectInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(TestInputObject)}, - resolver=input_to_json), - 'fieldWithCustomObjectInput': GraphQLField( - GraphQLBoolean, - args={'input': GraphQLArgument(TestCustomInputObject)}, - resolver=lambda root, info, **args: isinstance(args.get('input'), my_special_dict)), - 'fieldWithNullableStringInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLString)}, - resolver=input_to_json), - 'fieldWithNonNullableStringInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLNonNull(GraphQLString))}, - resolver=input_to_json), - 'fieldWithDefaultArgumentValue': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLString, 'Hello World')}, - resolver=input_to_json), - 'fieldWithNestedInputObject': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(TestNestedInputObject, 'Hello World')}, - resolver=input_to_json), - 'list': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLList(GraphQLString))}, - resolver=input_to_json), - 'nnList': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLNonNull(GraphQLList(GraphQLString)) - )}, - resolver=input_to_json), - 'listNN': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLList(GraphQLNonNull(GraphQLString)) - )}, - resolver=input_to_json), - 'nnListNN': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))) - )}, - resolver=input_to_json), -}) +TestType = GraphQLObjectType( + "TestType", + { + "fieldWithObjectInput": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(TestInputObject)}, + resolver=input_to_json, + ), + "fieldWithCustomObjectInput": GraphQLField( + GraphQLBoolean, + args={"input": GraphQLArgument(TestCustomInputObject)}, + resolver=lambda root, info, **args: isinstance( + args.get("input"), my_special_dict + ), + ), + "fieldWithNullableStringInput": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLString)}, + resolver=input_to_json, + ), + "fieldWithNonNullableStringInput": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLNonNull(GraphQLString))}, + resolver=input_to_json, + ), + "fieldWithDefaultArgumentValue": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLString, "Hello World")}, + resolver=input_to_json, + ), + "fieldWithNestedInputObject": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(TestNestedInputObject, "Hello World")}, + resolver=input_to_json, + ), + "list": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLList(GraphQLString))}, + resolver=input_to_json, + ), + "nnList": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLNonNull(GraphQLList(GraphQLString)))}, + resolver=input_to_json, + ), + "listNN": GraphQLField( + GraphQLString, + args={"input": GraphQLArgument(GraphQLList(GraphQLNonNull(GraphQLString)))}, + resolver=input_to_json, + ), + "nnListNN": GraphQLField( + GraphQLString, + args={ + "input": GraphQLArgument( + GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))) + ) + }, + resolver=input_to_json, + ), + }, +) schema = GraphQLSchema(TestType) -def check(doc, expected, args=None): +def check( + doc, # type: str + expected, # type: Union[Dict[str, Dict[str, None]], Dict[str, Dict[str, str]]] + args=None, # type: Any +): + # type: (...) -> None ast = parse(doc) response = execute(schema, ast, variable_values=args) if response.errors: result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] + "data": response.data, + "errors": [format_error(e) for e in response.errors], } else: - result = { - 'data': response.data - } + result = {"data": response.data} assert result == expected # Handles objects and nullability + def test_inline_executes_with_complex_input(): - doc = ''' + # type: () -> None + doc = """ { fieldWithObjectInput(input: {a: "foo", b: ["bar"], c: "baz"}) } - ''' - check(doc, { - 'data': {"fieldWithObjectInput": stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) + """ + check( + doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"a": "foo", "b": ["bar"], "c": "baz"} + ) + } + }, + ) def test_properly_parses_single_value_to_list(): - doc = ''' + # type: () -> None + doc = """ { fieldWithObjectInput(input: {a: "foo", b: "bar", c: "baz"}) } - ''' - check(doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) + """ + check( + doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"a": "foo", "b": ["bar"], "c": "baz"} + ) + } + }, + ) def test_does_not_use_incorrect_value(): - doc = ''' + # type: () -> None + doc = """ { fieldWithObjectInput(input: ["foo", "bar", "baz"]) } - ''' - check(doc, { - 'data': {'fieldWithObjectInput': None} - }) + """ + check(doc, {"data": {"fieldWithObjectInput": None}}) def test_properly_runs_parse_literal_on_complex_scalar_types(): - doc = ''' + # type: () -> None + doc = """ { fieldWithObjectInput(input: {a: "foo", d: "SerializedValue"}) } - ''' - check(doc, { - 'data': { - 'fieldWithObjectInput': '{"a": "foo", "d": "DeserializedValue"}', - } - }) + """ + check( + doc, + {"data": {"fieldWithObjectInput": '{"a": "foo", "d": "DeserializedValue"}'}}, + ) # noinspection PyMethodMayBeStatic class TestUsingVariables: - doc = ''' + doc = """ query q($input: TestInputObject) { fieldWithObjectInput(input: $input) } - ''' + """ def test_executes_with_complex_input(self): - params = {'input': {'a': 'foo', 'b': ['bar'], 'c': 'baz'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }, params) + # type: () -> None + params = {"input": {"a": "foo", "b": ["bar"], "c": "baz"}} + check( + self.doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"a": "foo", "b": ["bar"], "c": "baz"} + ) + } + }, + params, + ) def test_uses_default_value_when_not_provided(self): - with_defaults_doc = ''' + # type: () -> None + with_defaults_doc = """ query q($input: TestInputObject = {a: "foo", b: ["bar"], c: "baz"}) { fieldWithObjectInput(input: $input) } - ''' - - check(with_defaults_doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) + """ + + check( + with_defaults_doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"a": "foo", "b": ["bar"], "c": "baz"} + ) + } + }, + ) def test_properly_parses_single_value_to_list(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }, params) + # type: () -> None + params = {"input": {"a": "foo", "b": "bar", "c": "baz"}} + check( + self.doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"a": "foo", "b": ["bar"], "c": "baz"} + ) + } + }, + params, + ) def test_executes_with_complex_scalar_input(self): - params = {'input': {'c': 'foo', 'd': 'SerializedValue'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"c": "foo", "d": "DeserializedValue"})} - }, params) + # type: () -> None + params = {"input": {"c": "foo", "d": "SerializedValue"}} + check( + self.doc, + { + "data": { + "fieldWithObjectInput": stringify( + {"c": "foo", "d": "DeserializedValue"} + ) + } + }, + params, + ) def test_errors_on_null_for_nested_non_null(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': None}} + # type: () -> None + params = {"input": {"a": "foo", "b": "bar", "c": None}} with raises(GraphQLError) as excinfo: check(self.doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "c": Expected "String!", found null.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In field "c": Expected "String!", found null.'.format( + stringify(params["input"]) + ), } def test_errors_on_incorrect_type(self): - params = {'input': 'foo bar'} + # type: () -> None + params = {"input": "foo bar"} with raises(GraphQLError) as excinfo: check(self.doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'Expected "TestInputObject", found not an object.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'Expected "TestInputObject", found not an object.'.format( + stringify(params["input"]) + ), } def test_errors_on_omission_of_nested_non_null(self): - params = {'input': {'a': 'foo', 'b': 'bar'}} + # type: () -> None + params = {"input": {"a": "foo", "b": "bar"}} with raises(GraphQLError) as excinfo: check(self.doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "c": Expected "String!", found null.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In field "c": Expected "String!", found null.'.format( + stringify(params["input"]) + ), } def test_errors_on_deep_nested_errors_and_with_many_errors(self): - nested_doc = ''' + # type: () -> None + nested_doc = """ query q($input: TestNestedInputObject) { fieldWithNestedObjectInput(input: $input) } - ''' + """ - params = {'input': {'na': {'a': 'foo'}}} + params = {"input": {"na": {"a": "foo"}}} with raises(GraphQLError) as excinfo: check(nested_doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 19, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "na": In field "c": Expected "String!", found null.\n' - 'In field "nb": Expected "String!", found null.'.format(stringify(params['input'])) + "locations": [{"column": 19, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In field "na": In field "c": Expected "String!", found null.\n' + 'In field "nb": Expected "String!", found null.'.format( + stringify(params["input"]) + ), } def test_errors_on_addition_of_input_field_of_incorrect_type(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz', 'd': 'dog'}} + # type: () -> None + params = {"input": {"a": "foo", "b": "bar", "c": "baz", "d": "dog"}} with raises(GraphQLError) as excinfo: check(self.doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "d": Expected type "ComplexScalar", found "dog".'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In field "d": Expected type "ComplexScalar", found "dog".'.format( + stringify(params["input"]) + ), } def test_errors_on_addition_of_unknown_input_field(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz', 'extra': 'dog'}} + # type: () -> None + params = {"input": {"a": "foo", "b": "bar", "c": "baz", "extra": "dog"}} with raises(GraphQLError) as excinfo: check(self.doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "extra": Unknown field.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In field "extra": Unknown field.'.format(stringify(params["input"])), } def test_allows_nullable_inputs_to_be_omitted(): - doc = '{ fieldWithNullableStringInput }' - check(doc, {'data': { - 'fieldWithNullableStringInput': None - }}) + # type: () -> None + doc = "{ fieldWithNullableStringInput }" + check(doc, {"data": {"fieldWithNullableStringInput": None}}) def test_allows_nullable_inputs_to_be_omitted_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) } - ''' + """ - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }) + check(doc, {"data": {"fieldWithNullableStringInput": None}}) def test_allows_nullable_inputs_to_be_omitted_in_an_unlisted_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNullable { fieldWithNullableStringInput(input: $value) } - ''' + """ - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }) + check(doc, {"data": {"fieldWithNullableStringInput": None}}) def test_allows_nullable_inputs_to_be_set_to_null_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) } - ''' - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }, {'value': None}) + """ + check(doc, {"data": {"fieldWithNullableStringInput": None}}, {"value": None}) def test_allows_nullable_inputs_to_be_set_to_a_value_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) } - ''' + """ - check(doc, { - 'data': { - 'fieldWithNullableStringInput': '"a"' - } - }, {'value': 'a'}) + check(doc, {"data": {"fieldWithNullableStringInput": '"a"'}}, {"value": "a"}) def test_allows_nullable_inputs_to_be_set_to_a_value_directly(): - doc = ''' + # type: () -> None + doc = """ { fieldWithNullableStringInput(input: "a") } - ''' - check(doc, { - 'data': { - 'fieldWithNullableStringInput': '"a"' - } - }) + """ + check(doc, {"data": {"fieldWithNullableStringInput": '"a"'}}) def test_does_not_allow_non_nullable_inputs_to_be_omitted_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) } - ''' + """ with raises(GraphQLError) as excinfo: check(doc, {}) assert format_error(excinfo.value) == { - 'locations': [{'column': 27, 'line': 2}], - 'message': 'Variable "$value" of required type "String!" was not provided.' + "locations": [{"column": 27, "line": 2}], + "message": 'Variable "$value" of required type "String!" was not provided.', } def test_does_not_allow_non_nullable_inputs_to_be_set_to_null_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) } - ''' + """ with raises(GraphQLError) as excinfo: - check(doc, {}, {'value': None}) + check(doc, {}, {"value": None}) assert format_error(excinfo.value) == { - 'locations': [{'column': 27, 'line': 2}], - 'message': 'Variable "$value" of required type "String!" was not provided.' + "locations": [{"column": 27, "line": 2}], + "message": 'Variable "$value" of required type "String!" was not provided.', } def test_allows_non_nullable_inputs_to_be_set_to_a_value_in_a_variable(): - doc = ''' + # type: () -> None + doc = """ query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) } - ''' + """ - check(doc, { - 'data': { - 'fieldWithNonNullableStringInput': '"a"' - } - }, {'value': 'a'}) + check(doc, {"data": {"fieldWithNonNullableStringInput": '"a"'}}, {"value": "a"}) def test_allows_non_nullable_inputs_to_be_set_to_a_value_directly(): - doc = ''' + # type: () -> None + doc = """ { fieldWithNonNullableStringInput(input: "a") } - ''' + """ - check(doc, { - 'data': { - 'fieldWithNonNullableStringInput': '"a"' - } - }) + check(doc, {"data": {"fieldWithNonNullableStringInput": '"a"'}}) def test_passes_along_null_for_non_nullable_inputs_if_explcitly_set_in_the_query(): - doc = ''' + # type: () -> None + doc = """ { fieldWithNonNullableStringInput } - ''' + """ - check(doc, { - 'errors': [{ - 'message': 'Argument "input" of required type String!" was not provided.' - }], - 'data': None - }) + check( + doc, + { + "errors": [ + { + "message": 'Argument "input" of required type String!" was not provided.' + } + ], + "data": None, + }, + ) def test_uses_objectinput_container(): - doc = ''' + # type: () -> None + doc = """ { fieldWithCustomObjectInput(input: {a: "b"}) } - ''' + """ - check(doc, { - 'data': { - 'fieldWithCustomObjectInput': True - } - }) + check(doc, {"data": {"fieldWithCustomObjectInput": True}}) def test_allows_lists_to_be_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]) { list(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'list': None - } - }) + check(doc, {"data": {"list": None}}) def test_allows_lists_to_contain_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]) { list(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'list': stringify(['A']) - } - }, {'input': ['A']}) + check(doc, {"data": {"list": stringify(["A"])}}, {"input": ["A"]}) def test_allows_lists_to_contain_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]) { list(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'list': stringify(['A', None, 'B']) - } - }, {'input': ['A', None, 'B']}) + check( + doc, + {"data": {"list": stringify(["A", None, "B"])}}, + {"input": ["A", None, "B"]}, + ) def test_does_not_allow_non_null_lists_to_be_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]!) { nnList(input: $input) } - ''' + """ with raises(GraphQLError) as excinfo: - check(doc, {}, {'input': None}) + check(doc, {}, {"input": None}) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" of required type "[String]!" was not provided.' + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" of required type "[String]!" was not provided.', } def test_allows_non_null_lists_to_contain_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]!) { nnList(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'nnList': stringify(['A']) - } - }, {'input': ['A']}) + check(doc, {"data": {"nnList": stringify(["A"])}}, {"input": ["A"]}) def test_allows_non_null_lists_to_contain_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String]!) { nnList(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'nnList': stringify(['A', None, 'B']) - } - }, {'input': ['A', None, 'B']}) + check( + doc, + {"data": {"nnList": stringify(["A", None, "B"])}}, + {"input": ["A", None, "B"]}, + ) def test_allows_lists_of_non_nulls_to_be_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]) { listNN(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'listNN': None - } - }, {'input': None}) + check(doc, {"data": {"listNN": None}}, {"input": None}) def test_allows_lists_of_non_nulls_to_contain_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]) { listNN(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'listNN': stringify(['A']) - } - }, {'input': ['A']}) + check(doc, {"data": {"listNN": stringify(["A"])}}, {"input": ["A"]}) def test_does_not_allow_lists_of_non_nulls_to_contain_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]) { listNN(input: $input) } - ''' + """ - params = {'input': ['A', None, 'B']} + params = {"input": ["A", None, "B"]} with raises(GraphQLError) as excinfo: check(doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In element #1: Expected "String!", found null.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In element #1: Expected "String!", found null.'.format( + stringify(params["input"]) + ), } def test_does_not_allow_non_null_lists_of_non_nulls_to_be_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]!) { nnListNN(input: $input) } - ''' + """ with raises(GraphQLError) as excinfo: - check(doc, {}, {'input': None}) + check(doc, {}, {"input": None}) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" of required type "[String!]!" was not provided.' + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" of required type "[String!]!" was not provided.', } def test_allows_non_null_lists_of_non_nulls_to_contain_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]!) { nnListNN(input: $input) } - ''' + """ - check(doc, { - 'data': { - 'nnListNN': stringify(['A']) - } - }, {'input': ['A']}) + check(doc, {"data": {"nnListNN": stringify(["A"])}}, {"input": ["A"]}) def test_does_not_allow_non_null_lists_of_non_nulls_to_contain_null(): - doc = ''' + # type: () -> None + doc = """ query q($input: [String!]!) { nnListNN(input: $input) } - ''' + """ - params = {'input': ['A', None, 'B']} + params = {"input": ["A", None, "B"]} with raises(GraphQLError) as excinfo: check(doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In element #1: Expected "String!", found null.'.format(stringify(params['input'])) + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" got invalid value {}.\n' + 'In element #1: Expected "String!", found null.'.format( + stringify(params["input"]) + ), } def test_does_not_allow_invalid_types_to_be_used_as_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: TestType!) { fieldWithObjectInput(input: $input) } - ''' - params = {'input': {'list': ['A', 'B']}} + """ + params = {"input": {"list": ["A", "B"]}} with raises(GraphQLError) as excinfo: check(doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" expected value of type "TestType!" which cannot be used as an input type.' + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" expected value of type "TestType!" which cannot be used as an input type.', } def test_does_not_allow_unknown_types_to_be_used_as_values(): - doc = ''' + # type: () -> None + doc = """ query q($input: UnknownType!) { fieldWithObjectInput(input: $input) } - ''' - params = {'input': 'whoknows'} + """ + params = {"input": "whoknows"} with raises(GraphQLError) as excinfo: check(doc, {}, params) assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" expected value of type "UnknownType!" which cannot be used as an input type.' + "locations": [{"column": 13, "line": 2}], + "message": 'Variable "$input" expected value of type "UnknownType!" which cannot be used as an input type.', } # noinspection PyMethodMayBeStatic class TestUsesArgumentDefaultValues: - def test_when_no_argument_provided(self): - check('{ fieldWithDefaultArgumentValue }', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) + # type: () -> None + check( + "{ fieldWithDefaultArgumentValue }", + {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}}, + ) def test_when_nullable_variable_provided(self): - check(''' + # type: () -> None + check( + """ query optionalVariable($optional: String) { fieldWithDefaultArgumentValue(input: $optional) } - ''', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) + """, + {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}}, + ) def test_when_argument_provided_cannot_be_parsed(self): - check(''' + # type: () -> None + check( + """ { fieldWithDefaultArgumentValue(input: WRONG_TYPE) } - ''', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) + """, + {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}}, + ) + diff --git a/graphql/execution/tests/utils.py b/graphql/execution/tests/utils.py index 0c260810..2e9ff60c 100644 --- a/graphql/execution/tests/utils.py +++ b/graphql/execution/tests/utils.py @@ -1,9 +1,13 @@ from promise import Promise +from promise.promise import Promise +from typing import Any def resolved(value): + # type: (Any) -> Promise return Promise.fulfilled(value) def rejected(error): + # type: (Exception) -> Promise return Promise.rejected(error) diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py index a9da6bac..d282d180 100644 --- a/graphql/execution/utils.py +++ b/graphql/execution/utils.py @@ -7,11 +7,29 @@ from ..pyutils.default_ordered_dict import DefaultOrderedDict from ..type.definition import GraphQLInterfaceType, GraphQLUnionType from ..type.directives import GraphQLIncludeDirective, GraphQLSkipDirective -from ..type.introspection import (SchemaMetaFieldDef, TypeMetaFieldDef, - TypeNameMetaFieldDef) +from ..type.introspection import ( + SchemaMetaFieldDef, + TypeMetaFieldDef, + TypeNameMetaFieldDef, +) from ..utils.type_from_ast import type_from_ast from .values import get_argument_values, get_variable_values +if False: + from ..type.definition import GraphQLObjectType, GraphQLField + from ..type.schema import GraphQLSchema + from ..language.ast import ( + Document, + OperationDefinition, + SelectionSet, + Directive, + FragmentDefinition, + InlineFragment, + Field, + ) + from .base import ResolveInfo + from typing import Any, List, Dict, Optional, Union, Callable, Set + logger = logging.getLogger(__name__) @@ -21,10 +39,34 @@ class ExecutionContext(object): Namely, schema of the type system that is currently executing, and the fragments defined in the query document""" - __slots__ = 'schema', 'fragments', 'root_value', 'operation', 'variable_values', 'errors', 'context_value', \ - 'argument_values_cache', 'executor', 'middleware', 'allow_subscriptions', '_subfields_cache' + __slots__ = ( + "schema", + "fragments", + "root_value", + "operation", + "variable_values", + "errors", + "context_value", + "argument_values_cache", + "executor", + "middleware", + "allow_subscriptions", + "_subfields_cache", + ) - def __init__(self, schema, document_ast, root_value, context_value, variable_values, operation_name, executor, middleware, allow_subscriptions): + def __init__( + self, + schema, # type: GraphQLSchema + document_ast, # type: Document + root_value, # type: Union[None, Data, type] + context_value, # type: Optional[Context] + variable_values, # type: Dict[str, int] + operation_name, # type: Optional[str] + executor, # type: Any + middleware, # type: Optional[Any] + allow_subscriptions, # type: bool + ): + # type: (...) -> None """Constructs a ExecutionContext object from the arguments passed to execute, which we will pass throughout the other execution methods.""" @@ -36,9 +78,14 @@ def __init__(self, schema, document_ast, root_value, context_value, variable_val if isinstance(definition, ast.OperationDefinition): if not operation_name and operation: raise GraphQLError( - 'Must provide operation name if query contains multiple operations.') + "Must provide operation name if query contains multiple operations." + ) - if not operation_name or definition.name and definition.name.value == operation_name: + if ( + not operation_name + or definition.name + and definition.name.value == operation_name + ): operation = definition elif isinstance(definition, ast.FragmentDefinition): @@ -46,21 +93,24 @@ def __init__(self, schema, document_ast, root_value, context_value, variable_val else: raise GraphQLError( - u'GraphQL cannot execute a request containing a {}.'.format( - definition.__class__.__name__), - definition + u"GraphQL cannot execute a request containing a {}.".format( + definition.__class__.__name__ + ), + definition, ) if not operation: if operation_name: raise GraphQLError( - u'Unknown operation named "{}".'.format(operation_name)) + u'Unknown operation named "{}".'.format(operation_name) + ) else: - raise GraphQLError('Must provide an operation.') + raise GraphQLError("Must provide an operation.") variable_values = get_variable_values( - schema, operation.variable_definitions or [], variable_values) + schema, operation.variable_definitions or [], variable_values + ) self.schema = schema self.fragments = fragments @@ -76,25 +126,34 @@ def __init__(self, schema, document_ast, root_value, context_value, variable_val self._subfields_cache = {} def get_field_resolver(self, field_resolver): + # type: (Callable) -> Callable if not self.middleware: return field_resolver return self.middleware.get_field_resolver(field_resolver) def get_argument_values(self, field_def, field_ast): + # type: (GraphQLField, Field) -> Dict[str, Any] k = field_def, field_ast result = self.argument_values_cache.get(k) if not result: - result = self.argument_values_cache[k] = get_argument_values(field_def.args, field_ast.arguments, - self.variable_values) + result = self.argument_values_cache[k] = get_argument_values( + field_def.args, field_ast.arguments, self.variable_values + ) return result - def report_error(self, error, traceback=None): - exception = format_exception(type(error), error, getattr(error, 'stack', None) or traceback) - logger.error(''.join(exception)) + def report_error( + self, error, traceback=None # type: GraphQLError # type: Optional[traceback] + ): + # type: (...) -> None + exception = format_exception( + type(error), error, getattr(error, "stack", None) or traceback + ) + logger.error("".join(exception)) self.errors.append(error) def get_sub_fields(self, return_type, field_asts): + # type: (GraphQLObjectType, List[Field]) -> DefaultOrderedDict k = return_type, tuple(field_asts) if k not in self._subfields_cache: subfield_asts = DefaultOrderedDict(list) @@ -103,61 +162,70 @@ def get_sub_fields(self, return_type, field_asts): selection_set = field_ast.selection_set if selection_set: subfield_asts = collect_fields( - self, return_type, selection_set, - subfield_asts, visited_fragment_names + self, + return_type, + selection_set, + subfield_asts, + visited_fragment_names, ) self._subfields_cache[k] = subfield_asts return self._subfields_cache[k] class SubscriberExecutionContext(object): - __slots__ = 'exe_context', 'errors' + __slots__ = "exe_context", "errors" def __init__(self, exe_context): + # type: (ExecutionContext) -> None self.exe_context = exe_context self.errors = [] def reset(self): + # type: () -> None self.errors = [] def __getattr__(self, name): + # type: (str) -> Any return getattr(self.exe_context, name) def get_operation_root_type(schema, operation): + # type: (GraphQLSchema, OperationDefinition) -> GraphQLObjectType op = operation.operation - if op == 'query': + if op == "query": return schema.get_query_type() - elif op == 'mutation': + elif op == "mutation": mutation_type = schema.get_mutation_type() if not mutation_type: - raise GraphQLError( - 'Schema is not configured for mutations', - [operation] - ) + raise GraphQLError("Schema is not configured for mutations", [operation]) return mutation_type - elif op == 'subscription': + elif op == "subscription": subscription_type = schema.get_subscription_type() if not subscription_type: raise GraphQLError( - 'Schema is not configured for subscriptions', - [operation] + "Schema is not configured for subscriptions", [operation] ) return subscription_type raise GraphQLError( - 'Can only execute queries, mutations and subscriptions', - [operation] + "Can only execute queries, mutations and subscriptions", [operation] ) -def collect_fields(ctx, runtime_type, selection_set, fields, prev_fragment_names): +def collect_fields( + ctx, # type: ExecutionContext + runtime_type, # type: GraphQLObjectType + selection_set, # type: SelectionSet + fields, # type: DefaultOrderedDict + prev_fragment_names, # type: Set[str] +): + # type: (...) -> DefaultOrderedDict """ Given a selectionSet, adds all of the fields in that selection to the passed in map of fields, and returns it at the end. @@ -178,34 +246,41 @@ def collect_fields(ctx, runtime_type, selection_set, fields, prev_fragment_names elif isinstance(selection, ast.InlineFragment): if not should_include_node( - ctx, directives) or not does_fragment_condition_match( - ctx, selection, runtime_type): + ctx, directives + ) or not does_fragment_condition_match(ctx, selection, runtime_type): continue - collect_fields(ctx, runtime_type, - selection.selection_set, fields, prev_fragment_names) + collect_fields( + ctx, runtime_type, selection.selection_set, fields, prev_fragment_names + ) elif isinstance(selection, ast.FragmentSpread): frag_name = selection.name.value - if frag_name in prev_fragment_names or not should_include_node(ctx, directives): + if frag_name in prev_fragment_names or not should_include_node( + ctx, directives + ): continue prev_fragment_names.add(frag_name) fragment = ctx.fragments.get(frag_name) frag_directives = fragment.directives - if not fragment or not \ - should_include_node(ctx, frag_directives) or not \ - does_fragment_condition_match(ctx, fragment, runtime_type): + if ( + not fragment + or not should_include_node(ctx, frag_directives) + or not does_fragment_condition_match(ctx, fragment, runtime_type) + ): continue - collect_fields(ctx, runtime_type, - fragment.selection_set, fields, prev_fragment_names) + collect_fields( + ctx, runtime_type, fragment.selection_set, fields, prev_fragment_names + ) return fields def should_include_node(ctx, directives): + # type: (ExecutionContext, List[Directive]) -> bool """Determines if a field should be included based on the @include and @skip directives, where @skip has higher precidence than @include.""" # TODO: Refactor based on latest code @@ -219,11 +294,9 @@ def should_include_node(ctx, directives): if skip_ast: args = get_argument_values( - GraphQLSkipDirective.args, - skip_ast.arguments, - ctx.variable_values, + GraphQLSkipDirective.args, skip_ast.arguments, ctx.variable_values ) - if args.get('if') is True: + if args.get("if") is True: return False include_ast = None @@ -235,18 +308,21 @@ def should_include_node(ctx, directives): if include_ast: args = get_argument_values( - GraphQLIncludeDirective.args, - include_ast.arguments, - ctx.variable_values, + GraphQLIncludeDirective.args, include_ast.arguments, ctx.variable_values ) - if args.get('if') is False: + if args.get("if") is False: return False return True -def does_fragment_condition_match(ctx, fragment, type_): +def does_fragment_condition_match( + ctx, # type: ExecutionContext + fragment, # type: Union[FragmentDefinition, InlineFragment] + type_, # type: GraphQLObjectType +): + # type: (...) -> bool type_condition_ast = fragment.type_condition if not type_condition_ast: return True @@ -262,6 +338,7 @@ def does_fragment_condition_match(ctx, fragment, type_): def get_field_entry_key(node): + # type: (Field) -> str """Implements the logic to compute the key of a given field's entry""" if node.alias: return node.alias.value @@ -269,6 +346,7 @@ def get_field_entry_key(node): def default_resolve_fn(source, info, **args): + # type: (Any, ResolveInfo, **Any) -> Union[int, str] """If a resolve function is not given, then a default resolve behavior is used which takes the property of the source object of the same name as the field and returns it as the result, or if it's a function, returns the result of calling that function.""" name = info.field_name @@ -278,7 +356,12 @@ def default_resolve_fn(source, info, **args): return property -def get_field_def(schema, parent_type, field_name): +def get_field_def( + schema, # type: GraphQLSchema + parent_type, # type: GraphQLObjectType + field_name, # type: str +): + # type: (...) -> Optional[GraphQLField] """This method looks up the field on the given type defintion. It has special casing for the two introspection fields, __schema and __typename. __typename is special because it can always be @@ -286,10 +369,10 @@ def get_field_def(schema, parent_type, field_name): are allowed, like on a Union. __schema could get automatically added to the query type, but that would require mutating type definitions, which would cause issues.""" - if field_name == '__schema' and schema.get_query_type() == parent_type: + if field_name == "__schema" and schema.get_query_type() == parent_type: return SchemaMetaFieldDef - elif field_name == '__type' and schema.get_query_type() == parent_type: + elif field_name == "__type" and schema.get_query_type() == parent_type: return TypeMetaFieldDef - elif field_name == '__typename': + elif field_name == "__typename": return TypeNameMetaFieldDef return parent_type.fields.get(field_name) diff --git a/graphql/execution/values.py b/graphql/execution/values.py index 252ba1f3..289273ab 100644 --- a/graphql/execution/values.py +++ b/graphql/execution/values.py @@ -6,16 +6,33 @@ from ..error import GraphQLError from ..language import ast from ..language.printer import print_ast -from ..type import (GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, GraphQLScalarType, is_input_type) +from ..type import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, + is_input_type, +) from ..utils.is_valid_value import is_valid_value from ..utils.type_from_ast import type_from_ast from ..utils.value_from_ast import value_from_ast -__all__ = ['get_variable_values', 'get_argument_values'] +if False: + from ..language.ast import VariableDefinition, Argument + from ..type.schema import GraphQLSchema + from ..type.definition import GraphQLArgument + from typing import Any, Dict, List, Union, Dict +__all__ = ["get_variable_values", "get_argument_values"] -def get_variable_values(schema, definition_asts, inputs): + +def get_variable_values( + schema, # type: GraphQLSchema + definition_asts, # type: List[VariableDefinition] + inputs, # type: Any +): + # type: (...) -> Union[Dict[str, Dict[str, Any]], Dict[str, Dict[str, str]], Dict[str, int]] """Prepares an object map of variables of the correct type based on the provided variable definitions and arbitrary input. If the input cannot be parsed to match the variable definitions, a GraphQLError will be thrown.""" if inputs is None: @@ -30,10 +47,9 @@ def get_variable_values(schema, definition_asts, inputs): if not is_input_type(var_type): raise GraphQLError( 'Variable "${var_name}" expected value of type "{var_type}" which cannot be used as an input type.'.format( - var_name=var_name, - var_type=print_ast(def_ast.type), + var_name=var_name, var_type=print_ast(def_ast.type) ), - [def_ast] + [def_ast], ) elif value is None: if def_ast.default_value is not None: @@ -42,30 +58,34 @@ def get_variable_values(schema, definition_asts, inputs): raise GraphQLError( 'Variable "${var_name}" of required type "{var_type}" was not provided.'.format( var_name=var_name, var_type=var_type - ), [def_ast] + ), + [def_ast], ) else: errors = is_valid_value(value, var_type) if errors: - message = u'\n' + u'\n'.join(errors) + message = u"\n" + u"\n".join(errors) raise GraphQLError( 'Variable "${}" got invalid value {}.{}'.format( - var_name, - json.dumps(value, sort_keys=True), - message + var_name, json.dumps(value, sort_keys=True), message ), - [def_ast] + [def_ast], ) coerced_value = coerce_value(var_type, value) if coerced_value is None: - raise Exception('Should have reported error.') + raise Exception("Should have reported error.") values[var_name] = coerced_value return values -def get_argument_values(arg_defs, arg_asts, variables=None): +def get_argument_values( + arg_defs, # type: Union[Dict[str, GraphQLArgument], Dict] + arg_asts, # type: List[Argument] + variables=None, # type: Dict[str, int] +): + # type: (...) -> Dict[str, Any] """Prepares an object map of argument values given a list of argument definitions and list of argument AST nodes.""" if not arg_defs: @@ -85,10 +105,12 @@ def get_argument_values(arg_defs, arg_asts, variables=None): result[arg_def.out_name or name] = arg_def.default_value continue elif isinstance(arg_type, GraphQLNonNull): - raise GraphQLError('Argument "{name}" of required type {arg_type}" was not provided.'.format( - name=name, - arg_type=arg_type - ), arg_asts) + raise GraphQLError( + 'Argument "{name}" of required type {arg_type}" was not provided.'.format( + name=name, arg_type=arg_type + ), + arg_asts, + ) elif isinstance(value_ast.value, ast.Variable): variable_name = value_ast.value.name.value variable_value = variables.get(variable_name) @@ -97,21 +119,18 @@ def get_argument_values(arg_defs, arg_asts, variables=None): elif arg_def.default_value is not None: result[arg_def.out_name or name] = arg_def.default_value elif isinstance(arg_type, GraphQLNonNull): - raise GraphQLError('Argument "{name}" of required type {arg_type}" provided the variable "${variable_name}" which was not provided'.format( - name=name, - arg_type=arg_type, - variable_name=variable_name - ), arg_asts) + raise GraphQLError( + 'Argument "{name}" of required type {arg_type}" provided the variable "${variable_name}" which was not provided'.format( + name=name, arg_type=arg_type, variable_name=variable_name + ), + arg_asts, + ) continue else: value_ast = value_ast.value - value = value_from_ast( - value_ast, - arg_type, - variables - ) + value = value_from_ast(value_ast, arg_type, variables) if value is None: if arg_def.default_value is not None: value = arg_def.default_value @@ -125,6 +144,7 @@ def get_argument_values(arg_defs, arg_asts, variables=None): def coerce_value(type, value): + # type: (Any, Any) -> Union[int, str] """Given a type and any value, return a runtime value coerced to match the type.""" if isinstance(type, GraphQLNonNull): # Note: we're not checking that the result of coerceValue is @@ -137,7 +157,9 @@ def coerce_value(type, value): if isinstance(type, GraphQLList): item_type = type.of_type - if not isinstance(value, string_types) and isinstance(value, collections.Iterable): + if not isinstance(value, string_types) and isinstance( + value, collections.Iterable + ): return [coerce_value(item_type, item) for item in value] else: return [coerce_value(item_type, value)] @@ -156,7 +178,6 @@ def coerce_value(type, value): return type.create_container(obj) - assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), \ - 'Must be input type' + assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type" return type.parse_value(value) diff --git a/graphql/graphql.py b/graphql/graphql.py index 8dc4a906..be5b6119 100644 --- a/graphql/graphql.py +++ b/graphql/graphql.py @@ -3,6 +3,12 @@ from promise import promisify +if False: + from rx.core.anonymousobservable import AnonymousObservable + from typing import Any, Union, Optional + from .language.ast import Document + from .type.schema import GraphQLSchema + # This is the primary entry point function for fulfilling GraphQL operations # by parsing, validating, and executing a GraphQL document along side a # GraphQL schema. @@ -28,16 +34,26 @@ def graphql(*args, **kwargs): - return_promise = kwargs.get('return_promise', False) + # type: (*Any, **Any) -> Union[ExecutionResult, AnonymousObservable] + return_promise = kwargs.get("return_promise", False) if return_promise: return execute_graphql_as_promise(*args, **kwargs) else: return execute_graphql(*args, **kwargs) -def execute_graphql(schema, request_string='', root=None, context=None, - variables=None, operation_name=None, - middleware=None, backend=None, **execute_options): +def execute_graphql( + schema, # type: GraphQLSchema + request_string="", # type: Union[Document, str] + root=None, # type: Any + context=None, # type: Optional[Any] + variables=None, # type: Optional[Any] + operation_name=None, # type: Optional[Any] + middleware=None, # type: Optional[Any] + backend=None, # type: Optional[Any] + **execute_options # type: Any +): + # type: (...) -> Union[ExecutionResult, AnonymousObservable] try: if backend is None: backend = get_default_backend() @@ -52,10 +68,7 @@ def execute_graphql(schema, request_string='', root=None, context=None, **execute_options ) except Exception as e: - return ExecutionResult( - errors=[e], - invalid=True, - ) + return ExecutionResult(errors=[e], invalid=True) @promisify diff --git a/graphql/language/ast.py b/graphql/language/ast.py index 6fffae84..7a8deb48 100644 --- a/graphql/language/ast.py +++ b/graphql/language/ast.py @@ -1,9 +1,15 @@ +if False: + from .parser import Loc + from typing import Any, Optional, Union, List, Tuple, Iterable + # This is autogenerated code. DO NOT change this manually. # Run scripts/generate_ast.py to generate this file. class Node(object): __slots__ = () + _fields = () # type: Iterable[str] + loc = None # type: Optional[Loc] class Definition(Node): @@ -11,42 +17,64 @@ class Definition(Node): class Document(Node): - __slots__ = ('loc', 'definitions',) - _fields = ('definitions',) + __slots__ = ("loc", "definitions") + _fields = ("definitions",) def __init__(self, definitions, loc=None): + # type: (Any, Optional[Loc]) -> None self.loc = loc self.definitions = definitions def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Document) and - # self.loc == other.loc and - self.definitions == other.definitions - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Document) + and + # self.loc == other.loc and + self.definitions == other.definitions ) def __repr__(self): - return ('Document(' - 'definitions={self.definitions!r}' - ')').format(self=self) + # type: () -> str + return ("Document(" "definitions={self.definitions!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.definitions, - self.loc - ) + # type: () -> Document + return type(self)(self.definitions, self.loc) def __hash__(self): + # type: () -> int return id(self) class OperationDefinition(Definition): - __slots__ = ('loc', 'operation', 'name', 'variable_definitions', 'directives', 'selection_set',) - _fields = ('operation', 'name', 'variable_definitions', 'directives', 'selection_set',) - - def __init__(self, operation, selection_set, name=None, variable_definitions=None, directives=None, loc=None): + __slots__ = ( + "loc", + "operation", + "name", + "variable_definitions", + "directives", + "selection_set", + ) + _fields = ( + "operation", + "name", + "variable_definitions", + "directives", + "selection_set", + ) + + def __init__( + self, + operation, # type: str + selection_set, # type: SelectionSet + name=None, # type: Optional[Name] + # + variable_definitions=None, # type: Optional[List[VariableDefinition]] + directives=None, # type: Optional[List[Directive]] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.operation = operation self.name = name @@ -55,110 +83,115 @@ def __init__(self, operation, selection_set, name=None, variable_definitions=Non self.selection_set = selection_set def __eq__(self, other): - return ( - self is other or ( - isinstance(other, OperationDefinition) and - # self.loc == other.loc and - self.operation == other.operation and - self.name == other.name and - self.variable_definitions == other.variable_definitions and - self.directives == other.directives and - self.selection_set == other.selection_set - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, OperationDefinition) + and + # self.loc == other.loc and + self.operation == other.operation + and self.name == other.name + and self.variable_definitions == other.variable_definitions + and self.directives == other.directives + and self.selection_set == other.selection_set ) def __repr__(self): - return ('OperationDefinition(' - 'operation={self.operation!r}' - ', name={self.name!r}' - ', variable_definitions={self.variable_definitions!r}' - ', directives={self.directives!r}' - ', selection_set={self.selection_set!r}' - ')').format(self=self) + # type: () -> str + return ( + "OperationDefinition(" + "operation={self.operation!r}" + ", name={self.name!r}" + ", variable_definitions={self.variable_definitions!r}" + ", directives={self.directives!r}" + ", selection_set={self.selection_set!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> OperationDefinition return type(self)( self.operation, self.selection_set, self.name, self.variable_definitions, self.directives, - self.loc + self.loc, ) def __hash__(self): + # type: () -> int return id(self) class VariableDefinition(Node): - __slots__ = ('loc', 'variable', 'type', 'default_value',) - _fields = ('variable', 'type', 'default_value',) + __slots__ = ("loc", "variable", "type", "default_value") + _fields = ("variable", "type", "default_value") def __init__(self, variable, type, default_value=None, loc=None): + # type: (Variable, Any, Any, Optional[Loc]) -> None self.loc = loc self.variable = variable self.type = type self.default_value = default_value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, VariableDefinition) and - # self.loc == other.loc and - self.variable == other.variable and - self.type == other.type and - self.default_value == other.default_value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, VariableDefinition) + and + # self.loc == other.loc and + self.variable == other.variable + and self.type == other.type + and self.default_value == other.default_value ) def __repr__(self): - return ('VariableDefinition(' - 'variable={self.variable!r}' - ', type={self.type!r}' - ', default_value={self.default_value!r}' - ')').format(self=self) + # type: () -> str + return ( + "VariableDefinition(" + "variable={self.variable!r}" + ", type={self.type!r}" + ", default_value={self.default_value!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.variable, - self.type, - self.default_value, - self.loc - ) + # type: () -> VariableDefinition + return type(self)(self.variable, self.type, self.default_value, self.loc) def __hash__(self): + # type: () -> int return id(self) class SelectionSet(Node): - __slots__ = ('loc', 'selections',) - _fields = ('selections',) + __slots__ = ("loc", "selections") + _fields = ("selections",) def __init__(self, selections, loc=None): + # type: (Any, Optional[Loc]) -> None self.loc = loc self.selections = selections def __eq__(self, other): - return ( - self is other or ( - isinstance(other, SelectionSet) and - # self.loc == other.loc and - self.selections == other.selections - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, SelectionSet) + and + # self.loc == other.loc and + self.selections == other.selections ) def __repr__(self): - return ('SelectionSet(' - 'selections={self.selections!r}' - ')').format(self=self) + # type: () -> str + return ("SelectionSet(" "selections={self.selections!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.selections, - self.loc - ) + # type: () -> SelectionSet + return type(self)(self.selections, self.loc) def __hash__(self): + # type: () -> int return id(self) @@ -167,10 +200,19 @@ class Selection(Node): class Field(Selection): - __slots__ = ('loc', 'alias', 'name', 'arguments', 'directives', 'selection_set',) - _fields = ('alias', 'name', 'arguments', 'directives', 'selection_set',) - - def __init__(self, name, alias=None, arguments=None, directives=None, selection_set=None, loc=None): + __slots__ = ("loc", "alias", "name", "arguments", "directives", "selection_set") + _fields = ("alias", "name", "arguments", "directives", "selection_set") + + def __init__( + self, + name, # type: Name + alias=None, # type: Optional[Name] + arguments=None, # type: Optional[List[Argument]] + directives=None, # type: Optional[List[Directive]] + selection_set=None, # type: Optional[SelectionSet] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.alias = alias self.name = name @@ -179,158 +221,186 @@ def __init__(self, name, alias=None, arguments=None, directives=None, selection_ self.selection_set = selection_set def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Field) and - # self.loc == other.loc and - self.alias == other.alias and - self.name == other.name and - self.arguments == other.arguments and - self.directives == other.directives and - self.selection_set == other.selection_set - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Field) + and + # self.loc == other.loc and + self.alias == other.alias + and self.name == other.name + and self.arguments == other.arguments + and self.directives == other.directives + and self.selection_set == other.selection_set ) def __repr__(self): - return ('Field(' - 'alias={self.alias!r}' - ', name={self.name!r}' - ', arguments={self.arguments!r}' - ', directives={self.directives!r}' - ', selection_set={self.selection_set!r}' - ')').format(self=self) + # type: () -> str + return ( + "Field(" + "alias={self.alias!r}" + ", name={self.name!r}" + ", arguments={self.arguments!r}" + ", directives={self.directives!r}" + ", selection_set={self.selection_set!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> Field return type(self)( self.name, self.alias, self.arguments, self.directives, self.selection_set, - self.loc + self.loc, ) def __hash__(self): + # type: () -> int return id(self) class Argument(Node): - __slots__ = ('loc', 'name', 'value',) - _fields = ('name', 'value',) + __slots__ = ("loc", "name", "value") + _fields = ("name", "value") def __init__(self, name, value, loc=None): + # type: (Name, Any, Optional[Loc]) -> None self.loc = loc self.name = name self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Argument) and - # self.loc == other.loc and - self.name == other.name and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Argument) + and + # self.loc == other.loc and + self.name == other.name + and self.value == other.value ) def __repr__(self): - return ('Argument(' - 'name={self.name!r}' - ', value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("Argument(" "name={self.name!r}" ", value={self.value!r}" ")").format( + self=self + ) def __copy__(self): - return type(self)( - self.name, - self.value, - self.loc - ) + # type: () -> Argument + return type(self)(self.name, self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class FragmentSpread(Selection): - __slots__ = ('loc', 'name', 'directives',) - _fields = ('name', 'directives',) - - def __init__(self, name, directives=None, loc=None): + __slots__ = ("loc", "name", "directives") + _fields = ("name", "directives") + + def __init__( + self, + name, # type: Name + directives=None, # type: List[Directive] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.name = name self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, FragmentSpread) and - # self.loc == other.loc and - self.name == other.name and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, FragmentSpread) + and + # self.loc == other.loc and + self.name == other.name + and self.directives == other.directives ) def __repr__(self): - return ('FragmentSpread(' - 'name={self.name!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "FragmentSpread(" + "name={self.name!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.directives, - self.loc - ) + # type: () -> FragmentSpread + return type(self)(self.name, self.directives, self.loc) def __hash__(self): + # type: () -> int return id(self) class InlineFragment(Selection): - __slots__ = ('loc', 'type_condition', 'directives', 'selection_set',) - _fields = ('type_condition', 'directives', 'selection_set',) - - def __init__(self, type_condition, selection_set, directives=None, loc=None): + __slots__ = ("loc", "type_condition", "directives", "selection_set") + _fields = ("type_condition", "directives", "selection_set") + + def __init__( + self, + type_condition, # type: Optional[NamedType] + selection_set, # type: SelectionSet + directives=None, # type: Optional[List[Directive]] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.type_condition = type_condition self.directives = directives self.selection_set = selection_set def __eq__(self, other): - return ( - self is other or ( - isinstance(other, InlineFragment) and - # self.loc == other.loc and - self.type_condition == other.type_condition and - self.directives == other.directives and - self.selection_set == other.selection_set - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, InlineFragment) + and + # self.loc == other.loc and + self.type_condition == other.type_condition + and self.directives == other.directives + and self.selection_set == other.selection_set ) def __repr__(self): - return ('InlineFragment(' - 'type_condition={self.type_condition!r}' - ', directives={self.directives!r}' - ', selection_set={self.selection_set!r}' - ')').format(self=self) + # type: () -> str + return ( + "InlineFragment(" + "type_condition={self.type_condition!r}" + ", directives={self.directives!r}" + ", selection_set={self.selection_set!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> InlineFragment return type(self)( - self.type_condition, - self.selection_set, - self.directives, - self.loc + self.type_condition, self.selection_set, self.directives, self.loc ) def __hash__(self): + # type: () -> int return id(self) class FragmentDefinition(Definition): - __slots__ = ('loc', 'name', 'type_condition', 'directives', 'selection_set',) - _fields = ('name', 'type_condition', 'directives', 'selection_set',) - - def __init__(self, name, type_condition, selection_set, directives=None, loc=None): + __slots__ = ("loc", "name", "type_condition", "directives", "selection_set") + _fields = ("name", "type_condition", "directives", "selection_set") + + def __init__( + self, + name, # type: Name + type_condition, # type: Optional[NamedType] + selection_set, # type: SelectionSet + directives=None, # type: Optional[List[Directive]] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.name = name self.type_condition = type_condition @@ -338,35 +408,40 @@ def __init__(self, name, type_condition, selection_set, directives=None, loc=Non self.selection_set = selection_set def __eq__(self, other): - return ( - self is other or ( - isinstance(other, FragmentDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.type_condition == other.type_condition and - self.directives == other.directives and - self.selection_set == other.selection_set - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, FragmentDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.type_condition == other.type_condition + and self.directives == other.directives + and self.selection_set == other.selection_set ) def __repr__(self): - return ('FragmentDefinition(' - 'name={self.name!r}' - ', type_condition={self.type_condition!r}' - ', directives={self.directives!r}' - ', selection_set={self.selection_set!r}' - ')').format(self=self) + # type: () -> str + return ( + "FragmentDefinition(" + "name={self.name!r}" + ", type_condition={self.type_condition!r}" + ", directives={self.directives!r}" + ", selection_set={self.selection_set!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> FragmentDefinition return type(self)( self.name, self.type_condition, self.selection_set, self.directives, - self.loc + self.loc, ) def __hash__(self): + # type: () -> int return id(self) @@ -375,330 +450,325 @@ class Value(Node): class Variable(Value): - __slots__ = ('loc', 'name',) - _fields = ('name',) + __slots__ = ("loc", "name") + _fields = ("name",) def __init__(self, name, loc=None): + # type: (Name, Optional[Loc]) -> None self.loc = loc self.name = name def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Variable) and - # self.loc == other.loc and - self.name == other.name - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Variable) + and + # self.loc == other.loc and + self.name == other.name ) def __repr__(self): - return ('Variable(' - 'name={self.name!r}' - ')').format(self=self) + # type: () -> str + return ("Variable(" "name={self.name!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.name, - self.loc - ) + # type: () -> Variable + return type(self)(self.name, self.loc) def __hash__(self): + # type: () -> int return id(self) class IntValue(Value): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (str, Optional[Loc]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, IntValue) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, IntValue) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('IntValue(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("IntValue(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> IntValue + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class FloatValue(Value): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (str, Optional[Any]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, FloatValue) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, FloatValue) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('FloatValue(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("FloatValue(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> FloatValue + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class StringValue(Value): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (str, Optional[Loc]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, StringValue) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, StringValue) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('StringValue(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("StringValue(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> StringValue + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class BooleanValue(Value): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (bool, Optional[Loc]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, BooleanValue) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, BooleanValue) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('BooleanValue(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("BooleanValue(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> BooleanValue + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class EnumValue(Value): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (str, Optional[Loc]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, EnumValue) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, EnumValue) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('EnumValue(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("EnumValue(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> EnumValue + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class ListValue(Value): - __slots__ = ('loc', 'values',) - _fields = ('values',) + __slots__ = ("loc", "values") + _fields = ("values",) def __init__(self, values, loc=None): + # type: (Any, Optional[Loc]) -> None self.loc = loc self.values = values def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ListValue) and - # self.loc == other.loc and - self.values == other.values - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ListValue) + and + # self.loc == other.loc and + self.values == other.values ) def __repr__(self): - return ('ListValue(' - 'values={self.values!r}' - ')').format(self=self) + # type: () -> str + return ("ListValue(" "values={self.values!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.values, - self.loc - ) + # type: () -> ListValue + return type(self)(self.values, self.loc) def __hash__(self): + # type: () -> int return id(self) class ObjectValue(Value): - __slots__ = ('loc', 'fields',) - _fields = ('fields',) + __slots__ = ("loc", "fields") + _fields = ("fields",) def __init__(self, fields, loc=None): + # type: (List[ObjectField], Optional[Loc]) -> None self.loc = loc self.fields = fields def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ObjectValue) and - # self.loc == other.loc and - self.fields == other.fields - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ObjectValue) + and + # self.loc == other.loc and + self.fields == other.fields ) def __repr__(self): - return ('ObjectValue(' - 'fields={self.fields!r}' - ')').format(self=self) + # type: () -> str + return ("ObjectValue(" "fields={self.fields!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.fields, - self.loc - ) + # type: () -> ObjectValue + return type(self)(self.fields, self.loc) def __hash__(self): + # type: () -> int return id(self) class ObjectField(Node): - __slots__ = ('loc', 'name', 'value',) - _fields = ('name', 'value',) + __slots__ = ("loc", "name", "value") + _fields = ("name", "value") def __init__(self, name, value, loc=None): + # type: (Name, Any, Optional[Loc]) -> None self.loc = loc self.name = name self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ObjectField) and - # self.loc == other.loc and - self.name == other.name and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ObjectField) + and + # self.loc == other.loc and + self.name == other.name + and self.value == other.value ) def __repr__(self): - return ('ObjectField(' - 'name={self.name!r}' - ', value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ( + "ObjectField(" "name={self.name!r}" ", value={self.value!r}" ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.value, - self.loc - ) + # type: () -> ObjectField + return type(self)(self.name, self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) class Directive(Node): - __slots__ = ('loc', 'name', 'arguments',) - _fields = ('name', 'arguments',) - - def __init__(self, name, arguments=None, loc=None): + __slots__ = ("loc", "name", "arguments") + _fields = ("name", "arguments") + + def __init__( + self, + name, # type: Name + arguments=None, # type: Optional[List[Argument]] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.loc = loc self.name = name self.arguments = arguments def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Directive) and - # self.loc == other.loc and - self.name == other.name and - self.arguments == other.arguments - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Directive) + and + # self.loc == other.loc and + self.name == other.name + and self.arguments == other.arguments ) def __repr__(self): - return ('Directive(' - 'name={self.name!r}' - ', arguments={self.arguments!r}' - ')').format(self=self) + # type: () -> str + return ( + "Directive(" "name={self.name!r}" ", arguments={self.arguments!r}" ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.arguments, - self.loc - ) + # type: () -> Directive + return type(self)(self.name, self.arguments, self.loc) def __hash__(self): + # type: () -> int return id(self) @@ -707,135 +777,132 @@ class Type(Node): class NamedType(Type): - __slots__ = ('loc', 'name',) - _fields = ('name',) + __slots__ = ("loc", "name") + _fields = ("name",) def __init__(self, name, loc=None): + # type: (Name, Optional[Loc]) -> None self.loc = loc self.name = name def __eq__(self, other): - return ( - self is other or ( - isinstance(other, NamedType) and - # self.loc == other.loc and - self.name == other.name - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, NamedType) + and + # self.loc == other.loc and + self.name == other.name ) def __repr__(self): - return ('NamedType(' - 'name={self.name!r}' - ')').format(self=self) + # type: () -> str + return ("NamedType(" "name={self.name!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.name, - self.loc - ) + # type: () -> NamedType + return type(self)(self.name, self.loc) def __hash__(self): + # type: () -> int return id(self) class ListType(Type): - __slots__ = ('loc', 'type',) - _fields = ('type',) + __slots__ = ("loc", "type") + _fields = ("type",) def __init__(self, type, loc=None): + # type: (Union[NamedType, NonNullType], Optional[Loc]) -> None self.loc = loc self.type = type def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ListType) and - # self.loc == other.loc and - self.type == other.type - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ListType) + and + # self.loc == other.loc and + self.type == other.type ) def __repr__(self): - return ('ListType(' - 'type={self.type!r}' - ')').format(self=self) + # type: () -> str + return ("ListType(" "type={self.type!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.type, - self.loc - ) + # type: () -> ListType + return type(self)(self.type, self.loc) def __hash__(self): + # type: () -> int return id(self) class NonNullType(Type): - __slots__ = ('loc', 'type',) - _fields = ('type',) + __slots__ = ("loc", "type") + _fields = ("type",) def __init__(self, type, loc=None): + # type: (Union[ListType, NamedType], Optional[Loc]) -> None self.loc = loc self.type = type def __eq__(self, other): - return ( - self is other or ( - isinstance(other, NonNullType) and - # self.loc == other.loc and - self.type == other.type - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, NonNullType) + and + # self.loc == other.loc and + self.type == other.type ) def __repr__(self): - return ('NonNullType(' - 'type={self.type!r}' - ')').format(self=self) + # type: () -> str + return ("NonNullType(" "type={self.type!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.type, - self.loc - ) + # type: () -> NonNullType + return type(self)(self.type, self.loc) def __hash__(self): + # type: () -> int return id(self) class Name(Node): - __slots__ = ('loc', 'value',) - _fields = ('value',) + __slots__ = ("loc", "value") + _fields = ("value",) def __init__(self, value, loc=None): + # type: (str, Optional[Loc]) -> None self.loc = loc self.value = value def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Name) and - # self.loc == other.loc and - self.value == other.value - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, Name) + and + # self.loc == other.loc and + self.value == other.value ) def __repr__(self): - return ('Name(' - 'value={self.value!r}' - ')').format(self=self) + # type: () -> str + return ("Name(" "value={self.value!r}" ")").format(self=self) def __copy__(self): - return type(self)( - self.value, - self.loc - ) + # type: () -> Name + return type(self)(self.value, self.loc) def __hash__(self): + # type: () -> int return id(self) # Type System Definition + class TypeDefinition(Node): pass @@ -845,80 +912,95 @@ class TypeSystemDefinition(TypeDefinition): class SchemaDefinition(TypeSystemDefinition): - __slots__ = ('loc', 'directives', 'operation_types',) - _fields = ('operation_types',) - - def __init__(self, operation_types, loc=None, directives=None): + __slots__ = ("loc", "directives", "operation_types") + _fields = ("operation_types",) + + def __init__( + self, + operation_types, # type: List[OperationTypeDefinition] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.operation_types = operation_types self.loc = loc self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, SchemaDefinition) and - self.operation_types == other.operation_types and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, SchemaDefinition) + and self.operation_types == other.operation_types + and self.directives == other.directives ) def __repr__(self): - return ('SchemaDefinition(' - 'operation_types={self.operation_types!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "SchemaDefinition(" + "operation_types={self.operation_types!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.operation_types, - self.loc, - self.directives, - ) + # type: () -> SchemaDefinition + return type(self)(self.operation_types, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class OperationTypeDefinition(Node): - __slots__ = ('loc', 'operation', 'type',) - _fields = ('operation', 'type',) + __slots__ = ("loc", "operation", "type") + _fields = ("operation", "type") def __init__(self, operation, type, loc=None): + # type: (str, NamedType, Optional[Loc]) -> None self.operation = operation self.type = type self.loc = loc def __eq__(self, other): - return ( - self is other or ( - isinstance(other, OperationTypeDefinition) and - self.operation == other.operation and - self.type == other.type - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, OperationTypeDefinition) + and self.operation == other.operation + and self.type == other.type ) def __repr__(self): - return ('OperationTypeDefinition(' - 'operation={self.operation!r}' - ', type={self.type!r}' - ')').format(self=self) + # type: () -> str + return ( + "OperationTypeDefinition(" + "operation={self.operation!r}" + ", type={self.type!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.operation, - self.type, - self.loc - ) + # type: () -> OperationTypeDefinition + return type(self)(self.operation, self.type, self.loc) def __hash__(self): + # type: () -> int return id(self) class ObjectTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'interfaces', 'directives', 'fields',) - _fields = ('name', 'interfaces', 'fields',) - - def __init__(self, name, fields, interfaces=None, loc=None, directives=None): + __slots__ = ("loc", "name", "interfaces", "directives", "fields") + _fields = ("name", "interfaces", "fields") + + def __init__( + self, + name, # type: Name + fields, # type: List[FieldDefinition] + interfaces=None, # type: Optional[List[NamedType]] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.interfaces = interfaces @@ -926,43 +1008,52 @@ def __init__(self, name, fields, interfaces=None, loc=None, directives=None): self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ObjectTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.interfaces == other.interfaces and - self.fields == other.fields and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ObjectTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.interfaces == other.interfaces + and self.fields == other.fields + and self.directives == other.directives ) def __repr__(self): - return ('ObjectTypeDefinition(' - 'name={self.name!r}' - ', interfaces={self.interfaces!r}' - ', fields={self.fields!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "ObjectTypeDefinition(" + "name={self.name!r}" + ", interfaces={self.interfaces!r}" + ", fields={self.fields!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> ObjectTypeDefinition return type(self)( - self.name, - self.fields, - self.interfaces, - self.loc, - self.directives, + self.name, self.fields, self.interfaces, self.loc, self.directives ) def __hash__(self): + # type: () -> int return id(self) class FieldDefinition(Node): - __slots__ = ('loc', 'name', 'arguments', 'type', 'directives',) - _fields = ('name', 'arguments', 'type',) - - def __init__(self, name, arguments, type, loc=None, directives=None): + __slots__ = ("loc", "name", "arguments", "type", "directives") + _fields = ("name", "arguments", "type") + + def __init__( + self, + name, # type: Name + arguments, # type: List[InputValueDefinition] + type, # type: Union[NamedType, NonNullType, ListType] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List] + ): + # type: (...) -> None self.loc = loc self.name = name self.arguments = arguments @@ -970,43 +1061,51 @@ def __init__(self, name, arguments, type, loc=None, directives=None): self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, FieldDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.arguments == other.arguments and - self.type == other.type and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, FieldDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.arguments == other.arguments + and self.type == other.type + and self.directives == other.directives ) def __repr__(self): - return ('FieldDefinition(' - 'name={self.name!r}' - ', arguments={self.arguments!r}' - ', type={self.type!r}' - ')').format(self=self) + # type: () -> str + return ( + "FieldDefinition(" + "name={self.name!r}" + ", arguments={self.arguments!r}" + ", type={self.type!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> FieldDefinition return type(self)( - self.name, - self.arguments, - self.type, - self.loc, - self.directives, + self.name, self.arguments, self.type, self.loc, self.directives ) def __hash__(self): + # type: () -> int return id(self) class InputValueDefinition(Node): - __slots__ = ('loc', 'name', 'type', 'default_value', 'directives') - _fields = ('name', 'type', 'default_value',) - - def __init__(self, name, type, default_value=None, loc=None, - directives=None): + __slots__ = ("loc", "name", "type", "default_value", "directives") + _fields = ("name", "type", "default_value") + + def __init__( + self, + name, # type: Name + type, # type: Union[NamedType, NonNullType, ListType] + default_value=None, # type: Any + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List] + ): + # type: (...) -> None self.loc = loc self.name = name self.type = type @@ -1014,336 +1113,388 @@ def __init__(self, name, type, default_value=None, loc=None, self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, InputValueDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.type == other.type and - self.default_value == other.default_value and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, InputValueDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.type == other.type + and self.default_value == other.default_value + and self.directives == other.directives ) def __repr__(self): - return ('InputValueDefinition(' - 'name={self.name!r}' - ', type={self.type!r}' - ', default_value={self.default_value!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "InputValueDefinition(" + "name={self.name!r}" + ", type={self.type!r}" + ", default_value={self.default_value!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): + # type: () -> InputValueDefinition return type(self)( - self.name, - self.type, - self.default_value, - self.loc, - self.directives, + self.name, self.type, self.default_value, self.loc, self.directives ) def __hash__(self): + # type: () -> int return id(self) class InterfaceTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'fields', 'directives',) - _fields = ('name', 'fields',) - - def __init__(self, name, fields, loc=None, directives=None): + __slots__ = ("loc", "name", "fields", "directives") + _fields = ("name", "fields") + + def __init__( + self, + name, # type: Name + fields, # type: List[FieldDefinition] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.fields = fields self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, InterfaceTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.fields == other.fields and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, InterfaceTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.fields == other.fields + and self.directives == other.directives ) def __repr__(self): - return ('InterfaceTypeDefinition(' - 'name={self.name!r}' - ', fields={self.fields!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "InterfaceTypeDefinition(" + "name={self.name!r}" + ", fields={self.fields!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.fields, - self.loc, - self.directives, - ) + # type: () -> InterfaceTypeDefinition + return type(self)(self.name, self.fields, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class UnionTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'types', 'directives',) - _fields = ('name', 'types',) - - def __init__(self, name, types, loc=None, directives=None): + __slots__ = ("loc", "name", "types", "directives") + _fields = ("name", "types") + + def __init__( + self, + name, # type: Name + types, # type: List[NamedType] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.types = types self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, UnionTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.types == other.types and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, UnionTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.types == other.types + and self.directives == other.directives ) def __repr__(self): - return ('UnionTypeDefinition(' - 'name={self.name!r}' - ', types={self.types!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "UnionTypeDefinition(" + "name={self.name!r}" + ", types={self.types!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.types, - self.loc, - self.directives, - ) + # type: () -> UnionTypeDefinition + return type(self)(self.name, self.types, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class ScalarTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'directives',) - _fields = ('name',) - - def __init__(self, name, loc=None, directives=None): + __slots__ = ("loc", "name", "directives") + _fields = ("name",) + + def __init__( + self, + name, # type: Name + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, ScalarTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, ScalarTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.directives == other.directives ) def __repr__(self): - return ('ScalarTypeDefinition(' - 'name={self.name!r}' - 'directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "ScalarTypeDefinition(" + "name={self.name!r}" + "directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.loc, - self.directives - ) + # type: () -> ScalarTypeDefinition + return type(self)(self.name, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class EnumTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'values', 'directives',) - _fields = ('name', 'values',) - - def __init__(self, name, values, loc=None, directives=None): + __slots__ = ("loc", "name", "values", "directives") + _fields = ("name", "values") + + def __init__( + self, + name, # type: Name + values, # type: List[EnumValueDefinition] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.values = values self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, EnumTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.values == other.values and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, EnumTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.values == other.values + and self.directives == other.directives ) def __repr__(self): - return ('EnumTypeDefinition(' - 'name={self.name!r}' - ', values={self.values!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "EnumTypeDefinition(" + "name={self.name!r}" + ", values={self.values!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.values, - self.loc, - self.directives, - ) + # type: () -> EnumTypeDefinition + return type(self)(self.name, self.values, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class EnumValueDefinition(Node): - __slots__ = ('loc', 'name', 'directives',) - _fields = ('name',) - - def __init__(self, name, loc=None, directives=None): + __slots__ = ("loc", "name", "directives") + _fields = ("name",) + + def __init__( + self, + name, # type: Name + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, EnumValueDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, EnumValueDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.directives == other.directives ) def __repr__(self): - return ('EnumValueDefinition(' - 'name={self.name!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "EnumValueDefinition(" + "name={self.name!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.loc, - self.directives, - ) + # type: () -> EnumValueDefinition + return type(self)(self.name, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class InputObjectTypeDefinition(TypeDefinition): - __slots__ = ('loc', 'name', 'fields', 'directives',) - _fields = ('name', 'fields',) - - def __init__(self, name, fields, loc=None, directives=None): + __slots__ = ("loc", "name", "fields", "directives") + _fields = ("name", "fields") + + def __init__( + self, + name, # type: Name + fields, # type: List[InputValueDefinition] + loc=None, # type: Optional[Loc] + directives=None, # type: Optional[List[Directive]] + ): + # type: (...) -> None self.loc = loc self.name = name self.fields = fields self.directives = directives def __eq__(self, other): - return ( - self is other or ( - isinstance(other, InputObjectTypeDefinition) and - # self.loc == other.loc and - self.name == other.name and - self.fields == other.fields and - self.directives == other.directives - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, InputObjectTypeDefinition) + and + # self.loc == other.loc and + self.name == other.name + and self.fields == other.fields + and self.directives == other.directives ) def __repr__(self): - return ('InputObjectTypeDefinition(' - 'name={self.name!r}' - ', fields={self.fields!r}' - ', directives={self.directives!r}' - ')').format(self=self) + # type: () -> str + return ( + "InputObjectTypeDefinition(" + "name={self.name!r}" + ", fields={self.fields!r}" + ", directives={self.directives!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.fields, - self.loc, - self.directives, - ) + # type: () -> InputObjectTypeDefinition + return type(self)(self.name, self.fields, self.loc, self.directives) def __hash__(self): + # type: () -> int return id(self) class TypeExtensionDefinition(TypeSystemDefinition): - __slots__ = ('loc', 'definition',) - _fields = ('definition',) + __slots__ = ("loc", "definition") + _fields = ("definition",) def __init__(self, definition, loc=None): + # type: (ObjectTypeDefinition, Optional[Loc]) -> None self.loc = loc self.definition = definition def __eq__(self, other): - return ( - self is other or ( - isinstance(other, TypeExtensionDefinition) and - # self.loc == other.loc and - self.definition == other.definition - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, TypeExtensionDefinition) + and + # self.loc == other.loc and + self.definition == other.definition ) def __repr__(self): - return ('TypeExtensionDefinition(' - 'definition={self.definition!r}' - ')').format(self=self) + # type: () -> str + return ("TypeExtensionDefinition(" "definition={self.definition!r}" ")").format( + self=self + ) def __copy__(self): - return type(self)( - self.definition, - self.loc - ) + # type: () -> TypeExtensionDefinition + return type(self)(self.definition, self.loc) def __hash__(self): + # type: () -> int return id(self) class DirectiveDefinition(TypeSystemDefinition): - __slots__ = ('loc', 'name', 'arguments', 'locations') - _fields = ('name', 'locations') - - def __init__(self, name, locations, arguments=None, loc=None): + __slots__ = ("loc", "name", "arguments", "locations") + _fields = ("name", "locations") + + def __init__( + self, + name, # type: Name + locations, # type: List[Name] + arguments=None, # type: Optional[List[InputValueDefinition]] + loc=None, # type: Optional[Loc] + ): + # type: (...) -> None self.name = name self.locations = locations self.loc = loc self.arguments = arguments def __eq__(self, other): - return ( - self is other or ( - isinstance(other, DirectiveDefinition) and - self.name == other.name and - self.locations == other.locations and - # self.loc == other.loc and - self.arguments == other.arguments - ) + # type: (Any) -> bool + return self is other or ( + isinstance(other, DirectiveDefinition) + and self.name == other.name + and self.locations == other.locations + and + # self.loc == other.loc and + self.arguments == other.arguments ) def __repr__(self): - return ('DirectiveDefinition(' - 'name={self.name!r}, ' - 'locations={self.locations!r}' - ')').format(self=self) + # type: () -> str + return ( + "DirectiveDefinition(" + "name={self.name!r}, " + "locations={self.locations!r}" + ")" + ).format(self=self) def __copy__(self): - return type(self)( - self.name, - self.locations, - self.arguments, - self.loc, - ) + # type: () -> DirectiveDefinition + return type(self)(self.name, self.locations, self.arguments, self.loc) def __hash__(self): + # type: () -> int return id(self) + diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py index 711525ef..dbc11401 100644 --- a/graphql/language/lexer.py +++ b/graphql/language/lexer.py @@ -4,42 +4,49 @@ from ..error import GraphQLSyntaxError -__all__ = ['Token', 'Lexer', 'TokenKind', - 'get_token_desc', 'get_token_kind_desc'] +if False: + from typing import Optional + from .source import Source + +__all__ = ["Token", "Lexer", "TokenKind", "get_token_desc", "get_token_kind_desc"] class Token(object): - __slots__ = 'kind', 'start', 'end', 'value' + __slots__ = "kind", "start", "end", "value" def __init__(self, kind, start, end, value=None): + # type: (int, int, int, Optional[str]) -> None self.kind = kind self.start = start self.end = end self.value = value def __repr__(self): - return u''.format( - get_token_kind_desc(self.kind), - self.start, - self.end, - repr(self.value) + # type: () -> str + return u"".format( + get_token_kind_desc(self.kind), self.start, self.end, repr(self.value) ) def __eq__(self, other): - return (self.kind == other.kind and - self.start == other.start and - self.end == other.end and - self.value == other.value) + # type: (Token) -> bool + return ( + self.kind == other.kind + and self.start == other.start + and self.end == other.end + and self.value == other.value + ) class Lexer(object): - __slots__ = 'source', 'prev_position' + __slots__ = "source", "prev_position" def __init__(self, source): + # type: (Source) -> None self.source = source self.prev_position = 0 def next_token(self, reset_position=None): + # type: (Optional[int]) -> Token if reset_position is None: reset_position = self.prev_position token = read_token(self.source, reset_position) @@ -70,43 +77,43 @@ class TokenKind(object): def get_token_desc(token): + # type: (Token) -> str if token.value: - return u'{} "{}"'.format( - get_token_kind_desc(token.kind), - token.value - ) + return u'{} "{}"'.format(get_token_kind_desc(token.kind), token.value) else: return get_token_kind_desc(token.kind) def get_token_kind_desc(kind): + # type: (int) -> str return TOKEN_DESCRIPTION[kind] TOKEN_DESCRIPTION = { - TokenKind.EOF: 'EOF', - TokenKind.BANG: '!', - TokenKind.DOLLAR: '$', - TokenKind.PAREN_L: '(', - TokenKind.PAREN_R: ')', - TokenKind.SPREAD: '...', - TokenKind.COLON: ':', - TokenKind.EQUALS: '=', - TokenKind.AT: '@', - TokenKind.BRACKET_L: '[', - TokenKind.BRACKET_R: ']', - TokenKind.BRACE_L: '{', - TokenKind.PIPE: '|', - TokenKind.BRACE_R: '}', - TokenKind.NAME: 'Name', - TokenKind.VARIABLE: 'Variable', - TokenKind.INT: 'Int', - TokenKind.FLOAT: 'Float', - TokenKind.STRING: 'String', + TokenKind.EOF: "EOF", + TokenKind.BANG: "!", + TokenKind.DOLLAR: "$", + TokenKind.PAREN_L: "(", + TokenKind.PAREN_R: ")", + TokenKind.SPREAD: "...", + TokenKind.COLON: ":", + TokenKind.EQUALS: "=", + TokenKind.AT: "@", + TokenKind.BRACKET_L: "[", + TokenKind.BRACKET_R: "]", + TokenKind.BRACE_L: "{", + TokenKind.PIPE: "|", + TokenKind.BRACE_R: "}", + TokenKind.NAME: "Name", + TokenKind.VARIABLE: "Variable", + TokenKind.INT: "Int", + TokenKind.FLOAT: "Float", + TokenKind.STRING: "String", } def char_code_at(s, pos): + # type: (str, int) -> Optional[int] if 0 <= pos < len(s): return ord(s[pos]) @@ -114,24 +121,25 @@ def char_code_at(s, pos): PUNCT_CODE_TO_KIND = { - ord('!'): TokenKind.BANG, - ord('$'): TokenKind.DOLLAR, - ord('('): TokenKind.PAREN_L, - ord(')'): TokenKind.PAREN_R, - ord(':'): TokenKind.COLON, - ord('='): TokenKind.EQUALS, - ord('@'): TokenKind.AT, - ord('['): TokenKind.BRACKET_L, - ord(']'): TokenKind.BRACKET_R, - ord('{'): TokenKind.BRACE_L, - ord('|'): TokenKind.PIPE, - ord('}'): TokenKind.BRACE_R, + ord("!"): TokenKind.BANG, + ord("$"): TokenKind.DOLLAR, + ord("("): TokenKind.PAREN_L, + ord(")"): TokenKind.PAREN_R, + ord(":"): TokenKind.COLON, + ord("="): TokenKind.EQUALS, + ord("@"): TokenKind.AT, + ord("["): TokenKind.BRACKET_L, + ord("]"): TokenKind.BRACKET_R, + ord("{"): TokenKind.BRACE_L, + ord("|"): TokenKind.PIPE, + ord("}"): TokenKind.BRACE_R, } def print_char_code(code): + # type: (Optional[int]) -> str if code is None: - return '' + return "" if code < 0x007F: return json.dumps(unichr(code)) @@ -140,6 +148,7 @@ def print_char_code(code): def read_token(source, from_position): + # type: (Source, int) -> Token """Gets the next token from the source starting at the given position. This skips over whitespace and comments until it finds the next lexable @@ -157,8 +166,7 @@ def read_token(source, from_position): if code < 0x0020 and code not in (0x0009, 0x000A, 0x000D): raise GraphQLSyntaxError( - source, position, - u'Invalid character {}.'.format(print_char_code(code)) + source, position, u"Invalid character {}.".format(print_char_code(code)) ) kind = PUNCT_CODE_TO_KIND.get(code) @@ -180,25 +188,28 @@ def read_token(source, from_position): return read_string(source, position) raise GraphQLSyntaxError( - source, position, - u'Unexpected character {}.'.format(print_char_code(code))) + source, position, u"Unexpected character {}.".format(print_char_code(code)) + ) -ignored_whitespace_characters = frozenset([ - # BOM - 0xFEFF, - # White Space - 0x0009, # tab - 0x0020, # space - # Line Terminator - 0x000A, # new line - 0x000D, # carriage return - # Comma - 0x002C -]) +ignored_whitespace_characters = frozenset( + [ + # BOM + 0xFEFF, + # White Space + 0x0009, # tab + 0x0020, # space + # Line Terminator + 0x000A, # new line + 0x000D, # carriage return + # Comma + 0x002C, + ] +) def position_after_whitespace(body, start_position): + # type: (str, int) -> int """Reads from body starting at start_position until it finds a non-whitespace or commented character, then returns the position of that character for lexing.""" @@ -213,7 +224,11 @@ def position_after_whitespace(body, start_position): position += 1 while position < body_length: code = char_code_at(body, position) - if not (code is not None and (code > 0x001F or code == 0x0009) and code not in (0x000A, 0x000D)): + if not ( + code is not None + and (code > 0x001F or code == 0x0009) + and code not in (0x000A, 0x000D) + ): break position += 1 @@ -223,6 +238,7 @@ def position_after_whitespace(body, start_position): def read_number(source, start, first_code): + # type: (Source, int, int) -> Token """Reads a number token from the source file, either a float or an int depending on whether a decimal point appears. @@ -245,7 +261,9 @@ def read_number(source, start, first_code): raise GraphQLSyntaxError( source, position, - u'Invalid number, unexpected digit after 0: {}.'.format(print_char_code(code)) + u"Invalid number, unexpected digit after 0: {}.".format( + print_char_code(code) + ), ) else: position = read_digits(source, position, code) @@ -273,11 +291,12 @@ def read_number(source, start, first_code): TokenKind.FLOAT if is_float else TokenKind.INT, start, position, - body[start:position] + body[start:position], ) def read_digits(source, start, first_code): + # type: (Source, int, Optional[int]) -> int body = source.body position = start code = first_code @@ -295,23 +314,24 @@ def read_digits(source, start, first_code): raise GraphQLSyntaxError( source, position, - u'Invalid number, expected digit but got: {}.'.format(print_char_code(code)) + u"Invalid number, expected digit but got: {}.".format(print_char_code(code)), ) ESCAPED_CHAR_CODES = { 34: '"', - 47: '/', - 92: '\\', - 98: '\b', - 102: '\f', - 110: '\n', - 114: '\r', - 116: '\t', + 47: "/", + 92: "\\", + 98: "\b", + 102: "\f", + 110: "\n", + 114: "\r", + 116: "\t", } def read_string(source, start): + # type: (Source, int) -> Token """Reads a string token from the source file. "([^"\\\u000A\u000D\u2028\u2029]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*" @@ -328,12 +348,14 @@ def read_string(source, start): while position < body_length: code = char_code_at(body, position) if not ( - code is not None and - code not in ( + code is not None + and code + not in ( # LineTerminator - 0x000A, 0x000D, + 0x000A, + 0x000D, # Quote - 34 + 34, ) ): break @@ -342,12 +364,12 @@ def read_string(source, start): raise GraphQLSyntaxError( source, position, - u'Invalid character within String: {}.'.format(print_char_code(code)) + u"Invalid character within String: {}.".format(print_char_code(code)), ) position += 1 if code == 92: # \ - append(body[chunk_start:position - 1]) + append(body[chunk_start : position - 1]) code = char_code_at(body, position) escaped = ESCAPED_CHAR_CODES.get(code) @@ -364,29 +386,34 @@ def read_string(source, start): if char_code < 0: raise GraphQLSyntaxError( - source, position, - u'Invalid character escape sequence: \\u{}.'.format(body[position + 1: position + 5]) + source, + position, + u"Invalid character escape sequence: \\u{}.".format( + body[position + 1 : position + 5] + ), ) append(unichr(char_code)) position += 4 else: raise GraphQLSyntaxError( - source, position, - u'Invalid character escape sequence: \\{}.'.format(unichr(code)) + source, + position, + u"Invalid character escape sequence: \\{}.".format(unichr(code)), ) position += 1 chunk_start = position if code != 34: # Quote (") - raise GraphQLSyntaxError(source, position, 'Unterminated string') + raise GraphQLSyntaxError(source, position, "Unterminated string") append(body[chunk_start:position]) - return Token(TokenKind.STRING, start, position + 1, u''.join(value)) + return Token(TokenKind.STRING, start, position + 1, u"".join(value)) def uni_char_code(a, b, c, d): + # type: (int, int, int, int) -> int """Converts four hexidecimal chars to the integer that the string represents. For example, uniCharCode('0','0','0','f') will return 15, and uniCharCode('0','0','f','f') returns 255. @@ -396,11 +423,11 @@ def uni_char_code(a, b, c, d): This is implemented by noting that char2hex() returns -1 on error, which means the result of ORing the char2hex() will also be negative. """ - return (char2hex(a) << 12 | char2hex(b) << 8 | - char2hex(c) << 4 | char2hex(d)) + return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d) def char2hex(a): + # type: (int) -> int """Converts a hex character to its integer value. '0' becomes 0, '9' becomes 9 'A' becomes 10, 'F' becomes 15 @@ -417,6 +444,7 @@ def char2hex(a): def read_name(source, position): + # type: (Source, int) -> Token """Reads an alphanumeric + underscore name from the source. [_A-Za-z][_0-9A-Za-z]*""" @@ -426,12 +454,15 @@ def read_name(source, position): while end != body_length: code = char_code_at(body, end) - if not (code is not None and ( - code == 95 or # _ - 48 <= code <= 57 or # 0-9 - 65 <= code <= 90 or # A-Z - 97 <= code <= 122 # a-z - )): + if not ( + code is not None + and ( + code == 95 + or 48 <= code <= 57 # _ + or 65 <= code <= 90 # 0-9 + or 97 <= code <= 122 # A-Z # a-z + ) + ): break end += 1 diff --git a/graphql/language/location.py b/graphql/language/location.py index 8a4f8192..973743b0 100644 --- a/graphql/language/location.py +++ b/graphql/language/location.py @@ -1,25 +1,33 @@ -__all__ = ['get_location', 'SourceLocation'] +if False: + from .source import Source + from typing import Any + +__all__ = ["get_location", "SourceLocation"] class SourceLocation(object): - __slots__ = 'line', 'column' + __slots__ = "line", "column" def __init__(self, line, column): + # type: (int, int) -> None self.line = line self.column = column def __repr__(self): - return 'SourceLocation(line={}, column={})'.format(self.line, self.column) + # type: () -> str + return "SourceLocation(line={}, column={})".format(self.line, self.column) def __eq__(self, other): + # type: (Any) -> bool return ( - isinstance(other, SourceLocation) and - self.line == other.line and - self.column == other.column + isinstance(other, SourceLocation) + and self.line == other.line + and self.column == other.column ) def get_location(source, position): + # type: (Source, int) -> SourceLocation lines = source.body[:position].splitlines() if lines: line = len(lines) diff --git a/graphql/language/parser.py b/graphql/language/parser.py index 21adac91..d44e9313 100644 --- a/graphql/language/parser.py +++ b/graphql/language/parser.py @@ -5,24 +5,68 @@ from .lexer import Lexer, TokenKind, get_token_desc, get_token_kind_desc from .source import Source -__all__ = ['parse'] +if False: + from typing import Dict, Union, Any, Optional, Callable, List + from ..error.syntax_error import GraphQLSyntaxError + from .source import Source + from .lexer import Token + from .ast import ( + Document, + Name, + OperationDefinition, + VariableDefinition, + Variable, + SelectionSet, + Field, + FragmentSpread, + Argument, + InlineFragment, + FragmentDefinition, + IntValue, + StringValue, + BooleanValue, + ObjectValue, + ListValue, + ObjectField, + Directive, + NamedType, + NonNullType, + ListType, + SchemaDefinition, + OperationTypeDefinition, + ScalarTypeDefinition, + ObjectTypeDefinition, + FieldDefinition, + InputValueDefinition, + InterfaceTypeDefinition, + UnionTypeDefinition, + EnumTypeDefinition, + EnumValueDefinition, + InputObjectTypeDefinition, + TypeExtensionDefinition, + DirectiveDefinition, + ) + +__all__ = ["parse"] def parse(source, **kwargs): + # type: (Union[Source, str], **Any) -> Document """Given a GraphQL source, parses it into a Document.""" - options = {'no_location': False, 'no_source': False} + options = {"no_location": False, "no_source": False} options.update(kwargs) - source_obj = source if isinstance(source, string_types): - source_obj = Source(source) + source_obj = Source(source) # type: Source + else: + source_obj = source # type: ignore parser = Parser(source_obj, options) return parse_document(parser) def parse_value(source, **kwargs): - options = {'no_location': False, 'no_source': False} + options = {"no_location": False, "no_source": False} options.update(kwargs) source_obj = source @@ -34,9 +78,10 @@ def parse_value(source, **kwargs): class Parser(object): - __slots__ = 'lexer', 'source', 'options', 'prev_end', 'token' + __slots__ = "lexer", "source", "options", "prev_end", "token" def __init__(self, source, options): + # type: (Source, Dict[str, bool]) -> None self.lexer = Lexer(source) self.source = source self.options = options @@ -45,39 +90,43 @@ def __init__(self, source, options): class Loc(object): - __slots__ = 'start', 'end', 'source' + __slots__ = "start", "end", "source" def __init__(self, start, end, source=None): + # type: (int, int, Union[Source, str]) -> None self.start = start self.end = end self.source = source def __repr__(self): - source = ' source={}'.format(self.source) if self.source else '' - return ''.format(self.start, self.end, source) + # type: () -> str + source = " source={}".format(self.source) if self.source else "" + return "".format(self.start, self.end, source) def __eq__(self, other): return ( - isinstance(other, Loc) and - self.start == other.start and - self.end == other.end and - self.source == other.source + isinstance(other, Loc) + and self.start == other.start + and self.end == other.end + and self.source == other.source ) def loc(parser, start): + # type: (Parser, int) -> Optional[Loc] """Returns a location object, used to identify the place in the source that created a given parsed object.""" - if parser.options['no_location']: + if parser.options["no_location"]: return None - if parser.options['no_source']: + if parser.options["no_source"]: return Loc(start, parser.prev_end) return Loc(start, parser.prev_end, parser.source) def advance(parser): + # type: (Parser) -> None """Moves the internal parser object to the next lexed token.""" prev_end = parser.token.end parser.prev_end = prev_end @@ -85,11 +134,13 @@ def advance(parser): def peek(parser, kind): + # type: (Parser, int) -> bool """Determines if the next token is of a given kind""" return parser.token.kind == kind def skip(parser, kind): + # type: (Parser, int) -> bool """If the next token is of the given kind, return true after advancing the parser. Otherwise, do not change the parser state and throw an error.""" @@ -101,6 +152,7 @@ def skip(parser, kind): def expect(parser, kind): + # type: (Parser, int) -> Token """If the next token is of the given kind, return that token after advancing the parser. Otherwise, do not change the parser state and return False.""" @@ -112,14 +164,14 @@ def expect(parser, kind): raise GraphQLSyntaxError( parser.source, token.start, - u'Expected {}, found {}'.format( - get_token_kind_desc(kind), - get_token_desc(token) - ) + u"Expected {}, found {}".format( + get_token_kind_desc(kind), get_token_desc(token) + ), ) def expect_keyword(parser, value): + # type: (Parser, str) -> Token """If the next token is a keyword with the given value, return that token after advancing the parser. Otherwise, do not change the parser state and return False.""" @@ -131,22 +183,22 @@ def expect_keyword(parser, value): raise GraphQLSyntaxError( parser.source, token.start, - u'Expected "{}", found {}'.format(value, get_token_desc(token)) + u'Expected "{}", found {}'.format(value, get_token_desc(token)), ) def unexpected(parser, at_token=None): + # type: (Parser, Optional[Any]) -> GraphQLSyntaxError """Helper function for creating an error when an unexpected lexed token is encountered.""" token = at_token or parser.token return GraphQLSyntaxError( - parser.source, - token.start, - u'Unexpected {}'.format(get_token_desc(token)) + parser.source, token.start, u"Unexpected {}".format(get_token_desc(token)) ) def any(parser, open_kind, parse_fn, close_kind): + # type: (Parser, int, Callable, int) -> Any """Returns a possibly empty list of parse nodes, determined by the parse_fn. This list begins with a lex token of openKind and ends with a lex token of closeKind. Advances the parser @@ -160,6 +212,7 @@ def any(parser, open_kind, parse_fn, close_kind): def many(parser, open_kind, parse_fn, close_kind): + # type: (Parser, int, Callable, int) -> Any """Returns a non-empty list of parse nodes, determined by the parse_fn. This list begins with a lex token of openKind and ends with a lex token of closeKind. Advances the parser @@ -173,17 +226,17 @@ def many(parser, open_kind, parse_fn, close_kind): def parse_name(parser): + # type: (Parser) -> Name """Converts a name lex token into a name parse node.""" token = expect(parser, TokenKind.NAME) - return ast.Name( - value=token.value, - loc=loc(parser, token.start) - ) + return ast.Name(value=token.value, loc=loc(parser, token.start)) # type: ignore # Implements the parsing rules in the Document section. + def parse_document(parser): + # type: (Parser) -> Document start = parser.token.start definitions = [] while True: @@ -192,24 +245,32 @@ def parse_document(parser): if skip(parser, TokenKind.EOF): break - return ast.Document( - definitions=definitions, - loc=loc(parser, start) - ) + return ast.Document(definitions=definitions, loc=loc(parser, start)) def parse_definition(parser): + # type: (Parser) -> Any if peek(parser, TokenKind.BRACE_L): return parse_operation_definition(parser) if peek(parser, TokenKind.NAME): name = parser.token.value - if name in ('query', 'mutation', 'subscription'): + if name in ("query", "mutation", "subscription"): return parse_operation_definition(parser) - elif name == 'fragment': + elif name == "fragment": return parse_fragment_definition(parser) - elif name in ('schema', 'scalar', 'type', 'interface', 'union', 'enum', 'input', 'extend', 'directive'): + elif name in ( + "schema", + "scalar", + "type", + "interface", + "union", + "enum", + "input", + "extend", + "directive", + ): return parse_type_system_definition(parser) raise unexpected(parser) @@ -217,15 +278,16 @@ def parse_definition(parser): # Implements the parsing rules in the Operations section. def parse_operation_definition(parser): + # type: (Parser) -> OperationDefinition start = parser.token.start if peek(parser, TokenKind.BRACE_L): return ast.OperationDefinition( - operation='query', + operation="query", name=None, variable_definitions=None, directives=[], selection_set=parse_selection_set(parser), - loc=loc(parser, start) + loc=loc(parser, start), ) operation = parse_operation_type(parser) @@ -240,65 +302,67 @@ def parse_operation_definition(parser): variable_definitions=parse_variable_definitions(parser), directives=parse_directives(parser), selection_set=parse_selection_set(parser), - loc=loc(parser, start) + loc=loc(parser, start), ) def parse_operation_type(parser): + # type: (Parser) -> str operation_token = expect(parser, TokenKind.NAME) operation = operation_token.value - if operation == 'query': - return 'query' - elif operation == 'mutation': - return 'mutation' - elif operation == 'subscription': - return 'subscription' + if operation == "query": + return "query" + elif operation == "mutation": + return "mutation" + elif operation == "subscription": + return "subscription" raise unexpected(parser, operation_token) def parse_variable_definitions(parser): + # type: (Parser) -> List[VariableDefinition] if peek(parser, TokenKind.PAREN_L): return many( - parser, - TokenKind.PAREN_L, - parse_variable_definition, - TokenKind.PAREN_R + parser, TokenKind.PAREN_L, parse_variable_definition, TokenKind.PAREN_R ) return [] def parse_variable_definition(parser): + # type: (Parser) -> VariableDefinition start = parser.token.start return ast.VariableDefinition( variable=parse_variable(parser), type=expect(parser, TokenKind.COLON) and parse_type(parser), - default_value=parse_value_literal(parser, True) if skip(parser, TokenKind.EQUALS) else None, - loc=loc(parser, start) + default_value=parse_value_literal(parser, True) + if skip(parser, TokenKind.EQUALS) + else None, + loc=loc(parser, start), ) def parse_variable(parser): + # type: (Parser) -> Variable start = parser.token.start expect(parser, TokenKind.DOLLAR) - return ast.Variable( - name=parse_name(parser), - loc=loc(parser, start) - ) + return ast.Variable(name=parse_name(parser), loc=loc(parser, start)) def parse_selection_set(parser): + # type: (Parser) -> SelectionSet start = parser.token.start return ast.SelectionSet( selections=many(parser, TokenKind.BRACE_L, parse_selection, TokenKind.BRACE_R), - loc=loc(parser, start) + loc=loc(parser, start), ) def parse_selection(parser): + # type: (Parser) -> Union[Field, FragmentSpread, InlineFragment] if peek(parser, TokenKind.SPREAD): return parse_fragment(parser) else: @@ -306,6 +370,7 @@ def parse_selection(parser): def parse_field(parser): + # type: (Parser) -> Field # Corresponds to both Field and Alias in the spec start = parser.token.start @@ -314,7 +379,7 @@ def parse_field(parser): alias = name_or_alias name = parse_name(parser) else: - alias = None + alias = None # type: ignore name = name_or_alias return ast.Field( @@ -322,46 +387,50 @@ def parse_field(parser): name=name, arguments=parse_arguments(parser), directives=parse_directives(parser), - selection_set=parse_selection_set(parser) if peek(parser, TokenKind.BRACE_L) else None, - loc=loc(parser, start) + selection_set=parse_selection_set(parser) + if peek(parser, TokenKind.BRACE_L) + else None, + loc=loc(parser, start), ) def parse_arguments(parser): + # type: (Parser) -> List[Argument] if peek(parser, TokenKind.PAREN_L): - return many( - parser, TokenKind.PAREN_L, - parse_argument, TokenKind.PAREN_R) + return many(parser, TokenKind.PAREN_L, parse_argument, TokenKind.PAREN_R) return [] def parse_argument(parser): + # type: (Parser) -> Argument start = parser.token.start return ast.Argument( name=parse_name(parser), value=expect(parser, TokenKind.COLON) and parse_value_literal(parser, False), - loc=loc(parser, start) + loc=loc(parser, start), ) # Implements the parsing rules in the Fragments section. + def parse_fragment(parser): + # type: (Parser) -> Union[FragmentSpread, InlineFragment] # Corresponds to both FragmentSpread and InlineFragment in the spec start = parser.token.start expect(parser, TokenKind.SPREAD) - if peek(parser, TokenKind.NAME) and parser.token.value != 'on': + if peek(parser, TokenKind.NAME) and parser.token.value != "on": return ast.FragmentSpread( name=parse_fragment_name(parser), directives=parse_directives(parser), - loc=loc(parser, start) + loc=loc(parser, start), ) type_condition = None - if parser.token.value == 'on': + if parser.token.value == "on": advance(parser) type_condition = parse_named_type(parser) @@ -369,31 +438,36 @@ def parse_fragment(parser): type_condition=type_condition, directives=parse_directives(parser), selection_set=parse_selection_set(parser), - loc=loc(parser, start) + loc=loc(parser, start), ) def parse_fragment_definition(parser): + # type: (Parser) -> FragmentDefinition start = parser.token.start - expect_keyword(parser, 'fragment') + expect_keyword(parser, "fragment") return ast.FragmentDefinition( name=parse_fragment_name(parser), - type_condition=expect_keyword(parser, 'on') and parse_named_type(parser), + type_condition=parse_named_type(parser) + if expect_keyword(parser, "on") + else None, directives=parse_directives(parser), selection_set=parse_selection_set(parser), - loc=loc(parser, start) + loc=loc(parser, start), ) def parse_fragment_name(parser): - if parser.token.value == 'on': + # type: (Parser) -> Name + if parser.token.value == "on": raise unexpected(parser) return parse_name(parser) def parse_value_literal(parser, is_const): + # type: (Parser, bool) -> Any token = parser.token if token.kind == TokenKind.BRACKET_L: return parse_list(parser, is_const) @@ -403,24 +477,34 @@ def parse_value_literal(parser, is_const): elif token.kind == TokenKind.INT: advance(parser) - return ast.IntValue(value=token.value, loc=loc(parser, token.start)) + return ast.IntValue( # type: ignore + value=token.value, loc=loc(parser, token.start) + ) elif token.kind == TokenKind.FLOAT: advance(parser) - return ast.FloatValue(value=token.value, loc=loc(parser, token.start)) + return ast.FloatValue( # type: ignore + value=token.value, loc=loc(parser, token.start) + ) elif token.kind == TokenKind.STRING: advance(parser) - return ast.StringValue(value=token.value, loc=loc(parser, token.start)) + return ast.StringValue( # type: ignore + value=token.value, loc=loc(parser, token.start) + ) elif token.kind == TokenKind.NAME: - if token.value in ('true', 'false'): + if token.value in ("true", "false"): advance(parser) - return ast.BooleanValue(value=token.value == 'true', loc=loc(parser, token.start)) + return ast.BooleanValue( # type: ignore + value=token.value == "true", loc=loc(parser, token.start) + ) - if token.value != 'null': + if token.value != "null": advance(parser) - return ast.EnumValue(value=token.value, loc=loc(parser, token.start)) + return ast.EnumValue( # type: ignore + value=token.value, loc=loc(parser, token.start) + ) elif token.kind == TokenKind.DOLLAR: if not is_const: @@ -431,26 +515,28 @@ def parse_value_literal(parser, is_const): # Implements the parsing rules in the Values section. def parse_variable_value(parser): + # type: (Parser) -> Union[IntValue, StringValue, Variable] return parse_value_literal(parser, False) def parse_const_value(parser): + # type: (Parser) -> Union[BooleanValue, ObjectValue, StringValue] return parse_value_literal(parser, True) def parse_list(parser, is_const): + # type: (Parser, bool) -> ListValue start = parser.token.start item = parse_const_value if is_const else parse_variable_value return ast.ListValue( - values=any( - parser, TokenKind.BRACKET_L, - item, TokenKind.BRACKET_R), - loc=loc(parser, start) + values=any(parser, TokenKind.BRACKET_L, item, TokenKind.BRACKET_R), + loc=loc(parser, start), ) def parse_object(parser, is_const): + # type: (Parser, bool) -> ObjectValue start = parser.token.start expect(parser, TokenKind.BRACE_L) fields = [] @@ -462,17 +548,20 @@ def parse_object(parser, is_const): def parse_object_field(parser, is_const): + # type: (Parser, bool) -> ObjectField start = parser.token.start return ast.ObjectField( name=parse_name(parser), value=expect(parser, TokenKind.COLON) and parse_value_literal(parser, is_const), - loc=loc(parser, start) + loc=loc(parser, start), ) # Implements the parsing rules in the Directives section. + def parse_directives(parser): + # type: (Parser) -> List[Directive] directives = [] while peek(parser, TokenKind.AT): directives.append(parse_directive(parser)) @@ -480,6 +569,7 @@ def parse_directives(parser): def parse_directive(parser): + # type: (Parser) -> Directive start = parser.token.start expect(parser, TokenKind.AT) @@ -492,13 +582,14 @@ def parse_directive(parser): # Implements the parsing rules in the Types section. def parse_type(parser): + # type: (Parser) -> Union[NamedType, NonNullType, ListType] """Handles the 'Type': TypeName, ListType, and NonNullType parsing rules.""" start = parser.token.start if skip(parser, TokenKind.BRACKET_L): ast_type = parse_type(parser) expect(parser, TokenKind.BRACKET_R) - ast_type = ast.ListType(type=ast_type, loc=loc(parser, start)) + ast_type = ast.ListType(type=ast_type, loc=loc(parser, start)) # type: ignore else: ast_type = parse_named_type(parser) @@ -510,15 +601,14 @@ def parse_type(parser): def parse_named_type(parser): + # type: (Parser) -> NamedType start = parser.token.start - return ast.NamedType( - name=parse_name(parser), - loc=loc(parser, start), - ) + return ast.NamedType(name=parse_name(parser), loc=loc(parser, start)) def parse_type_system_definition(parser): - ''' + # type: (Parser) -> Any + """ TypeSystemDefinition : - SchemaDefinition - TypeDefinition @@ -532,75 +622,71 @@ def parse_type_system_definition(parser): - UnionTypeDefinition - EnumTypeDefinition - InputObjectTypeDefinition - ''' + """ if not peek(parser, TokenKind.NAME): raise unexpected(parser) name = parser.token.value - if name == 'schema': + if name == "schema": return parse_schema_definition(parser) - elif name == 'scalar': + elif name == "scalar": return parse_scalar_type_definition(parser) - elif name == 'type': + elif name == "type": return parse_object_type_definition(parser) - elif name == 'interface': + elif name == "interface": return parse_interface_type_definition(parser) - elif name == 'union': + elif name == "union": return parse_union_type_definition(parser) - elif name == 'enum': + elif name == "enum": return parse_enum_type_definition(parser) - elif name == 'input': + elif name == "input": return parse_input_object_type_definition(parser) - elif name == 'extend': + elif name == "extend": return parse_type_extension_definition(parser) - elif name == 'directive': + elif name == "directive": return parse_directive_definition(parser) raise unexpected(parser) def parse_schema_definition(parser): + # type: (Parser) -> SchemaDefinition start = parser.token.start - expect_keyword(parser, 'schema') + expect_keyword(parser, "schema") directives = parse_directives(parser) operation_types = many( - parser, - TokenKind.BRACE_L, - parse_operation_type_definition, - TokenKind.BRACE_R + parser, TokenKind.BRACE_L, parse_operation_type_definition, TokenKind.BRACE_R ) return ast.SchemaDefinition( - directives=directives, - operation_types=operation_types, - loc=loc(parser, start) + directives=directives, operation_types=operation_types, loc=loc(parser, start) ) def parse_operation_type_definition(parser): + # type: (Parser) -> OperationTypeDefinition start = parser.token.start operation = parse_operation_type(parser) expect(parser, TokenKind.COLON) return ast.OperationTypeDefinition( - operation=operation, - type=parse_named_type(parser), - loc=loc(parser, start) + operation=operation, type=parse_named_type(parser), loc=loc(parser, start) ) def parse_scalar_type_definition(parser): + # type: (Parser) -> ScalarTypeDefinition start = parser.token.start - expect_keyword(parser, 'scalar') + expect_keyword(parser, "scalar") return ast.ScalarTypeDefinition( name=parse_name(parser), @@ -610,25 +696,24 @@ def parse_scalar_type_definition(parser): def parse_object_type_definition(parser): + # type: (Parser) -> ObjectTypeDefinition start = parser.token.start - expect_keyword(parser, 'type') + expect_keyword(parser, "type") return ast.ObjectTypeDefinition( name=parse_name(parser), interfaces=parse_implements_interfaces(parser), directives=parse_directives(parser), fields=any( - parser, - TokenKind.BRACE_L, - parse_field_definition, - TokenKind.BRACE_R + parser, TokenKind.BRACE_L, parse_field_definition, TokenKind.BRACE_R ), loc=loc(parser, start), ) def parse_implements_interfaces(parser): + # type: (Parser) -> List[NamedType] types = [] - if parser.token.value == 'implements': + if parser.token.value == "implements": advance(parser) while True: @@ -641,9 +726,10 @@ def parse_implements_interfaces(parser): def parse_field_definition(parser): + # type: (Parser) -> FieldDefinition start = parser.token.start - return ast.FieldDefinition( + return ast.FieldDefinition( # type: ignore name=parse_name(parser), arguments=parse_argument_defs(parser), type=expect(parser, TokenKind.COLON) and parse_type(parser), @@ -653,6 +739,7 @@ def parse_field_definition(parser): def parse_argument_defs(parser): + # type: (Parser) -> List[InputValueDefinition] if not peek(parser, TokenKind.PAREN_L): return [] @@ -660,34 +747,41 @@ def parse_argument_defs(parser): def parse_input_value_def(parser): + # type: (Parser) -> InputValueDefinition start = parser.token.start - return ast.InputValueDefinition( + return ast.InputValueDefinition( # type: ignore name=parse_name(parser), type=expect(parser, TokenKind.COLON) and parse_type(parser), - default_value=parse_const_value(parser) if skip(parser, TokenKind.EQUALS) else None, + default_value=parse_const_value(parser) + if skip(parser, TokenKind.EQUALS) + else None, directives=parse_directives(parser), loc=loc(parser, start), ) def parse_interface_type_definition(parser): + # type: (Parser) -> InterfaceTypeDefinition start = parser.token.start - expect_keyword(parser, 'interface') + expect_keyword(parser, "interface") return ast.InterfaceTypeDefinition( name=parse_name(parser), directives=parse_directives(parser), - fields=any(parser, TokenKind.BRACE_L, parse_field_definition, TokenKind.BRACE_R), + fields=any( + parser, TokenKind.BRACE_L, parse_field_definition, TokenKind.BRACE_R + ), loc=loc(parser, start), ) def parse_union_type_definition(parser): + # type: (Parser) -> UnionTypeDefinition start = parser.token.start - expect_keyword(parser, 'union') + expect_keyword(parser, "union") - return ast.UnionTypeDefinition( + return ast.UnionTypeDefinition( # type: ignore name=parse_name(parser), directives=parse_directives(parser), types=expect(parser, TokenKind.EQUALS) and parse_union_members(parser), @@ -696,6 +790,7 @@ def parse_union_type_definition(parser): def parse_union_members(parser): + # type: (Parser) -> List[NamedType] members = [] while True: @@ -708,18 +803,22 @@ def parse_union_members(parser): def parse_enum_type_definition(parser): + # type: (Parser) -> EnumTypeDefinition start = parser.token.start - expect_keyword(parser, 'enum') + expect_keyword(parser, "enum") return ast.EnumTypeDefinition( name=parse_name(parser), directives=parse_directives(parser), - values=many(parser, TokenKind.BRACE_L, parse_enum_value_definition, TokenKind.BRACE_R), + values=many( + parser, TokenKind.BRACE_L, parse_enum_value_definition, TokenKind.BRACE_R + ), loc=loc(parser, start), ) def parse_enum_value_definition(parser): + # type: (Parser) -> EnumValueDefinition start = parser.token.start return ast.EnumValueDefinition( @@ -730,8 +829,9 @@ def parse_enum_value_definition(parser): def parse_input_object_type_definition(parser): + # type: (Parser) -> InputObjectTypeDefinition start = parser.token.start - expect_keyword(parser, 'input') + expect_keyword(parser, "input") return ast.InputObjectTypeDefinition( name=parse_name(parser), @@ -742,34 +842,33 @@ def parse_input_object_type_definition(parser): def parse_type_extension_definition(parser): + # type: (Parser) -> TypeExtensionDefinition start = parser.token.start - expect_keyword(parser, 'extend') + expect_keyword(parser, "extend") return ast.TypeExtensionDefinition( - definition=parse_object_type_definition(parser), - loc=loc(parser, start) + definition=parse_object_type_definition(parser), loc=loc(parser, start) ) def parse_directive_definition(parser): + # type: (Parser) -> DirectiveDefinition start = parser.token.start - expect_keyword(parser, 'directive') + expect_keyword(parser, "directive") expect(parser, TokenKind.AT) name = parse_name(parser) args = parse_argument_defs(parser) - expect_keyword(parser, 'on') + expect_keyword(parser, "on") locations = parse_directive_locations(parser) return ast.DirectiveDefinition( - name=name, - locations=locations, - arguments=args, - loc=loc(parser, start) + name=name, locations=locations, arguments=args, loc=loc(parser, start) ) def parse_directive_locations(parser): + # type: (Parser) -> List[Name] locations = [] while True: diff --git a/graphql/language/printer.py b/graphql/language/printer.py index e136b7d1..11e086eb 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -2,10 +2,52 @@ from .visitor import Visitor, visit -__all__ = ['print_ast'] +if False: + from typing import Any, List, Optional, Union + from graphql.language.ast import ( + Node, + Name, + Variable, + Document, + OperationDefinition, + VariableDefinition, + SelectionSet, + Field, + Argument, + FragmentSpread, + InlineFragment, + FragmentDefinition, + IntValue, + StringValue, + BooleanValue, + EnumValue, + ListValue, + ObjectValue, + ObjectField, + Directive, + NamedType, + ListType, + NonNullType, + SchemaDefinition, + OperationTypeDefinition, + ScalarTypeDefinition, + ObjectTypeDefinition, + FieldDefinition, + InputValueDefinition, + InterfaceTypeDefinition, + UnionTypeDefinition, + EnumTypeDefinition, + EnumValueDefinition, + InputObjectTypeDefinition, + TypeExtensionDefinition, + DirectiveDefinition, + ) + +__all__ = ["print_ast"] def print_ast(ast): + # type: (Node) -> str return visit(ast, PrintingVisitor()) @@ -13,181 +55,265 @@ class PrintingVisitor(Visitor): __slots__ = () def leave_Name(self, node, *args): + # type: (Name, *Any) -> str return node.value def leave_Variable(self, node, *args): - return '$' + node.name + # type: (Variable, *Any) -> str + return "$" + node.name def leave_Document(self, node, *args): - return join(node.definitions, '\n\n') + '\n' + # type: (Document, *Any) -> str + return join(node.definitions, "\n\n") + "\n" def leave_OperationDefinition(self, node, *args): + # type: (OperationDefinition, *Any) -> str name = node.name selection_set = node.selection_set op = node.operation - var_defs = wrap('(', join(node.variable_definitions, ', '), ')') - directives = join(node.directives, ' ') + var_defs = wrap("(", join(node.variable_definitions, ", "), ")") + directives = join(node.directives, " ") - if not name and not directives and not var_defs and op == 'query': + if not name and not directives and not var_defs and op == "query": return selection_set - return join([op, join([name, var_defs]), directives, selection_set], ' ') + return join([op, join([name, var_defs]), directives, selection_set], " ") def leave_VariableDefinition(self, node, *args): - return node.variable + ': ' + node.type + wrap(' = ', node.default_value) + # type: (VariableDefinition, *Any) -> str + return node.variable + ": " + node.type + wrap(" = ", node.default_value) def leave_SelectionSet(self, node, *args): + # type: (SelectionSet, *Any) -> str return block(node.selections) def leave_Field(self, node, *args): - return join([ - wrap('', node.alias, ': ') + node.name + wrap('(', join(node.arguments, ', '), ')'), - join(node.directives, ' '), - node.selection_set - ], ' ') + # type: (Field, *Any) -> str + return join( + [ + wrap("", node.alias, ": ") + + node.name + + wrap("(", join(node.arguments, ", "), ")"), + join(node.directives, " "), + node.selection_set, + ], + " ", + ) def leave_Argument(self, node, *args): - return '{0.name}: {0.value}'.format(node) + # type: (Argument, *Any) -> str + return "{0.name}: {0.value}".format(node) # Fragments def leave_FragmentSpread(self, node, *args): - return '...' + node.name + wrap(' ', join(node.directives, ' ')) + # type: (FragmentSpread, *Any) -> str + return "..." + node.name + wrap(" ", join(node.directives, " ")) def leave_InlineFragment(self, node, *args): - return join([ - '...', - wrap('on ', node.type_condition), - join(node.directives, ''), - node.selection_set - ], ' ') + # type: (InlineFragment, *Any) -> str + return join( + [ + "...", + wrap("on ", node.type_condition), + join(node.directives, ""), + node.selection_set, + ], + " ", + ) def leave_FragmentDefinition(self, node, *args): - return ('fragment {} on {} '.format(node.name, node.type_condition) + - wrap('', join(node.directives, ' '), ' ') + - node.selection_set) + # type: (FragmentDefinition, *Any) -> str + return ( + "fragment {} on {} ".format(node.name, node.type_condition) + + wrap("", join(node.directives, " "), " ") + + node.selection_set + ) # Value def leave_IntValue(self, node, *args): + # type: (IntValue, *Any) -> str return node.value def leave_FloatValue(self, node, *args): return node.value def leave_StringValue(self, node, *args): + # type: (StringValue, *Any) -> str return json.dumps(node.value) def leave_BooleanValue(self, node, *args): + # type: (BooleanValue, *Any) -> str return json.dumps(node.value) def leave_EnumValue(self, node, *args): + # type: (EnumValue, *Any) -> str return node.value def leave_ListValue(self, node, *args): - return '[' + join(node.values, ', ') + ']' + # type: (ListValue, *Any) -> str + return "[" + join(node.values, ", ") + "]" def leave_ObjectValue(self, node, *args): - return '{' + join(node.fields, ', ') + '}' + # type: (ObjectValue, *Any) -> str + return "{" + join(node.fields, ", ") + "}" def leave_ObjectField(self, node, *args): - return node.name + ': ' + node.value + # type: (ObjectField, *Any) -> str + return node.name + ": " + node.value # Directive def leave_Directive(self, node, *args): - return '@' + node.name + wrap('(', join(node.arguments, ', '), ')') + # type: (Directive, *Any) -> str + return "@" + node.name + wrap("(", join(node.arguments, ", "), ")") # Type def leave_NamedType(self, node, *args): + # type: (NamedType, *Any) -> str return node.name def leave_ListType(self, node, *args): - return '[' + node.type + ']' + # type: (ListType, *Any) -> str + return "[" + node.type + "]" def leave_NonNullType(self, node, *args): - return node.type + '!' + # type: (NonNullType, *Any) -> str + return node.type + "!" # Type Definitions: def leave_SchemaDefinition(self, node, *args): - return join([ - 'schema', - join(node.directives, ' '), - block(node.operation_types), - ], ' ') + # type: (SchemaDefinition, *Any) -> str + return join( + ["schema", join(node.directives, " "), block(node.operation_types)], " " + ) def leave_OperationTypeDefinition(self, node, *args): - return '{}: {}'.format(node.operation, node.type) + # type: (OperationTypeDefinition, *Any) -> str + return "{}: {}".format(node.operation, node.type) def leave_ScalarTypeDefinition(self, node, *args): - return 'scalar ' + node.name + wrap(' ', join(node.directives, ' ')) + # type: (ScalarTypeDefinition, *Any) -> str + return "scalar " + node.name + wrap(" ", join(node.directives, " ")) def leave_ObjectTypeDefinition(self, node, *args): - return join([ - 'type', - node.name, - wrap('implements ', join(node.interfaces, ', ')), - join(node.directives, ' '), - block(node.fields) - ], ' ') + # type: (ObjectTypeDefinition, *Any) -> str + return join( + [ + "type", + node.name, + wrap("implements ", join(node.interfaces, ", ")), + join(node.directives, " "), + block(node.fields), + ], + " ", + ) def leave_FieldDefinition(self, node, *args): + # type: (FieldDefinition, *Any) -> str return ( - node.name + - wrap('(', join(node.arguments, ', '), ')') + - ': ' + - node.type + - wrap(' ', join(node.directives, ' ')) + node.name + + wrap("(", join(node.arguments, ", "), ")") + + ": " + + node.type + + wrap(" ", join(node.directives, " ")) ) def leave_InputValueDefinition(self, node, *args): - return node.name + ': ' + node.type + wrap(' = ', node.default_value) + wrap(' ', join(node.directives, ' ')) + # type: (InputValueDefinition, *Any) -> str + return ( + node.name + + ": " + + node.type + + wrap(" = ", node.default_value) + + wrap(" ", join(node.directives, " ")) + ) def leave_InterfaceTypeDefinition(self, node, *args): - return 'interface ' + node.name + wrap(' ', join(node.directives, ' ')) + ' ' + block(node.fields) + # type: (InterfaceTypeDefinition, *Any) -> str + return ( + "interface " + + node.name + + wrap(" ", join(node.directives, " ")) + + " " + + block(node.fields) + ) def leave_UnionTypeDefinition(self, node, *args): - return 'union ' + node.name + wrap(' ', join(node.directives, ' ')) + ' = ' + join(node.types, ' | ') + # type: (UnionTypeDefinition, *Any) -> str + return ( + "union " + + node.name + + wrap(" ", join(node.directives, " ")) + + " = " + + join(node.types, " | ") + ) def leave_EnumTypeDefinition(self, node, *args): - return 'enum ' + node.name + wrap(' ', join(node.directives, ' ')) + ' ' + block(node.values) + # type: (EnumTypeDefinition, *Any) -> str + return ( + "enum " + + node.name + + wrap(" ", join(node.directives, " ")) + + " " + + block(node.values) + ) def leave_EnumValueDefinition(self, node, *args): - return node.name + wrap(' ', join(node.directives, ' ')) + # type: (EnumValueDefinition, *Any) -> str + return node.name + wrap(" ", join(node.directives, " ")) def leave_InputObjectTypeDefinition(self, node, *args): - return 'input ' + node.name + wrap(' ', join(node.directives, ' ')) + ' ' + block(node.fields) + # type: (InputObjectTypeDefinition, *Any) -> str + return ( + "input " + + node.name + + wrap(" ", join(node.directives, " ")) + + " " + + block(node.fields) + ) def leave_TypeExtensionDefinition(self, node, *args): - return 'extend ' + node.definition + # type: (TypeExtensionDefinition, *Any) -> str + return "extend " + node.definition def leave_DirectiveDefinition(self, node, *args): - return 'directive @{}{} on {}'.format(node.name, wrap( - '(', join(node.arguments, ', '), ')'), ' | '.join(node.locations)) + # type: (DirectiveDefinition, *Any) -> str + return "directive @{}{} on {}".format( + node.name, + wrap("(", join(node.arguments, ", "), ")"), + " | ".join(node.locations), + ) -def join(maybe_list, separator=''): +def join(maybe_list, separator=""): + # type: (Optional[List[Optional[str]]], str) -> str if maybe_list: return separator.join(filter(None, maybe_list)) - return '' + return "" def block(_list): - '''Given a list, print each item on its own line, wrapped in an indented "{ }" block.''' + # type: (List[str]) -> str + """Given a list, print each item on its own line, wrapped in an indented "{ }" block.""" if _list: - return indent('{\n' + join(_list, '\n')) + '\n}' - return '{}' + return indent("{\n" + join(_list, "\n")) + "\n}" + return "{}" -def wrap(start, maybe_str, end=''): +def wrap(start, maybe_str, end=""): + # type: (str, Optional[str], str) -> str if maybe_str: return start + maybe_str + end - return '' + return "" def indent(maybe_str): + # type: (Optional[str]) -> str if maybe_str: - return maybe_str.replace('\n', '\n ') - return maybe_str + return maybe_str.replace("\n", "\n ") + return "" + diff --git a/graphql/language/source.py b/graphql/language/source.py index 14e22fac..7af63eeb 100644 --- a/graphql/language/source.py +++ b/graphql/language/source.py @@ -5,6 +5,7 @@ class Source(object): __slots__ = 'body', 'name' def __init__(self, body, name='GraphQL'): + # type: (str, str) -> None self.body = body self.name = name diff --git a/graphql/language/tests/test_ast.py b/graphql/language/tests/test_ast.py index 269d1f09..e0f8476f 100644 --- a/graphql/language/tests/test_ast.py +++ b/graphql/language/tests/test_ast.py @@ -4,18 +4,21 @@ def test_ast_is_hashable(): + # type: () -> None for node_class in QUERY_DOCUMENT_KEYS: node = node_class(loc=None, **{k: k for k in node_class._fields}) assert hash(node) def test_ast_is_copyable(): + # type: () -> None for node_class in QUERY_DOCUMENT_KEYS: node = node_class(loc=None, **{k: k for k in node_class._fields}) assert copy.copy(node) == node def test_ast_is_reprable(): + # type: () -> None for node_class in QUERY_DOCUMENT_KEYS: node = node_class(loc=None, **{k: k for k in node_class._fields}) assert repr(node) diff --git a/graphql/language/tests/test_lexer.py b/graphql/language/tests/test_lexer.py index 44283355..36bf9c9b 100644 --- a/graphql/language/tests/test_lexer.py +++ b/graphql/language/tests/test_lexer.py @@ -6,15 +6,18 @@ def lex_one(s): + # type: (str) -> Token return Lexer(Source(s)).next_token() def test_repr_token(): + # type: () -> None token = lex_one('500') assert repr(token) == "" def test_disallows_uncommon_control_characters(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u'\u0007') @@ -22,10 +25,12 @@ def test_disallows_uncommon_control_characters(): def test_accepts_bom_header(): + # type: () -> None assert lex_one(u'\uFEFF foo') == Token(TokenKind.NAME, 2, 5, u'foo') def test_skips_whitespace(): + # type: () -> None assert lex_one(u""" foo @@ -42,6 +47,7 @@ def test_skips_whitespace(): def test_errors_respect_whitespace(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u""" @@ -60,6 +66,7 @@ def test_errors_respect_whitespace(): def test_lexes_strings(): + # type: () -> None assert lex_one(u'"simple"') == Token(TokenKind.STRING, 0, 8, 'simple') assert lex_one(u'" white space "') == Token(TokenKind.STRING, 0, 15, ' white space ') assert lex_one(u'"quote \\""') == Token(TokenKind.STRING, 0, 10, 'quote "') @@ -70,6 +77,7 @@ def test_lexes_strings(): def test_lex_reports_useful_string_errors(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"') assert u'Syntax Error GraphQL (1:2) Unterminated string' in excinfo.value.message @@ -124,6 +132,7 @@ def test_lex_reports_useful_string_errors(): def test_lexes_numbers(): + # type: () -> None assert lex_one(u'4') == Token(TokenKind.INT, 0, 1, '4') assert lex_one(u'4.123') == Token(TokenKind.FLOAT, 0, 5, '4.123') assert lex_one(u'-4') == Token(TokenKind.INT, 0, 2, '-4') @@ -143,6 +152,7 @@ def test_lexes_numbers(): def test_lex_reports_useful_number_errors(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u'00') assert u'Syntax Error GraphQL (1:2) Invalid number, unexpected digit after 0: "0".' in excinfo.value.message @@ -177,6 +187,7 @@ def test_lex_reports_useful_number_errors(): def test_lexes_punctuation(): + # type: () -> None assert lex_one(u'!') == Token(TokenKind.BANG, 0, 1) assert lex_one(u'$') == Token(TokenKind.DOLLAR, 0, 1) assert lex_one(u'(') == Token(TokenKind.PAREN_L, 0, 1) @@ -193,6 +204,7 @@ def test_lexes_punctuation(): def test_lex_reports_useful_unknown_character_error(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u'..') assert u'Syntax Error GraphQL (1:1) Unexpected character "."' in excinfo.value.message @@ -211,6 +223,7 @@ def test_lex_reports_useful_unknown_character_error(): def test_lex_reports_useful_information_for_dashes_in_names(): + # type: () -> None q = u'a-b' lexer = Lexer(Source(q)) first_token = lexer.next_token() diff --git a/graphql/language/tests/test_location.py b/graphql/language/tests/test_location.py index ef7ce064..48884893 100644 --- a/graphql/language/tests/test_location.py +++ b/graphql/language/tests/test_location.py @@ -2,5 +2,6 @@ def test_repr_source_location(): + # type: () -> None loc = SourceLocation(10, 25) assert repr(loc) == 'SourceLocation(line=10, column=25)' diff --git a/graphql/language/tests/test_parser.py b/graphql/language/tests/test_parser.py index 7d587db8..3bf8d611 100644 --- a/graphql/language/tests/test_parser.py +++ b/graphql/language/tests/test_parser.py @@ -10,11 +10,13 @@ def test_repr_loc(): + # type: () -> None loc = Loc(start=10, end=25, source='foo') assert repr(loc) == '' def test_empty_parse(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse("") assert ( @@ -24,6 +26,7 @@ def test_empty_parse(): def test_parse_provides_useful_errors(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse("""{""") assert ( @@ -60,6 +63,7 @@ def test_parse_provides_useful_errors(): def test_parse_provides_useful_error_when_using_source(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse(Source('query', 'MyQuery.graphql')) assert 'Syntax Error MyQuery.graphql (1:6) Expected {, found EOF' in str( @@ -67,16 +71,19 @@ def test_parse_provides_useful_error_when_using_source(): def test_parses_variable_inline_values(): + # type: () -> None parse('{ field(complex: { a: { b: [ $var ] } }) }') def test_parses_constant_default_values(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse('query Foo($x: Complex = { a: { b: [ $var ] } }) { field }') assert 'Syntax Error GraphQL (1:37) Unexpected $' in str(excinfo.value) def test_does_not_accept_fragments_named_on(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse('fragment on on on { on }') @@ -84,6 +91,7 @@ def test_does_not_accept_fragments_named_on(): def test_does_not_accept_fragments_spread_of_on(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse('{ ...on }') @@ -91,6 +99,7 @@ def test_does_not_accept_fragments_spread_of_on(): def test_does_not_allow_null_value(): + # type: () -> None with raises(GraphQLSyntaxError) as excinfo: parse('{ fieldWithNullableStringInput(input: null) }') @@ -98,6 +107,7 @@ def test_does_not_allow_null_value(): def test_parses_multi_byte_characters(): + # type: () -> None result = parse(u''' # This comment has a \u0A0A multi-byte character. { field(arg: "Has a \u0A0A multi-byte character.") } @@ -152,10 +162,12 @@ def tesst_allows_non_keywords_anywhere_a_name_is_allowed(): def test_parses_kitchen_sink(): + # type: () -> None parse(KITCHEN_SINK) def test_parses_anonymous_mutation_operations(): + # type: () -> None parse(''' mutation { mutationField @@ -164,6 +176,7 @@ def test_parses_anonymous_mutation_operations(): def test_parses_anonymous_subscription_operations(): + # type: () -> None parse(''' subscription { mutationField @@ -172,6 +185,7 @@ def test_parses_anonymous_subscription_operations(): def test_parses_named_mutation_operations(): + # type: () -> None parse(''' mutation Foo { mutationField @@ -180,6 +194,7 @@ def test_parses_named_mutation_operations(): def test_parses_named_subscription_operations(): + # type: () -> None parse(''' subscription Foo { subscriptionField @@ -188,6 +203,7 @@ def test_parses_named_subscription_operations(): def test_parse_creates_ast(): + # type: () -> None source = Source("""{ node(id: 4) { id, diff --git a/graphql/language/tests/test_printer.py b/graphql/language/tests/test_printer.py index 5d8ce7ea..f1188898 100644 --- a/graphql/language/tests/test_printer.py +++ b/graphql/language/tests/test_printer.py @@ -10,6 +10,7 @@ def test_does_not_alter_ast(): + # type: () -> None ast = parse(KITCHEN_SINK) ast_copy = copy.deepcopy(ast) print_ast(ast) @@ -17,11 +18,13 @@ def test_does_not_alter_ast(): def test_prints_minimal_ast(): + # type: () -> None ast = Field(name=Name(loc=None, value='foo')) assert print_ast(ast) == 'foo' def test_produces_helpful_error_messages(): + # type: () -> None bad_ast = {'random': 'Data'} with raises(Exception) as excinfo: print_ast(bad_ast) @@ -29,6 +32,7 @@ def test_produces_helpful_error_messages(): def test_correctly_prints_query_operation_without_name(): + # type: () -> None query_ast_shorthanded = parse('query { id, name }') assert print_ast(query_ast_shorthanded) == '''{ id @@ -38,6 +42,7 @@ def test_correctly_prints_query_operation_without_name(): def test_correctly_prints_mutation_operation_without_name(): + # type: () -> None mutation_ast = parse('mutation { id, name }') assert print_ast(mutation_ast) == '''mutation { id @@ -47,6 +52,7 @@ def test_correctly_prints_mutation_operation_without_name(): def test_correctly_prints_query_with_artifacts(): + # type: () -> None query_ast_shorthanded = parse( 'query ($foo: TestType) @testDirective { id, name }' ) @@ -58,6 +64,7 @@ def test_correctly_prints_query_with_artifacts(): def test_correctly_prints_mutation_with_artifacts(): + # type: () -> None query_ast_shorthanded = parse( 'mutation ($foo: TestType) @testDirective { id, name }' ) @@ -69,6 +76,7 @@ def test_correctly_prints_mutation_with_artifacts(): def test_prints_kitchen_sink(): + # type: () -> None ast = parse(KITCHEN_SINK) printed = print_ast(ast) assert printed == '''query queryName($foo: ComplexType, $site: Site = MOBILE) { diff --git a/graphql/language/tests/test_schema_parser.py b/graphql/language/tests/test_schema_parser.py index 59c690c7..cfb7b33d 100644 --- a/graphql/language/tests/test_schema_parser.py +++ b/graphql/language/tests/test_schema_parser.py @@ -4,14 +4,17 @@ from graphql.error import GraphQLSyntaxError from graphql.language import ast from graphql.language.parser import Loc +from typing import Callable def create_loc_fn(body): + # type: (str) -> Callable source = Source(body) return lambda start, end: Loc(start, end, source) def test_parses_simple_type(): + # type: () -> None body = ''' type Hello { world: String @@ -56,6 +59,7 @@ def test_parses_simple_type(): def test_parses_simple_extension(): + # type: () -> None body = ''' extend type Hello { world: String @@ -103,6 +107,7 @@ def test_parses_simple_extension(): def test_simple_non_null_type(): + # type: () -> None body = ''' type Hello { world: String! @@ -149,6 +154,7 @@ def test_simple_non_null_type(): def test_parses_simple_type_inheriting_interface(): + # type: () -> None body = 'type Hello implements World { }' loc = create_loc_fn(body) doc = parse(body) @@ -180,6 +186,7 @@ def test_parses_simple_type_inheriting_interface(): def test_parses_simple_type_inheriting_multiple_interfaces(): + # type: () -> None body = 'type Hello implements Wo, rld { }' loc = create_loc_fn(body) doc = parse(body) @@ -217,6 +224,7 @@ def test_parses_simple_type_inheriting_multiple_interfaces(): def test_parses_single_value_enum(): + # type: () -> None body = 'enum Hello { WORLD }' loc = create_loc_fn(body) doc = parse(body) @@ -248,6 +256,7 @@ def test_parses_single_value_enum(): def test_parses_double_value_enum(): + # type: () -> None body = 'enum Hello { WO, RLD }' loc = create_loc_fn(body) doc = parse(body) @@ -287,6 +296,7 @@ def test_parses_double_value_enum(): def test_parses_simple_interface(): + # type: () -> None body = ''' interface Hello { world: String @@ -330,6 +340,7 @@ def test_parses_simple_interface(): def test_parses_simple_field_with_arg(): + # type: () -> None body = ''' type Hello { world(flag: Boolean): String @@ -390,6 +401,7 @@ def test_parses_simple_field_with_arg(): def test_parses_simple_field_with_arg_with_default_value(): + # type: () -> None body = ''' type Hello { world(flag: Boolean = true): String @@ -453,6 +465,7 @@ def test_parses_simple_field_with_arg_with_default_value(): def test_parses_simple_field_with_list_arg(): + # type: () -> None body = ''' type Hello { world(things: [String]): String @@ -515,6 +528,7 @@ def test_parses_simple_field_with_list_arg(): def test_parses_simple_field_with_two_args(): + # type: () -> None body = ''' type Hello { world(argOne: Boolean, argTwo: Int): String @@ -590,6 +604,7 @@ def test_parses_simple_field_with_two_args(): def test_parses_simple_union(): + # type: () -> None body = 'union Hello = World' loc = create_loc_fn(body) doc = parse(body) @@ -619,6 +634,7 @@ def test_parses_simple_union(): def test_parses_union_with_two_types(): + # type: () -> None body = 'union Hello = Wo | Rld' loc = create_loc_fn(body) doc = parse(body) @@ -655,6 +671,7 @@ def test_parses_union_with_two_types(): def test_parses_scalar(): + # type: () -> None body = 'scalar Hello' loc = create_loc_fn(body) doc = parse(body) @@ -675,6 +692,7 @@ def test_parses_scalar(): def test_parses_simple_input_object(): + # type: () -> None body = ''' input Hello { world: String @@ -716,6 +734,7 @@ def test_parses_simple_input_object(): def test_parsing_simple_input_object_with_args_should_fail(): + # type: () -> None body = ''' input Hello { world(foo: Int): String diff --git a/graphql/language/tests/test_schema_printer.py b/graphql/language/tests/test_schema_printer.py index e565799e..dd812c01 100644 --- a/graphql/language/tests/test_schema_printer.py +++ b/graphql/language/tests/test_schema_printer.py @@ -10,6 +10,7 @@ def test_prints_minimal_ast(): + # type: () -> None node = ast.ScalarTypeDefinition( name=ast.Name('foo') ) @@ -18,6 +19,7 @@ def test_prints_minimal_ast(): def test_print_produces_helpful_error_messages(): + # type: () -> None bad_ast = {'random': 'Data'} with raises(AssertionError) as excinfo: print_ast(bad_ast) @@ -26,6 +28,7 @@ def test_print_produces_helpful_error_messages(): def test_does_not_alter_ast(): + # type: () -> None ast = parse(SCHEMA_KITCHEN_SINK) ast_copy = deepcopy(ast) print_ast(ast) @@ -33,6 +36,7 @@ def test_does_not_alter_ast(): def test_prints_kitchen_sink(): + # type: () -> None ast = parse(SCHEMA_KITCHEN_SINK) printed = print_ast(ast) diff --git a/graphql/language/tests/test_visitor.py b/graphql/language/tests/test_visitor.py index 5ede5294..4113f397 100644 --- a/graphql/language/tests/test_visitor.py +++ b/graphql/language/tests/test_visitor.py @@ -9,18 +9,36 @@ from ...validation.tests.utils import test_schema from .fixtures import KITCHEN_SINK +from graphql.language.ast import Document +from graphql.language.ast import OperationDefinition +from graphql.language.ast import SelectionSet +from typing import Any +from typing import Optional +from typing import Union +from graphql.language.ast import Field +from graphql.language.ast import Name +from graphql.language.visitor import Falsey +from typing import List +from graphql.language.ast import Argument +from graphql.language.ast import IntValue def test_allows_editing_a_node_both_on_enter_and_on_leave(): + # type: () -> None ast = parse('{ a, b, c { a, b, c } }', no_location=True) class TestVisitor(Visitor): def __init__(self): + # type: () -> None self.did_enter = False self.did_leave = False - def enter(self, node, *args): + def enter(self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + *args # type: Any + ): + # type: (...) -> Optional[OperationDefinition] if isinstance(node, OperationDefinition): self.did_enter = True selection_set = node.selection_set @@ -37,7 +55,11 @@ def enter(self, node, *args): operation=node.operation, selection_set=new_selection_set) - def leave(self, node, *args): + def leave(self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + *args # type: Any + ): + # type: (...) -> Optional[OperationDefinition] if isinstance(node, OperationDefinition): self.did_leave = True new_selection_set = None @@ -61,6 +83,7 @@ def leave(self, node, *args): def test_allows_editing_the_root_node_on_enter_and_on_leave(): + # type: () -> None ast = parse('{ a, b, c { a, b, c } }', no_location=True) definitions = ast.definitions @@ -68,10 +91,12 @@ def test_allows_editing_the_root_node_on_enter_and_on_leave(): class TestVisitor(Visitor): def __init__(self): + # type: () -> None self.did_enter = False self.did_leave = False def enter(self, node, *args): + # type: (Document, *Any) -> Document if isinstance(node, Document): self.did_enter = True return Document( @@ -79,6 +104,7 @@ def enter(self, node, *args): definitions=[]) def leave(self, node, *args): + # type: (Document, *Any) -> Document if isinstance(node, Document): self.did_leave = True return Document( @@ -93,11 +119,13 @@ def leave(self, node, *args): def test_allows_for_editing_on_enter(): + # type: () -> None ast = parse('{ a, b, c { a, b, c } }', no_location=True) class TestVisitor(Visitor): def enter(self, node, *args): + # type: (Any, *Any) -> Optional[Any] if isinstance(node, Field) and node.name.value == 'b': return REMOVE @@ -108,11 +136,13 @@ def enter(self, node, *args): def test_allows_for_editing_on_leave(): + # type: () -> None ast = parse('{ a, b, c { a, b, c } }', no_location=True) class TestVisitor(Visitor): def leave(self, node, *args): + # type: (Union[Field, Name], *Any) -> Optional[Falsey] if isinstance(node, Field) and node.name.value == 'b': return REMOVE @@ -123,15 +153,18 @@ def leave(self, node, *args): def test_visits_edited_node(): + # type: () -> None added_field = Field(name=Name(value='__typename')) ast = parse('{ a { x } }') class TestVisitor(Visitor): def __init__(self): + # type: () -> None self.did_visit_added_field = False def enter(self, node, *args): + # type: (Any, *Any) -> Optional[Field] if isinstance(node, Field) and node.name.value == 'a': selection_set = node.selection_set selections = [] @@ -149,18 +182,21 @@ def enter(self, node, *args): def test_allows_skipping_a_subtree(): + # type: () -> None visited = [] ast = parse('{ a, b { x }, c }') class TestVisitor(Visitor): def enter(self, node, *args): + # type: (Any, *Any) -> Optional[Any] visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) if isinstance(node, Field) and node.name.value == 'b': return False def leave(self, node, *args): + # type: (Union[Field, Name, SelectionSet], *Any) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -186,18 +222,21 @@ def leave(self, node, *args): def test_allows_early_exit_while_visiting(): + # type: () -> None visited = [] ast = parse('{ a, b { x }, c }') class TestVisitor(Visitor): def enter(self, node, *args): + # type: (Any, *Any) -> Optional[Any] visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) if isinstance(node, Name) and node.value == 'x': return BREAK def leave(self, node, *args): + # type: (Union[Field, Name], *Any) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -221,20 +260,24 @@ def leave(self, node, *args): def test_allows_a_named_functions_visitor_api(): + # type: () -> None visited = [] ast = parse('{ a, b { x }, c }') class TestVisitor(Visitor): def enter_Name(self, node, *args): + # type: (Name, *Any) -> None visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) def enter_SelectionSet(self, node, *args): + # type: (SelectionSet, *Any) -> None visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) def leave_SelectionSet(self, node, *args): + # type: (SelectionSet, *Any) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -253,18 +296,21 @@ def leave_SelectionSet(self, node, *args): def test_visits_kitchen_sink(): + # type: () -> None visited = [] ast = parse(KITCHEN_SINK) class TestVisitor(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> None kind = parent and type(parent).__name__ if kind == 'list': kind = None visited.append(['enter', type(node).__name__, key, kind]) def leave(self, node, key, parent, *args): + # type: (Any, Union[int, str], Any, *List[Any]) -> None kind = parent and type(parent).__name__ if kind == 'list': kind = None @@ -574,18 +620,26 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_skipping_a_subtree(): + # type: () -> None visited = [] ast = parse('{ a, b { x }, c }') class TestVisitor(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) if type(node).__name__ == 'Field' and node.name.value == 'b': return False - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name, SelectionSet] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field, OperationDefinition] + *args # type: List[Any] + ): + # type: (...) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -610,21 +664,35 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_skipping_different_subtrees(): + # type: () -> None visited = [] ast = parse('{ a { x }, b { y} }') class TestVisitor(Visitor): def __init__(self, name): + # type: (str) -> None self.name = name - def enter(self, node, key, parent, *args): + def enter(self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + key, # type: Union[None, int, str] + parent, # type: Union[List[OperationDefinition], None, OperationDefinition] + *args # type: Any + ): + # type: (...) -> Optional[Any] visited.append(["no-{}".format(self.name), 'enter', type(node).__name__, getattr(node, 'value', None)]) if type(node).__name__ == 'Field' and node.name.value == self.name: return False - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name, SelectionSet] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> None visited.append(["no-{}".format(self.name), 'leave', type(node).__name__, getattr(node, 'value', None)]) @@ -668,16 +736,24 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_early_exit_while_visiting(): + # type: () -> None visited = [] ast = parse('{ a, b { x }, c }') class TestVisitor(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> None visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> Optional[object] visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) if type(node).__name__ == 'Name' and node.value == 'x': @@ -703,19 +779,33 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_early_exit_from_different_points(): + # type: () -> None visited = [] ast = parse('{ a { y }, b { x } }') class TestVisitor(Visitor): def __init__(self, name): + # type: (str) -> None self.name = name - def enter(self, node, key, parent, *args): + def enter(self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + key, # type: Union[None, int, str] + parent, # type: Union[List[OperationDefinition], None, OperationDefinition] + *args # type: Any + ): + # type: (...) -> None visited.append(["break-{}".format(self.name), 'enter', type(node).__name__, getattr(node, 'value', None)]) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> Optional[Any] visited.append(["break-{}".format(self.name), 'leave', type(node).__name__, getattr(node, 'value', None)]) if type(node).__name__ == 'Field' and node.name.value == self.name: @@ -763,22 +853,31 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_for_editing_on_enter(): + # type: () -> None visited = [] ast = parse('{ a, b, c { a, b, c } }', no_location=True) class TestVisitor1(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] if type(node).__name__ == 'Field' and node.name.value == 'b': return REMOVE class TestVisitor2(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> None visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -816,22 +915,36 @@ def leave(self, node, key, parent, *args): def test_visits_in_pararell_allows_for_editing_on_leave(): + # type: () -> None visited = [] ast = parse('{ a, b, c { a, b, c } }', no_location=True) class TestVisitor1(Visitor): - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> Optional[Falsey] if type(node).__name__ == 'Field' and node.name.value == 'b': return REMOVE class TestVisitor2(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> None visited.append( ['enter', type(node).__name__, getattr(node, 'value', None)]) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): + # type: (...) -> None visited.append( ['leave', type(node).__name__, getattr(node, 'value', None)]) @@ -875,6 +988,7 @@ def leave(self, node, key, parent, *args): def test_visits_with_typeinfo_maintains_type_info_during_visit(): + # type: () -> None visited = [] ast = parse('{ human(id: 4) { name, pets { name }, unknown } }') @@ -883,6 +997,7 @@ def test_visits_with_typeinfo_maintains_type_info_during_visit(): class TestVisitor(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() @@ -895,7 +1010,13 @@ def enter(self, node, key, parent, *args): str(input_type) if input_type else None ]) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Argument, IntValue, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Argument], Argument, Field] + *args # type: List[Any] + ): + # type: (...) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() @@ -950,6 +1071,7 @@ def leave(self, node, key, parent, *args): def test_visits_with_typeinfo_maintains_type_info_during_edit(): + # type: () -> None visited = [] ast = parse('{ human(id: 4) { name, pets }, alien }') @@ -958,6 +1080,7 @@ def test_visits_with_typeinfo_maintains_type_info_during_edit(): class TestVisitor(Visitor): def enter(self, node, key, parent, *args): + # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() @@ -982,7 +1105,13 @@ def enter(self, node, key, parent, *args): ) ) - def leave(self, node, key, parent, *args): + def leave(self, + node, # type: Union[Argument, IntValue, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Argument], Argument, Field] + *args # type: List[Any] + ): + # type: (...) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() diff --git a/graphql/language/tests/test_visitor_meta.py b/graphql/language/tests/test_visitor_meta.py index 3e0dd4e1..19890ad3 100644 --- a/graphql/language/tests/test_visitor_meta.py +++ b/graphql/language/tests/test_visitor_meta.py @@ -3,6 +3,7 @@ def test_visitor_meta_creates_enter_and_leave_handlers(): + # type: () -> None class MyVisitor(Visitor): def enter_OperationDefinition(self): @@ -16,6 +17,7 @@ def leave_OperationDefinition(self): def test_visitor_inherits_parent_definitions(): + # type: () -> None class MyVisitor(Visitor): def enter_OperationDefinition(self): diff --git a/graphql/language/visitor.py b/graphql/language/visitor.py index a77c36e9..d5eda74e 100644 --- a/graphql/language/visitor.py +++ b/graphql/language/visitor.py @@ -5,13 +5,20 @@ from . import ast from .visitor_meta import QUERY_DOCUMENT_KEYS, VisitorMeta +if False: + from typing import Any, List, Optional, Union, Tuple, Dict + from ..utils.type_info import TypeInfo + from ..validation.validation import UsageVisitor + from .ast import Node, Document, OperationDefinition + from .printer import PrintingVisitor -class Falsey(object): +class Falsey(object): def __nonzero__(self): return False def __bool__(self): + # type: () -> bool return False @@ -20,9 +27,10 @@ def __bool__(self): class Stack(object): - __slots__ = 'in_array', 'index', 'keys', 'edits', 'prev' + __slots__ = "in_array", "index", "keys", "edits", "prev" def __init__(self, in_array, index, keys, edits, prev): + # type: (bool, int, Any, List[Tuple[str, str]], Optional[Stack]) -> None self.in_array = in_array self.index = index self.keys = keys @@ -31,16 +39,17 @@ def __init__(self, in_array, index, keys, edits, prev): def visit(root, visitor, key_map=None): + # type: (Union[Node, List[Node]], Visitor, Optional[Dict[Node, Tuple]]) -> Any visitor_keys = key_map or QUERY_DOCUMENT_KEYS - stack = None + stack = None # type: Optional[Stack] in_array = isinstance(root, list) keys = [root] index = -1 - edits = [] - parent = None - path = [] - ancestors = [] + edits = [] # type: List[Tuple[int, Any]] + parent = None # type: Optional[Node] + path = [] # type: List + ancestors = [] # type: List[Node] new_root = root leave = visitor.leave enter = visitor.enter @@ -60,8 +69,7 @@ def visit(root, visitor, key_map=None): if is_edited: if in_array: - node = list(node) - + node = list(node) # type: ignore else: node = copy(node) edit_offset = 0 @@ -70,7 +78,7 @@ def visit(root, visitor, key_map=None): edit_key -= edit_offset if in_array and edit_value is REMOVE: - node.pop(edit_key) + node.pop(edit_key) # type: ignore edit_offset += 1 else: @@ -78,13 +86,13 @@ def visit(root, visitor, key_map=None): node[edit_key] = edit_value else: - setattr(node, edit_key, edit_value) + setattr(node, edit_key, edit_value) # type: ignore - index = stack.index - keys = stack.keys - edits = stack.edits - in_array = stack.in_array - stack = stack.prev + index = stack.index # type: ignore + keys = stack.keys # type: ignore + edits = stack.edits # type: ignore + in_array = stack.in_array # type: ignore + stack = stack.prev # type: ignore else: if parent: @@ -97,7 +105,7 @@ def visit(root, visitor, key_map=None): else: key = None - node = new_root + node = new_root # type: ignore if node is REMOVE or node is None: continue @@ -108,7 +116,7 @@ def visit(root, visitor, key_map=None): result = None if not isinstance(node, list): - assert isinstance(node, ast.Node), 'Invalid AST Node: ' + repr(node) + assert isinstance(node, ast.Node), "Invalid AST Node: " + repr(node) if is_leaving: result = leave(node, key, parent, path, ancestors) @@ -162,25 +170,50 @@ def visit(root, visitor, key_map=None): class Visitor(object): __slots__ = () - def enter(self, node, key, parent, path, ancestors): + def enter( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] method = self._get_enter_handler(type(node)) if method: return method(self, node, key, parent, path, ancestors) - def leave(self, node, key, parent, path, ancestors): + def leave( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] method = self._get_leave_handler(type(node)) if method: return method(self, node, key, parent, path, ancestors) class ParallelVisitor(Visitor): - __slots__ = 'skipping', 'visitors' + __slots__ = "skipping", "visitors" def __init__(self, visitors): + # type: (List[Any]) -> None self.visitors = visitors self.skipping = [None] * len(visitors) - def enter(self, node, key, parent, path, ancestors): + def enter( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] for i, visitor in enumerate(self.visitors): if not self.skipping[i]: result = visitor.enter(node, key, parent, path, ancestors) @@ -191,7 +224,15 @@ def enter(self, node, key, parent, path, ancestors): elif result is not None: return result - def leave(self, node, key, parent, path, ancestors): + def leave( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] for i, visitor in enumerate(self.visitors): if not self.skipping[i]: result = visitor.leave(node, key, parent, path, ancestors) @@ -204,13 +245,26 @@ def leave(self, node, key, parent, path, ancestors): class TypeInfoVisitor(Visitor): - __slots__ = 'visitor', 'type_info' - - def __init__(self, type_info, visitor): + __slots__ = "visitor", "type_info" + + def __init__( + self, + type_info, # type: TypeInfo + visitor, # type: Union[TestVisitor, ParallelVisitor, UsageVisitor] + ): + # type: (...) -> None self.type_info = type_info self.visitor = visitor - def enter(self, node, key, parent, path, ancestors): + def enter( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] self.type_info.enter(node) result = self.visitor.enter(node, key, parent, path, ancestors) if result is not None: @@ -219,7 +273,15 @@ def enter(self, node, key, parent, path, ancestors): self.type_info.enter(result) return result - def leave(self, node, key, parent, path, ancestors): + def leave( + self, + node, # type: Any + key, # type: Union[None, int, str] + parent, # type: Any + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] result = self.visitor.leave(node, key, parent, path, ancestors) self.type_info.leave(node) return result diff --git a/graphql/pyutils/cached_property.py b/graphql/pyutils/cached_property.py index b5db6d48..e1e0fc75 100644 --- a/graphql/pyutils/cached_property.py +++ b/graphql/pyutils/cached_property.py @@ -1,3 +1,7 @@ +if False: + from typing import Any + + class cached_property(object): """ A property that is only computed once per instance and then replaces itself with an ordinary attribute. Deleting the attribute resets the @@ -7,10 +11,11 @@ class cached_property(object): """ def __init__(self, func): - self.__doc__ = getattr(func, '__doc__') + self.__doc__ = getattr(func, "__doc__") self.func = func def __get__(self, obj, cls): + # type: (Any, type) -> Any if obj is None: return self value = obj.__dict__[self.func.__name__] = self.func(obj) diff --git a/graphql/pyutils/contain_subset.py b/graphql/pyutils/contain_subset.py index 6c34936d..5b8f3f58 100644 --- a/graphql/pyutils/contain_subset.py +++ b/graphql/pyutils/contain_subset.py @@ -1,13 +1,19 @@ +if False: + from typing import Any, Dict + obj = (dict, list, tuple) def contain_subset(expected, actual): + # type: (Any, Any) -> bool t_actual = type(actual) t_expected = type(expected) actual_is_dict = issubclass(t_actual, dict) expected_is_dict = issubclass(t_expected, dict) both_dicts = actual_is_dict and expected_is_dict - if not(both_dicts) and not(issubclass(t_actual, t_expected) or issubclass(t_expected, t_actual)): + if not (both_dicts) and not ( + issubclass(t_actual, t_expected) or issubclass(t_expected, t_actual) + ): return False if not isinstance(expected, obj) or expected is None: return expected == actual @@ -16,7 +22,7 @@ def contain_subset(expected, actual): if isinstance(expected, list): aa = actual[:] return all([any([contain_subset(exp, act) for act in aa]) for exp in expected]) - for key in expected.keys(): + for key in expected.keys(): # type: ignore eo = expected[key] ao = actual.get(key) if isinstance(eo, obj) and eo is not None and ao is not None: diff --git a/graphql/pyutils/default_ordered_dict.py b/graphql/pyutils/default_ordered_dict.py index e82a1be1..273e62fd 100644 --- a/graphql/pyutils/default_ordered_dict.py +++ b/graphql/pyutils/default_ordered_dict.py @@ -1,19 +1,24 @@ import copy from collections import OrderedDict +if False: + from typing import Any, List + class DefaultOrderedDict(OrderedDict): - __slots__ = 'default_factory', + __slots__ = ("default_factory",) # Source: http://stackoverflow.com/a/6190500/562769 def __init__(self, default_factory=None, *a, **kw): + # type: (type, *Any, **Any) -> None if default_factory is not None and not callable(default_factory): - raise TypeError('first argument must be callable') + raise TypeError("first argument must be callable") OrderedDict.__init__(self, *a, **kw) self.default_factory = default_factory def __missing__(self, key): + # type: (str) -> List if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() @@ -23,7 +28,7 @@ def __reduce__(self): if self.default_factory is None: args = tuple() else: - args = self.default_factory, + args = (self.default_factory,) return type(self), args, None, None, iter(self.items()) def copy(self): @@ -36,5 +41,7 @@ def __deepcopy__(self, memo): return self.__class__(self.default_factory, copy.deepcopy(list(self.items()))) def __repr__(self): - return 'DefaultOrderedDict(%s, %s)' % (self.default_factory, - OrderedDict.__repr__(self)[19:-1]) + return "DefaultOrderedDict(%s, %s)" % ( + self.default_factory, + OrderedDict.__repr__(self)[19:-1], + ) diff --git a/graphql/pyutils/ordereddict.py b/graphql/pyutils/ordereddict.py index ff341a4c..29633537 100644 --- a/graphql/pyutils/ordereddict.py +++ b/graphql/pyutils/ordereddict.py @@ -1,7 +1,7 @@ try: # Try to load the Cython performant OrderedDict (C) # as is more performant than collections.OrderedDict (Python) - from cyordereddict import OrderedDict + from cyordereddict import OrderedDict # type: ignore except ImportError: from collections import OrderedDict diff --git a/graphql/pyutils/pair_set.py b/graphql/pyutils/pair_set.py index 0af547a9..f880ec3b 100644 --- a/graphql/pyutils/pair_set.py +++ b/graphql/pyutils/pair_set.py @@ -1,8 +1,13 @@ +if False: + from typing import Dict, Any + + class PairSet(object): - __slots__ = '_data', + __slots__ = ("_data",) def __init__(self): - self._data = {} + # type: () -> None + self._data = {} # type: Dict[str, Any] def __contains__(self, item): return self.has(item[0], item[1], item[2]) diff --git a/graphql/pyutils/tests/test_contain_subset.py b/graphql/pyutils/tests/test_contain_subset.py index 11b29cfc..361e1525 100644 --- a/graphql/pyutils/tests/test_contain_subset.py +++ b/graphql/pyutils/tests/test_contain_subset.py @@ -1,127 +1,79 @@ from ..contain_subset import contain_subset -plain_object = { - 'a': 'b', - 'c': 'd' -} - -complex_object = { - 'a': 'b', - 'c': 'd', - 'e': { - 'foo': 'bar', - 'baz': { - 'qux': 'quux' - } - } -} +plain_object = {"a": "b", "c": "d"} + +complex_object = {"a": "b", "c": "d", "e": {"foo": "bar", "baz": {"qux": "quux"}}} def test_plain_object_should_pass_for_smaller_object(): - assert contain_subset({'a': 'b'}, plain_object) + # type: () -> None + assert contain_subset({"a": "b"}, plain_object) def test_plain_object_should_pass_for_same_object(): - assert contain_subset({ - 'a': 'b', - 'c': 'd' - }, plain_object) + # type: () -> None + assert contain_subset({"a": "b", "c": "d"}, plain_object) def test_plain_object_should_reject_for_similar_object(): - assert not contain_subset({ - 'a': 'notB', - 'c': 'd' - }, plain_object) + # type: () -> None + assert not contain_subset({"a": "notB", "c": "d"}, plain_object) def test_complex_object_should_pass_for_smaller_object(): - assert contain_subset({ - 'a': 'b', - 'e': { - 'foo': 'bar' - } - }, complex_object) + # type: () -> None + assert contain_subset({"a": "b", "e": {"foo": "bar"}}, complex_object) def test_complex_object_should_pass_for_smaller_object_other(): - assert contain_subset({ - 'e': { - 'foo': 'bar', - 'baz': { - 'qux': 'quux' - } - } - }, complex_object) + # type: () -> None + assert contain_subset({"e": {"foo": "bar", "baz": {"qux": "quux"}}}, complex_object) def test_complex_object_should_pass_for_same_object(): - assert contain_subset({ - 'a': 'b', - 'c': 'd', - 'e': { - 'foo': 'bar', - 'baz': { - 'qux': 'quux' - } - } - }, complex_object) + # type: () -> None + assert contain_subset( + {"a": "b", "c": "d", "e": {"foo": "bar", "baz": {"qux": "quux"}}}, + complex_object, + ) def test_complex_object_should_reject_for_similar_object(): - assert not contain_subset({ - 'e': { - 'foo': 'bar', - 'baz': { - 'qux': 'notAQuux' - } - } - }, complex_object) - - -def test_circular_objects_should_contain_subdocument(): - obj = {} - obj['arr'] = [obj, obj] - obj['arr'].append(obj['arr']) - obj['obj'] = obj - - assert contain_subset({ - 'arr': [ - {'arr': []}, - {'arr': []}, - [ - {'arr': []}, - {'arr': []} - ] - ] - }, obj) - - -def test_circular_objects_should_not_contain_similardocument(): - obj = {} - obj['arr'] = [obj, obj] - obj['arr'].append(obj['arr']) - obj['obj'] = obj - - assert not contain_subset({ - 'arr': [ - {'arr': ['just random field']}, - {'arr': []}, - [ - {'arr': []}, - {'arr': []} - ] - ] - }, obj) + # type: () -> None + assert not contain_subset( + {"e": {"foo": "bar", "baz": {"qux": "notAQuux"}}}, complex_object + ) + + +# def test_circular_objects_should_contain_subdocument(): +# obj = {} +# obj["arr"] = [obj, obj] +# obj["arr"].append(obj["arr"]) +# obj["obj"] = obj + +# assert contain_subset( +# {"arr": [{"arr": []}, {"arr": []}, [{"arr": []}, {"arr": []}]]}, obj +# ) + + +# def test_circular_objects_should_not_contain_similardocument(): +# obj = {} +# obj["arr"] = [obj, obj] +# obj["arr"].append(obj["arr"]) +# obj["obj"] = obj + +# assert not contain_subset( +# { +# "arr": [ +# {"arr": ["just random field"]}, +# {"arr": []}, +# [{"arr": []}, {"arr": []}], +# ] +# }, +# obj, +# ) def test_should_contain_others(): - obj = { - 'elems': [{'a': 'b', 'c': 'd', 'e': 'f'}, {'g': 'h'}] - } - assert contain_subset({ - 'elems': [{ - 'g': 'h' - }, {'a': 'b', 'e': 'f'} - ] - }, obj) + obj = {"elems": [{"a": "b", "c": "d", "e": "f"}, {"g": "h"}]} + assert contain_subset({"elems": [{"g": "h"}, {"a": "b", "e": "f"}]}, obj) diff --git a/graphql/type/definition.py b/graphql/type/definition.py index 64dedac7..ecb4f4ed 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -7,61 +7,65 @@ from ..utils.assert_valid_name import assert_valid_name from ..utils.undefined import Undefined +if False: + from typing import List, Dict, Any, Callable, Optional, Union, Type + def is_type(type): - return isinstance(type, ( - GraphQLScalarType, - GraphQLObjectType, - GraphQLInterfaceType, - GraphQLUnionType, - GraphQLEnumType, - GraphQLInputObjectType, - GraphQLList, - GraphQLNonNull - )) + # type: (Any) -> bool + return isinstance( + type, + ( + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + ), + ) def is_input_type(type): + # type: (Any) -> bool named_type = get_named_type(type) - return isinstance(named_type, ( - GraphQLScalarType, - GraphQLEnumType, - GraphQLInputObjectType, - )) + return isinstance( + named_type, (GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType) + ) def is_output_type(type): + # type: (Any) -> bool named_type = get_named_type(type) - return isinstance(named_type, ( - GraphQLScalarType, - GraphQLObjectType, - GraphQLInterfaceType, - GraphQLUnionType, - GraphQLEnumType - )) + return isinstance( + named_type, + ( + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + ), + ) def is_leaf_type(type): - return isinstance(type, ( - GraphQLScalarType, - GraphQLEnumType, - )) + # type: (Any) -> bool + return isinstance(type, (GraphQLScalarType, GraphQLEnumType)) def is_composite_type(type): + # type: (Any) -> bool named_type = get_named_type(type) - return isinstance(named_type, ( - GraphQLObjectType, - GraphQLInterfaceType, - GraphQLUnionType, - )) + return isinstance( + named_type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType) + ) def is_abstract_type(type): - return isinstance(type, ( - GraphQLInterfaceType, - GraphQLUnionType - )) + return isinstance(type, (GraphQLInterfaceType, GraphQLUnionType)) def get_nullable_type(type): @@ -71,6 +75,7 @@ def get_nullable_type(type): def get_named_type(type): + # type: (Optional[GraphQLType]) -> Optional[GraphQLType] unmodified_type = type while isinstance(unmodified_type, (GraphQLList, GraphQLNonNull)): unmodified_type = unmodified_type.of_type @@ -79,12 +84,14 @@ def get_named_type(type): class GraphQLType(object): - __slots__ = 'name', + __slots__ = ("name",) def __str__(self): + # type: () -> str return self.name def is_same_type(self, other): + # type: (GraphQLObjectType) -> bool return self.__class__ is other.__class__ and self.name == other.name @@ -109,10 +116,17 @@ def coerce_odd(value): OddType = GraphQLScalarType(name='Odd', serialize=coerce_odd) """ - __slots__ = 'name', 'description', 'serialize', 'parse_value', 'parse_literal' - - def __init__(self, name, description=None, serialize=None, parse_value=None, parse_literal=None): - assert name, 'Type must be named.' + __slots__ = "name", "description", "serialize", "parse_value", "parse_literal" + + def __init__( + self, + name, + description=None, + serialize=None, + parse_value=None, + parse_literal=None, + ): + assert name, "Type must be named." assert_valid_name(name) self.name = name self.description = description @@ -120,12 +134,14 @@ def __init__(self, name, description=None, serialize=None, parse_value=None, par assert callable(serialize), ( '{} must provide "serialize" function. If this custom Scalar is ' 'also used as an input type, ensure "parse_value" and "parse_literal" ' - 'functions are also provided.' + "functions are also provided." ).format(self) if parse_value is not None or parse_literal is not None: - assert callable(parse_value) and callable(parse_literal), ( - '{} must provide both "parse_value" and "parse_literal" functions.'.format(self) + assert callable(parse_value) and callable( + parse_literal + ), '{} must provide both "parse_value" and "parse_literal" functions.'.format( + self ) self.serialize = serialize @@ -133,6 +149,7 @@ def __init__(self, name, description=None, serialize=None, parse_value=None, par self.parse_literal = parse_literal or none_func def __str__(self): + # type: () -> str return self.name @@ -163,14 +180,24 @@ class GraphQLObjectType(GraphQLType): }) """ - def __init__(self, name, fields, interfaces=None, is_type_of=None, description=None): - assert name, 'Type must be named.' + def __init__( + self, + name, # type: str + fields, # type: Union[Callable[[], Dict[str, GraphQLField]], Dict[str, GraphQLField]] + interfaces=None, # type: Optional[List[GraphQLInterfaceType]] + is_type_of=None, # type: Optional[Callable] + description=None, # type: Optional[Any] + ): + # type: (...) -> None + assert name, "Type must be named." assert_valid_name(name) self.name = name self.description = description if is_type_of is not None: - assert callable(is_type_of), '{} must provide "is_type_of" as a function.'.format(self) + assert callable( + is_type_of + ), '{} must provide "is_type_of" as a function.'.format(self) self.is_type_of = is_type_of self._fields = fields @@ -179,33 +206,40 @@ def __init__(self, name, fields, interfaces=None, is_type_of=None, description=N @cached_property def fields(self): + # type: () -> Dict[str, GraphQLField] return define_field_map(self, self._fields) @cached_property def interfaces(self): + # type: () -> List[GraphQLInterfaceType] return define_interfaces(self, self._provided_interfaces) -def define_field_map(type, field_map): +def define_field_map( + type, # type: Union[GraphQLInterfaceType, GraphQLObjectType] + field_map, # type: Union[Callable, Dict[str, GraphQLField], OrderedDict] +): + # type: (...) -> OrderedDict if callable(field_map): field_map = field_map() assert isinstance(field_map, collections.Mapping) and len(field_map) > 0, ( - '{} fields must be a mapping (dict / OrderedDict) with field names as keys or a ' - 'function which returns such a mapping.' + "{} fields must be a mapping (dict / OrderedDict) with field names as keys or a " + "function which returns such a mapping." ).format(type) for field_name, field in field_map.items(): assert_valid_name(field_name) - assert isinstance(field, GraphQLField), ( - '{}.{} must be an instance of GraphQLField.'.format(type, field_name) - ) - field_args = getattr(field, 'args', None) + assert isinstance( + field, GraphQLField + ), "{}.{} must be an instance of GraphQLField.".format(type, field_name) + field_args = getattr(field, "args", None) if field_args: - assert isinstance(field_args, collections.Mapping), ( - '{}.{} args must be a mapping (dict / OrderedDict) with argument names as keys.'.format(type, - field_name) + assert isinstance( + field_args, collections.Mapping + ), "{}.{} args must be a mapping (dict / OrderedDict) with argument names as keys.".format( + type, field_name ) for arg_name, arg in field_args.items(): @@ -214,37 +248,53 @@ def define_field_map(type, field_map): return OrderedDict(field_map) -def define_interfaces(type, interfaces): +def define_interfaces( + type, # type: GraphQLObjectType + interfaces, # type: Optional[List[GraphQLInterfaceType]] +): + # type: (...) -> List[GraphQLInterfaceType] if callable(interfaces): interfaces = interfaces() if interfaces is None: interfaces = [] - assert isinstance(interfaces, (list, tuple)), ( - '{} interfaces must be a list/tuple or a function which returns a list/tuple.'.format(type) + assert isinstance( + interfaces, (list, tuple) + ), "{} interfaces must be a list/tuple or a function which returns a list/tuple.".format( + type ) for interface in interfaces: - assert isinstance(interface, GraphQLInterfaceType), ( - '{} may only implement Interface types, it cannot implement: {}.'.format(type, interface) + assert isinstance( + interface, GraphQLInterfaceType + ), "{} may only implement Interface types, it cannot implement: {}.".format( + type, interface ) if not callable(interface.resolve_type): assert callable(type.is_type_of), ( 'Interface Type {} does not provide a "resolve_type" function ' 'and implementing Type {} does not provide a "is_type_of" ' - 'function. There is no way to resolve this implementing type ' - 'during execution.' + "function. There is no way to resolve this implementing type " + "during execution." ).format(interface, type) return interfaces class GraphQLField(object): - __slots__ = 'type', 'args', 'resolver', 'deprecation_reason', 'description' - - def __init__(self, type, args=None, resolver=None, deprecation_reason=None, description=None): + __slots__ = "type", "args", "resolver", "deprecation_reason", "description" + + def __init__( + self, + type, # type: Any + args=None, # type: Optional[Dict[str, GraphQLArgument]] + resolver=None, # type: Optional[Callable] + deprecation_reason=None, # type: Optional[Any] + description=None, # type: Optional[Any] + ): + # type: (...) -> None self.type = type self.args = args or OrderedDict() self.resolver = resolver @@ -252,18 +302,17 @@ def __init__(self, type, args=None, resolver=None, deprecation_reason=None, desc self.description = description def __eq__(self, other): - return ( - self is other or ( - isinstance(other, GraphQLField) and - self.type == other.type and - self.args == other.args and - self.resolver == other.resolver and - self.deprecation_reason == other.deprecation_reason and - self.description == other.description - ) + return self is other or ( + isinstance(other, GraphQLField) + and self.type == other.type + and self.args == other.args + and self.resolver == other.resolver + and self.deprecation_reason == other.deprecation_reason + and self.description == other.description ) def __hash__(self): + # type: () -> int return id(self) @property @@ -272,23 +321,29 @@ def is_deprecated(self): class GraphQLArgument(object): - __slots__ = 'type', 'default_value', 'description', 'out_name' - - def __init__(self, type, default_value=None, description=None, out_name=None): + __slots__ = "type", "default_value", "description", "out_name" + + def __init__( + self, + # type: Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLScalarType] + type, + default_value=None, # type: Optional[Any] + description=None, # type: Optional[Any] + out_name=None, # type: Optional[str] + ): + # type: (...) -> None self.type = type self.default_value = default_value self.description = description self.out_name = out_name def __eq__(self, other): - return ( - self is other or ( - isinstance(other, GraphQLArgument) and - self.type == other.type and - self.default_value == other.default_value and - self.description == other.description and - self.out_name == other.out_name - ) + return self is other or ( + isinstance(other, GraphQLArgument) + and self.type == other.type + and self.default_value == other.default_value + and self.description == other.description + and self.out_name == other.out_name ) def __hash__(self): @@ -310,20 +365,30 @@ class GraphQLInterfaceType(GraphQLType): }) """ - def __init__(self, name, fields=None, resolve_type=None, description=None): - assert name, 'Type must be named.' + def __init__( + self, + name, # type: str + fields=None, # type: Union[Callable[[], Dict[str, GraphQLField]], Dict[str, GraphQLField]] + resolve_type=None, # type: Optional[Callable] + description=None, # type: Optional[Any] + ): + # type: (...) -> None + assert name, "Type must be named." assert_valid_name(name) self.name = name self.description = description if resolve_type is not None: - assert callable(resolve_type), '{} must provide "resolve_type" as a function.'.format(self) + assert callable( + resolve_type + ), '{} must provide "resolve_type" as a function.'.format(self) self.resolve_type = resolve_type self._fields = fields @cached_property def fields(self): + # type: () -> Dict[str, GraphQLField] return define_field_map(self, self._fields) @@ -346,42 +411,61 @@ def resolve_type(self, value): return CatType() """ - def __init__(self, name, types=None, resolve_type=None, description=None): - assert name, 'Type must be named.' + def __init__( + self, + name, # type: str + types=None, # type: List[GraphQLObjectType] + resolve_type=None, # type: Optional[Callable] + description=None, # type: Optional[Any] + ): + # type: (...) -> None + assert name, "Type must be named." assert_valid_name(name) self.name = name self.description = description if resolve_type is not None: - assert callable(resolve_type), '{} must provide "resolve_type" as a function.'.format(self) + assert callable( + resolve_type + ), '{} must provide "resolve_type" as a function.'.format(self) self.resolve_type = resolve_type self._types = types @cached_property def types(self): + # type: () -> List[GraphQLObjectType] return define_types(self, self._types) -def define_types(union_type, types): +# fmt: off +def define_types( + union_type, # type: GraphQLUnionType + types, # type: List[GraphQLObjectType] +): + # type: (...) -> List[GraphQLObjectType] + # fmt: on if callable(types): types = types() - assert isinstance(types, (list, tuple)) and len( - types) > 0, 'Must provide types for Union {}.'.format(union_type.name) + assert ( + isinstance(types, (list, tuple)) and len(types) > 0 + ), "Must provide types for Union {}.".format(union_type.name) has_resolve_type_fn = callable(union_type.resolve_type) for type in types: - assert isinstance(type, GraphQLObjectType), ( - '{} may only contain Object types, it cannot contain: {}.'.format(union_type, type) + assert isinstance( + type, GraphQLObjectType + ), "{} may only contain Object types, it cannot contain: {}.".format( + union_type, type ) if not has_resolve_type_fn: assert callable(type.is_type_of), ( 'Union Type {} does not provide a "resolve_type" function ' 'and possible Type {} does not provide a "is_type_of" ' - 'function. There is no way to resolve this possible type ' - 'during execution.' + "function. There is no way to resolve this possible type " + "during execution." ).format(union_type, type) return types @@ -408,7 +492,7 @@ class GraphQLEnumType(GraphQLType): """ def __init__(self, name, values, description=None): - assert name, 'Type must provide name.' + assert name, "Type must provide name." assert_valid_name(name) self.name = name self.description = description @@ -422,6 +506,7 @@ def get_value(self, name): return self._name_lookup.get(name) def serialize(self, value): + # type: (str) -> str if isinstance(value, collections.Hashable): enum_value = self._value_lookup.get(value) @@ -448,6 +533,7 @@ def parse_literal(self, value_ast): @cached_property def _value_lookup(self): + # type: () -> Dict[str, GraphQLEnumValue] return {value.value: value for value in self.values} @cached_property @@ -456,8 +542,10 @@ def _name_lookup(self): def define_enum_values(type, value_map): - assert isinstance(value_map, collections.Mapping) and len(value_map) > 0, ( - '{} values must be a mapping (dict / OrderedDict) with value names as keys.'.format(type) + assert ( + isinstance(value_map, collections.Mapping) and len(value_map) > 0 + ), "{} values must be a mapping (dict / OrderedDict) with value names as keys.".format( + type ) values = [] @@ -466,8 +554,10 @@ def define_enum_values(type, value_map): for value_name, value in value_map.items(): assert_valid_name(value_name) - assert isinstance(value, GraphQLEnumValue), ( - '{}.{} must be an instance of GraphQLEnumValue, but got: {}'.format(type, value_name, value) + assert isinstance( + value, GraphQLEnumValue + ), "{}.{} must be an instance of GraphQLEnumValue, but got: {}".format( + type, value_name, value ) value = copy.copy(value) value.name = value_name @@ -480,9 +570,11 @@ def define_enum_values(type, value_map): class GraphQLEnumValue(object): - __slots__ = 'name', 'value', 'deprecation_reason', 'description' + __slots__ = "name", "value", "deprecation_reason", "description" - def __init__(self, value=Undefined, deprecation_reason=None, description=None, name=None): + def __init__( + self, value=Undefined, deprecation_reason=None, description=None, name=None + ): self.name = name self.value = value self.deprecation_reason = deprecation_reason @@ -493,14 +585,12 @@ def is_deprecated(self): return bool(self.deprecation_reason) def __eq__(self, other): - return ( - self is other or ( - isinstance(other, GraphQLEnumValue) and - self.name == other.name and - self.value == other.value and - self.deprecation_reason == other.deprecation_reason and - self.description == other.description - ) + return self is other or ( + isinstance(other, GraphQLEnumValue) + and self.name == other.name + and self.value == other.value + and self.deprecation_reason == other.deprecation_reason + and self.description == other.description ) @@ -526,8 +616,14 @@ class GeoPoint(GraphQLInputObjectType): } """ - def __init__(self, name, fields, description=None, container_type=None): - assert name, 'Type must be named.' + def __init__(self, + name, # type: str + fields, # type: Union[Callable[[], Dict[str, GraphQLInputObjectField]], Dict[str, GraphQLInputObjectField]] + description=None, # type: Optional[str] + container_type=None, # type: Type[Dict[str, Any]] + ): + # type: (...) -> None + assert name, "Type must be named." self.name = name self.description = description if container_type is None: @@ -537,20 +633,23 @@ def __init__(self, name, fields, description=None, container_type=None): self._fields = fields def create_container(self, data): + # type: (Dict[str, Any]) -> Dict[str, Any] return self.container_type(data) @cached_property def fields(self): + # type: () -> Dict[str, GraphQLInputObjectField] return self._define_field_map() def _define_field_map(self): + # type: () -> OrderedDict fields = self._fields if callable(fields): fields = fields() assert isinstance(fields, collections.Mapping) and len(fields) > 0, ( - '{} fields must be a mapping (dict / OrderedDict) with field names as keys or a ' - 'function which returns such a mapping.' + "{} fields must be a mapping (dict / OrderedDict) with field names as keys or a " + "function which returns such a mapping." ).format(self) if not isinstance(fields, (collections.OrderedDict, OrderedDict)): fields = OrderedDict(sorted(list(fields.items()))) @@ -562,22 +661,28 @@ def _define_field_map(self): class GraphQLInputObjectField(object): - __slots__ = 'type', 'default_value', 'description', 'out_name' - - def __init__(self, type, default_value=None, description=None, out_name=None): + __slots__ = "type", "default_value", "description", "out_name" + + def __init__( + self, + # type: Union[GraphQLInputObjectType, GraphQLScalarType] + type, + default_value=None, # type: Optional[Any] + description=None, # type: Optional[Any] + out_name=None, # type: str + ): + # type: (...) -> None self.type = type self.default_value = default_value self.description = description self.out_name = out_name def __eq__(self, other): - return ( - self is other or ( - isinstance(other, GraphQLInputObjectField) and - self.type == other.type and - self.description == other.description and - self.out_name == other.out_name - ) + return self is other or ( + isinstance(other, GraphQLInputObjectField) + and self.type == other.type + and self.description == other.description + and self.out_name == other.out_name ) @@ -599,17 +704,24 @@ def get_fields(self): 'children': GraphQLField(GraphQLList(PersonType())), } """ - __slots__ = 'of_type', + + __slots__ = ("of_type",) def __init__(self, type): - assert is_type(type), 'Can only create List of a GraphQLType but got: {}.'.format(type) + # type: (Any) -> None + assert is_type( + type + ), "Can only create List of a GraphQLType but got: {}.".format(type) self.of_type = type def __str__(self): - return '[' + str(self.of_type) + ']' + # type: () -> str + return "[" + str(self.of_type) + "]" def is_same_type(self, other): - return isinstance(other, GraphQLList) and self.of_type.is_same_type(other.of_type) + return isinstance(other, GraphQLList) and self.of_type.is_same_type( + other.of_type + ) class GraphQLNonNull(GraphQLType): @@ -629,16 +741,26 @@ class RowType(GraphQLObjectType): Note: the enforcement of non-nullability occurs within the executor. """ - __slots__ = 'of_type', - def __init__(self, type): - assert is_type(type) and not isinstance(type, GraphQLNonNull), ( - 'Can only create NonNull of a Nullable GraphQLType but got: {}.'.format(type) - ) + __slots__ = ("of_type",) + + def __init__( + self, + # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType] + type, + ): + # type: (...) -> None + assert is_type(type) and not isinstance( + type, GraphQLNonNull + ), "Can only create NonNull of a Nullable GraphQLType but got: {}.".format(type) self.of_type = type def __str__(self): - return str(self.of_type) + '!' + # type: () -> str + return str(self.of_type) + "!" def is_same_type(self, other): - return isinstance(other, GraphQLNonNull) and self.of_type.is_same_type(other.of_type) + return isinstance(other, GraphQLNonNull) and self.of_type.is_same_type( + other.of_type + ) + diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index 7c44ff75..4a18d785 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -2,194 +2,310 @@ from ..language.printer import print_ast from ..utils.ast_from_value import ast_from_value -from .definition import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue, - GraphQLField, GraphQLInputObjectType, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLScalarType, - GraphQLUnionType) +from .definition import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLUnionType, +) from .directives import DirectiveLocation from .scalars import GraphQLBoolean, GraphQLString -InputField = namedtuple('InputField', ['name', 'description', 'type', 'default_value']) -Field = namedtuple('Field', ['name', 'type', 'description', 'args', 'deprecation_reason']) +if False: + from ..execution.base import ResolveInfo + from typing import Union, List, Optional, Any + +InputField = namedtuple("InputField", ["name", "description", "type", "default_value"]) +Field = namedtuple( + "Field", ["name", "type", "description", "args", "deprecation_reason"] +) def input_fields_to_list(input_fields): fields = [] for field_name, field in input_fields.items(): - fields.append(InputField( - name=field_name, - description=field.description, - type=field.type, - default_value=field.default_value)) + fields.append( + InputField( + name=field_name, + description=field.description, + type=field.type, + default_value=field.default_value, + ) + ) return fields __Schema = GraphQLObjectType( - '__Schema', - description='A GraphQL Schema defines the capabilities of a GraphQL server. It ' - 'exposes all available types and directives on the server, as well as ' - 'the entry points for query, mutation and subscription operations.', - fields=lambda: OrderedDict([ - ('types', GraphQLField( - description='A list of all types supported by this server.', - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Type))), - resolver=lambda schema, *_: schema.get_type_map().values(), - )), - ('queryType', GraphQLField( - description='The type that query operations will be rooted at.', - type=GraphQLNonNull(__Type), - resolver=lambda schema, *_: schema.get_query_type(), - )), - ('mutationType', GraphQLField( - description='If this server supports mutation, the type that ' - 'mutation operations will be rooted at.', - type=__Type, - resolver=lambda schema, *_: schema.get_mutation_type(), - )), - ('subscriptionType', GraphQLField( - description='If this server support subscription, the type ' - 'that subscription operations will be rooted at.', - type=__Type, - resolver=lambda schema, *_: schema.get_subscription_type(), - )), - ('directives', GraphQLField( - description='A list of all directives supported by this server.', - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Directive))), - resolver=lambda schema, *_: schema.get_directives(), - )), - ])) + "__Schema", + description="A GraphQL Schema defines the capabilities of a GraphQL server. It " + "exposes all available types and directives on the server, as well as " + "the entry points for query, mutation and subscription operations.", + fields=lambda: OrderedDict( + [ + ( + "types", + GraphQLField( + description="A list of all types supported by this server.", + type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Type))), + resolver=lambda schema, *_: schema.get_type_map().values(), + ), + ), + ( + "queryType", + GraphQLField( + description="The type that query operations will be rooted at.", + type=GraphQLNonNull(__Type), + resolver=lambda schema, *_: schema.get_query_type(), + ), + ), + ( + "mutationType", + GraphQLField( + description="If this server supports mutation, the type that " + "mutation operations will be rooted at.", + type=__Type, + resolver=lambda schema, *_: schema.get_mutation_type(), + ), + ), + ( + "subscriptionType", + GraphQLField( + description="If this server support subscription, the type " + "that subscription operations will be rooted at.", + type=__Type, + resolver=lambda schema, *_: schema.get_subscription_type(), + ), + ), + ( + "directives", + GraphQLField( + description="A list of all directives supported by this server.", + type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Directive))), + resolver=lambda schema, *_: schema.get_directives(), + ), + ), + ] + ), +) _on_operation_locations = set(DirectiveLocation.OPERATION_LOCATIONS) _on_fragment_locations = set(DirectiveLocation.FRAGMENT_LOCATIONS) _on_field_locations = set(DirectiveLocation.FIELD_LOCATIONS) __Directive = GraphQLObjectType( - '__Directive', - description='A Directive provides a way to describe alternate runtime execution and ' - 'type validation behavior in a GraphQL document.' - '\n\nIn some cases, you need to provide options to alter GraphQL\'s ' - 'execution behavior in ways field arguments will not suffice, such as ' - 'conditionally including or skipping a field. Directives provide this by ' - 'describing additional information to the executor.', - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLNonNull(GraphQLString))), - ('description', GraphQLField(GraphQLString)), - ('locations', GraphQLField( - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__DirectiveLocation))), - )), - ('args', GraphQLField( - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), - resolver=lambda directive, *args: input_fields_to_list(directive.args), - )), - ('onOperation', GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), - deprecation_reason='Use `locations`.', - resolver=lambda directive, *args: set(directive.locations) & _on_operation_locations, - )), - ('onFragment', GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), - deprecation_reason='Use `locations`.', - resolver=lambda directive, *args: set(directive.locations) & _on_fragment_locations, - )), - ('onField', GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), - deprecation_reason='Use `locations`.', - resolver=lambda directive, *args: set(directive.locations) & _on_field_locations, - )) - ])) + "__Directive", + description="A Directive provides a way to describe alternate runtime execution and " + "type validation behavior in a GraphQL document." + "\n\nIn some cases, you need to provide options to alter GraphQL's " + "execution behavior in ways field arguments will not suffice, such as " + "conditionally including or skipping a field. Directives provide this by " + "describing additional information to the executor.", + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLNonNull(GraphQLString))), + ("description", GraphQLField(GraphQLString)), + ( + "locations", + GraphQLField( + type=GraphQLNonNull( + GraphQLList(GraphQLNonNull(__DirectiveLocation)) + ) + ), + ), + ( + "args", + GraphQLField( + type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), + resolver=lambda directive, *args: input_fields_to_list( + directive.args + ), + ), + ), + ( + "onOperation", + GraphQLField( + type=GraphQLNonNull(GraphQLBoolean), + deprecation_reason="Use `locations`.", + resolver=lambda directive, *args: set(directive.locations) + & _on_operation_locations, + ), + ), + ( + "onFragment", + GraphQLField( + type=GraphQLNonNull(GraphQLBoolean), + deprecation_reason="Use `locations`.", + resolver=lambda directive, *args: set(directive.locations) + & _on_fragment_locations, + ), + ), + ( + "onField", + GraphQLField( + type=GraphQLNonNull(GraphQLBoolean), + deprecation_reason="Use `locations`.", + resolver=lambda directive, *args: set(directive.locations) + & _on_field_locations, + ), + ), + ] + ), +) __DirectiveLocation = GraphQLEnumType( - '__DirectiveLocation', + "__DirectiveLocation", description=( - 'A Directive can be adjacent to many parts of the GraphQL language, a ' + - '__DirectiveLocation describes one such possible adjacencies.' + "A Directive can be adjacent to many parts of the GraphQL language, a " + + "__DirectiveLocation describes one such possible adjacencies." + ), + values=OrderedDict( + [ + ( + "QUERY", + GraphQLEnumValue( + DirectiveLocation.QUERY, + description="Location adjacent to a query operation.", + ), + ), + ( + "MUTATION", + GraphQLEnumValue( + DirectiveLocation.MUTATION, + description="Location adjacent to a mutation operation.", + ), + ), + ( + "SUBSCRIPTION", + GraphQLEnumValue( + DirectiveLocation.SUBSCRIPTION, + description="Location adjacent to a subscription operation.", + ), + ), + ( + "FIELD", + GraphQLEnumValue( + DirectiveLocation.FIELD, description="Location adjacent to a field." + ), + ), + ( + "FRAGMENT_DEFINITION", + GraphQLEnumValue( + DirectiveLocation.FRAGMENT_DEFINITION, + description="Location adjacent to a fragment definition.", + ), + ), + ( + "FRAGMENT_SPREAD", + GraphQLEnumValue( + DirectiveLocation.FRAGMENT_SPREAD, + description="Location adjacent to a fragment spread.", + ), + ), + ( + "INLINE_FRAGMENT", + GraphQLEnumValue( + DirectiveLocation.INLINE_FRAGMENT, + description="Location adjacent to an inline fragment.", + ), + ), + ( + "SCHEMA", + GraphQLEnumValue( + DirectiveLocation.SCHEMA, + description="Location adjacent to a schema definition.", + ), + ), + ( + "SCALAR", + GraphQLEnumValue( + DirectiveLocation.SCALAR, + description="Location adjacent to a scalar definition.", + ), + ), + ( + "OBJECT", + GraphQLEnumValue( + DirectiveLocation.OBJECT, + description="Location adjacent to an object definition.", + ), + ), + ( + "FIELD_DEFINITION", + GraphQLEnumValue( + DirectiveLocation.FIELD_DEFINITION, + description="Location adjacent to a field definition.", + ), + ), + ( + "ARGUMENT_DEFINITION", + GraphQLEnumValue( + DirectiveLocation.ARGUMENT_DEFINITION, + description="Location adjacent to an argument definition.", + ), + ), + ( + "INTERFACE", + GraphQLEnumValue( + DirectiveLocation.INTERFACE, + description="Location adjacent to an interface definition.", + ), + ), + ( + "UNION", + GraphQLEnumValue( + DirectiveLocation.UNION, + description="Location adjacent to a union definition.", + ), + ), + ( + "ENUM", + GraphQLEnumValue( + DirectiveLocation.ENUM, + description="Location adjacent to an enum definition.", + ), + ), + ( + "ENUM_VALUE", + GraphQLEnumValue( + DirectiveLocation.ENUM_VALUE, + description="Location adjacent to an enum value definition.", + ), + ), + ( + "INPUT_OBJECT", + GraphQLEnumValue( + DirectiveLocation.INPUT_OBJECT, + description="Location adjacent to an input object definition.", + ), + ), + ( + "INPUT_FIELD_DEFINITION", + GraphQLEnumValue( + DirectiveLocation.INPUT_FIELD_DEFINITION, + description="Location adjacent to an input object field definition.", + ), + ), + ] ), - values=OrderedDict([ - ('QUERY', GraphQLEnumValue( - DirectiveLocation.QUERY, - description='Location adjacent to a query operation.' - )), - ('MUTATION', GraphQLEnumValue( - DirectiveLocation.MUTATION, - description='Location adjacent to a mutation operation.' - )), - ('SUBSCRIPTION', GraphQLEnumValue( - DirectiveLocation.SUBSCRIPTION, - description='Location adjacent to a subscription operation.' - )), - ('FIELD', GraphQLEnumValue( - DirectiveLocation.FIELD, - description='Location adjacent to a field.' - )), - ('FRAGMENT_DEFINITION', GraphQLEnumValue( - DirectiveLocation.FRAGMENT_DEFINITION, - description='Location adjacent to a fragment definition.' - )), - ('FRAGMENT_SPREAD', GraphQLEnumValue( - DirectiveLocation.FRAGMENT_SPREAD, - description='Location adjacent to a fragment spread.' - )), - ('INLINE_FRAGMENT', GraphQLEnumValue( - DirectiveLocation.INLINE_FRAGMENT, - description='Location adjacent to an inline fragment.' - )), - ('SCHEMA', GraphQLEnumValue( - DirectiveLocation.SCHEMA, - description='Location adjacent to a schema definition.' - )), - ('SCALAR', GraphQLEnumValue( - DirectiveLocation.SCALAR, - description='Location adjacent to a scalar definition.' - )), - ('OBJECT', GraphQLEnumValue( - DirectiveLocation.OBJECT, - description='Location adjacent to an object definition.' - )), - ('FIELD_DEFINITION', GraphQLEnumValue( - DirectiveLocation.FIELD_DEFINITION, - description='Location adjacent to a field definition.' - )), - ('ARGUMENT_DEFINITION', GraphQLEnumValue( - DirectiveLocation.ARGUMENT_DEFINITION, - description='Location adjacent to an argument definition.' - )), - ('INTERFACE', GraphQLEnumValue( - DirectiveLocation.INTERFACE, - description='Location adjacent to an interface definition.' - )), - ('UNION', GraphQLEnumValue( - DirectiveLocation.UNION, - description='Location adjacent to a union definition.' - )), - ('ENUM', GraphQLEnumValue( - DirectiveLocation.ENUM, - description='Location adjacent to an enum definition.' - )), - ('ENUM_VALUE', GraphQLEnumValue( - DirectiveLocation.ENUM_VALUE, - description='Location adjacent to an enum value definition.' - )), - ('INPUT_OBJECT', GraphQLEnumValue( - DirectiveLocation.INPUT_OBJECT, - description='Location adjacent to an input object definition.' - )), - ('INPUT_FIELD_DEFINITION', GraphQLEnumValue( - DirectiveLocation.INPUT_FIELD_DEFINITION, - description='Location adjacent to an input object field definition.' - )), - ])) +) class TypeKind(object): - SCALAR = 'SCALAR' - OBJECT = 'OBJECT' - INTERFACE = 'INTERFACE' - UNION = 'UNION' - ENUM = 'ENUM' - INPUT_OBJECT = 'INPUT_OBJECT' - LIST = 'LIST' - NON_NULL = 'NON_NULL' + SCALAR = "SCALAR" + OBJECT = "OBJECT" + INTERFACE = "INTERFACE" + UNION = "UNION" + ENUM = "ENUM" + INPUT_OBJECT = "INPUT_OBJECT" + LIST = "LIST" + NON_NULL = "NON_NULL" class TypeFieldResolvers(object): @@ -205,43 +321,69 @@ class TypeFieldResolvers(object): ) @classmethod - def kind(cls, type, *_): + def kind( + cls, + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + *_ # type: ResolveInfo + ): + # type: (...) -> str for klass, kind in cls._kinds: if isinstance(type, klass): return kind - raise Exception('Unknown kind of type: {}'.format(type)) + raise Exception("Unknown kind of type: {}".format(type)) @staticmethod - def fields(type, info, includeDeprecated=None): + def fields( + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + info, # type: ResolveInfo + includeDeprecated=None, # type: bool + ): + # type: (...) -> Optional[List[Field]] if isinstance(type, (GraphQLObjectType, GraphQLInterfaceType)): fields = [] include_deprecated = includeDeprecated for field_name, field in type.fields.items(): if field.deprecation_reason and not include_deprecated: continue - fields.append(Field( - name=field_name, - description=field.description, - type=field.type, - args=field.args, - deprecation_reason=field.deprecation_reason - )) + fields.append( + Field( + name=field_name, + description=field.description, + type=field.type, + args=field.args, + deprecation_reason=field.deprecation_reason, + ) + ) return fields return None @staticmethod - def interfaces(type, info): + def interfaces( + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + info, # type: ResolveInfo + ): + # type: (...) -> Optional[Any] if isinstance(type, GraphQLObjectType): return type.interfaces @staticmethod - def possible_types(type, info, **args): + def possible_types( + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + info, # type: ResolveInfo + **args # type: Any + ): + # type: (...) -> List[GraphQLObjectType] if isinstance(type, (GraphQLInterfaceType, GraphQLUnionType)): return info.schema.get_possible_types(type) @staticmethod - def enum_values(type, info, includeDeprecated=None): + def enum_values( + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + info, # type: ResolveInfo + includeDeprecated=None, # type: bool + ): + # type: (...) -> Optional[Any] if isinstance(type, GraphQLEnumType): values = type.values if not includeDeprecated: @@ -250,191 +392,269 @@ def enum_values(type, info, includeDeprecated=None): return values @staticmethod - def input_fields(type, info): + def input_fields( + type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + info, # type: ResolveInfo + ): + # type: (...) -> Optional[Any] if isinstance(type, GraphQLInputObjectType): return input_fields_to_list(type.fields) __Type = GraphQLObjectType( - '__Type', - description='The fundamental unit of any GraphQL Schema is the type. There are ' - 'many kinds of types in GraphQL as represented by the `__TypeKind` enum.' - '\n\nDepending on the kind of a type, certain fields describe ' - 'information about that type. Scalar types provide no information ' - 'beyond a name and description, while Enum types provide their values. ' - 'Object and Interface types provide the fields they describe. Abstract ' - 'types, Union and Interface, provide the Object types possible ' - 'at runtime. List and NonNull types compose other types.', - fields=lambda: OrderedDict([ - ('kind', GraphQLField( - type=GraphQLNonNull(__TypeKind), - resolver=TypeFieldResolvers.kind - )), - ('name', GraphQLField(GraphQLString)), - ('description', GraphQLField(GraphQLString)), - ('fields', GraphQLField( - type=GraphQLList(GraphQLNonNull(__Field)), - args={ - 'includeDeprecated': GraphQLArgument( - GraphQLBoolean, - default_value=False - ) - }, - resolver=TypeFieldResolvers.fields - )), - ('interfaces', GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), - resolver=TypeFieldResolvers.interfaces - )), - ('possibleTypes', GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), - resolver=TypeFieldResolvers.possible_types - )), - ('enumValues', GraphQLField( - type=GraphQLList(GraphQLNonNull(__EnumValue)), - args={ - 'includeDeprecated': GraphQLArgument( - GraphQLBoolean, - default_value=False - ) - }, - resolver=TypeFieldResolvers.enum_values - )), - ('inputFields', GraphQLField( - type=GraphQLList(GraphQLNonNull(__InputValue)), - resolver=TypeFieldResolvers.input_fields - )), - ('ofType', GraphQLField( - type=__Type, - resolver=lambda type, *_: getattr(type, 'of_type', None) - )), - ])) + "__Type", + description="The fundamental unit of any GraphQL Schema is the type. There are " + "many kinds of types in GraphQL as represented by the `__TypeKind` enum." + "\n\nDepending on the kind of a type, certain fields describe " + "information about that type. Scalar types provide no information " + "beyond a name and description, while Enum types provide their values. " + "Object and Interface types provide the fields they describe. Abstract " + "types, Union and Interface, provide the Object types possible " + "at runtime. List and NonNull types compose other types.", + fields=lambda: OrderedDict( + [ + ( + "kind", + GraphQLField( + type=GraphQLNonNull(__TypeKind), resolver=TypeFieldResolvers.kind + ), + ), + ("name", GraphQLField(GraphQLString)), + ("description", GraphQLField(GraphQLString)), + ( + "fields", + GraphQLField( + type=GraphQLList(GraphQLNonNull(__Field)), + args={ + "includeDeprecated": GraphQLArgument( + GraphQLBoolean, default_value=False + ) + }, + resolver=TypeFieldResolvers.fields, + ), + ), + ( + "interfaces", + GraphQLField( + type=GraphQLList(GraphQLNonNull(__Type)), + resolver=TypeFieldResolvers.interfaces, + ), + ), + ( + "possibleTypes", + GraphQLField( + type=GraphQLList(GraphQLNonNull(__Type)), + resolver=TypeFieldResolvers.possible_types, + ), + ), + ( + "enumValues", + GraphQLField( + type=GraphQLList(GraphQLNonNull(__EnumValue)), + args={ + "includeDeprecated": GraphQLArgument( + GraphQLBoolean, default_value=False + ) + }, + resolver=TypeFieldResolvers.enum_values, + ), + ), + ( + "inputFields", + GraphQLField( + type=GraphQLList(GraphQLNonNull(__InputValue)), + resolver=TypeFieldResolvers.input_fields, + ), + ), + ( + "ofType", + GraphQLField( + type=__Type, + resolver=lambda type, *_: getattr(type, "of_type", None), + ), + ), + ] + ), +) __Field = GraphQLObjectType( - '__Field', - description='Object and Interface types are described by a list of Fields, each of ' - 'which has a name, potentially a list of arguments, and a return type.', - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLNonNull(GraphQLString))), - ('description', GraphQLField(GraphQLString)), - ('args', GraphQLField( - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), - resolver=lambda field, *_: input_fields_to_list(field.args) - )), - ('type', GraphQLField(GraphQLNonNull(__Type))), - ('isDeprecated', GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), - resolver=lambda field, *_: bool(field.deprecation_reason) - )), - ('deprecationReason', GraphQLField( - type=GraphQLString, - resolver=lambda field, *_: field.deprecation_reason - )) - ]) + "__Field", + description="Object and Interface types are described by a list of Fields, each of " + "which has a name, potentially a list of arguments, and a return type.", + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLNonNull(GraphQLString))), + ("description", GraphQLField(GraphQLString)), + ( + "args", + GraphQLField( + type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), + resolver=lambda field, *_: input_fields_to_list(field.args), + ), + ), + ("type", GraphQLField(GraphQLNonNull(__Type))), + ( + "isDeprecated", + GraphQLField( + type=GraphQLNonNull(GraphQLBoolean), + resolver=lambda field, *_: bool(field.deprecation_reason), + ), + ), + ( + "deprecationReason", + GraphQLField( + type=GraphQLString, + resolver=lambda field, *_: field.deprecation_reason, + ), + ), + ] + ), ) __InputValue = GraphQLObjectType( - '__InputValue', - description='Arguments provided to Fields or Directives and the input fields of an ' - 'InputObject are represented as Input Values which describe their type ' - 'and optionally a default value.', - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLNonNull(GraphQLString))), - ('description', GraphQLField(GraphQLString)), - ('type', GraphQLField(GraphQLNonNull(__Type))), - ('defaultValue', GraphQLField( - type=GraphQLString, - resolver=lambda input_val, *_: - None if input_val.default_value is None - else print_ast(ast_from_value(input_val.default_value, input_val)) - )) - ])) + "__InputValue", + description="Arguments provided to Fields or Directives and the input fields of an " + "InputObject are represented as Input Values which describe their type " + "and optionally a default value.", + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLNonNull(GraphQLString))), + ("description", GraphQLField(GraphQLString)), + ("type", GraphQLField(GraphQLNonNull(__Type))), + ( + "defaultValue", + GraphQLField( + type=GraphQLString, + resolver=lambda input_val, *_: None + if input_val.default_value is None + else print_ast(ast_from_value(input_val.default_value, input_val)), + ), + ), + ] + ), +) __EnumValue = GraphQLObjectType( - '__EnumValue', - description='One possible value for a given Enum. Enum values are unique values, not ' - 'a placeholder for a string or numeric value. However an Enum value is ' - 'returned in a JSON response as a string.', - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLNonNull(GraphQLString))), - ('description', GraphQLField(GraphQLString)), - ('isDeprecated', GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), - resolver=lambda field, *_: bool(field.deprecation_reason) - )), - ('deprecationReason', GraphQLField( - type=GraphQLString, - resolver=lambda enum_value, *_: enum_value.deprecation_reason, - )) - ])) + "__EnumValue", + description="One possible value for a given Enum. Enum values are unique values, not " + "a placeholder for a string or numeric value. However an Enum value is " + "returned in a JSON response as a string.", + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLNonNull(GraphQLString))), + ("description", GraphQLField(GraphQLString)), + ( + "isDeprecated", + GraphQLField( + type=GraphQLNonNull(GraphQLBoolean), + resolver=lambda field, *_: bool(field.deprecation_reason), + ), + ), + ( + "deprecationReason", + GraphQLField( + type=GraphQLString, + resolver=lambda enum_value, *_: enum_value.deprecation_reason, + ), + ), + ] + ), +) __TypeKind = GraphQLEnumType( - '__TypeKind', - description='An enum describing what kind of type a given `__Type` is', - values=OrderedDict([ - ('SCALAR', GraphQLEnumValue( - TypeKind.SCALAR, - description='Indicates this type is a scalar.' - )), - ('OBJECT', GraphQLEnumValue( - TypeKind.OBJECT, - description='Indicates this type is an object. ' - '`fields` and `interfaces` are valid fields.' - )), - ('INTERFACE', GraphQLEnumValue( - TypeKind.INTERFACE, - description='Indicates this type is an interface. ' - '`fields` and `possibleTypes` are valid fields.' - )), - ('UNION', GraphQLEnumValue( - TypeKind.UNION, - description='Indicates this type is a union. ' - '`possibleTypes` is a valid field.' - )), - ('ENUM', GraphQLEnumValue( - TypeKind.ENUM, - description='Indicates this type is an enum. ' - '`enumValues` is a valid field.' - )), - ('INPUT_OBJECT', GraphQLEnumValue( - TypeKind.INPUT_OBJECT, - description='Indicates this type is an input object. ' - '`inputFields` is a valid field.' - )), - ('LIST', GraphQLEnumValue( - TypeKind.LIST, - description='Indicates this type is a list. ' - '`ofType` is a valid field.' - )), - ('NON_NULL', GraphQLEnumValue( - TypeKind.NON_NULL, - description='Indicates this type is a non-null. ' - '`ofType` is a valid field.' - )), - ])) + "__TypeKind", + description="An enum describing what kind of type a given `__Type` is", + values=OrderedDict( + [ + ( + "SCALAR", + GraphQLEnumValue( + TypeKind.SCALAR, description="Indicates this type is a scalar." + ), + ), + ( + "OBJECT", + GraphQLEnumValue( + TypeKind.OBJECT, + description="Indicates this type is an object. " + "`fields` and `interfaces` are valid fields.", + ), + ), + ( + "INTERFACE", + GraphQLEnumValue( + TypeKind.INTERFACE, + description="Indicates this type is an interface. " + "`fields` and `possibleTypes` are valid fields.", + ), + ), + ( + "UNION", + GraphQLEnumValue( + TypeKind.UNION, + description="Indicates this type is a union. " + "`possibleTypes` is a valid field.", + ), + ), + ( + "ENUM", + GraphQLEnumValue( + TypeKind.ENUM, + description="Indicates this type is an enum. " + "`enumValues` is a valid field.", + ), + ), + ( + "INPUT_OBJECT", + GraphQLEnumValue( + TypeKind.INPUT_OBJECT, + description="Indicates this type is an input object. " + "`inputFields` is a valid field.", + ), + ), + ( + "LIST", + GraphQLEnumValue( + TypeKind.LIST, + description="Indicates this type is a list. " + "`ofType` is a valid field.", + ), + ), + ( + "NON_NULL", + GraphQLEnumValue( + TypeKind.NON_NULL, + description="Indicates this type is a non-null. " + "`ofType` is a valid field.", + ), + ), + ] + ), +) IntrospectionSchema = __Schema SchemaMetaFieldDef = GraphQLField( # name='__schema', type=GraphQLNonNull(__Schema), - description='Access the current type schema of this server.', + description="Access the current type schema of this server.", resolver=lambda source, info, **args: info.schema, - args={} + args={}, ) TypeMetaFieldDef = GraphQLField( type=__Type, # name='__type', - description='Request the type information of a single type.', - args={'name': GraphQLArgument(GraphQLNonNull(GraphQLString))}, - resolver=lambda source, info, **args: info.schema.get_type(args['name']) + description="Request the type information of a single type.", + args={"name": GraphQLArgument(GraphQLNonNull(GraphQLString))}, + resolver=lambda source, info, **args: info.schema.get_type(args["name"]), ) TypeNameMetaFieldDef = GraphQLField( type=GraphQLNonNull(GraphQLString), # name='__typename', - description='The name of the current Object type at runtime.', + description="The name of the current Object type at runtime.", resolver=lambda source, info, **args: info.parent_type.name, - args={} + args={}, ) + diff --git a/graphql/type/scalars.py b/graphql/type/scalars.py index 8a99580f..ce07ee3a 100644 --- a/graphql/type/scalars.py +++ b/graphql/type/scalars.py @@ -2,6 +2,8 @@ from ..language.ast import BooleanValue, FloatValue, IntValue, StringValue from .definition import GraphQLScalarType +if False: + from typing import Any, Optional, Union # As per the GraphQL Spec, Integers are only treated as valid when a valid # 32-bit signed integer, providing the broadest support across platforms. @@ -13,6 +15,7 @@ def coerce_int(value): + # type: (Any) -> int if isinstance(value, int): num = value else: @@ -22,16 +25,19 @@ def coerce_int(value): num = int(float(value)) if MIN_INT <= num <= MAX_INT: return num + raise Exception(( "Int cannot represent non 32-bit signed integer value: {}" ).format(value)) def parse_int_literal(ast): + # type: (IntValue) -> Optional[int] if isinstance(ast, IntValue): num = int(ast.value) if MIN_INT <= num <= MAX_INT: return num + return None GraphQLInt = GraphQLScalarType( @@ -46,12 +52,14 @@ def parse_int_literal(ast): def coerce_float(value): + # type: (Any) -> float if isinstance(value, float): return value return float(value) def parse_float_literal(ast): + # type: (Union[FloatValue, IntValue]) -> Optional[float] if isinstance(ast, (FloatValue, IntValue)): return float(ast.value) return None @@ -68,6 +76,7 @@ def parse_float_literal(ast): def coerce_string(value): + # type: (Any) -> str if isinstance(value, string_types): return value @@ -78,6 +87,7 @@ def coerce_string(value): def coerce_str(value): + # type: (Any) -> str if isinstance(value, string_types): return value @@ -85,6 +95,7 @@ def coerce_str(value): def parse_string_literal(ast): + # type: (Union[StringValue]) -> Optional[str] if isinstance(ast, StringValue): return ast.value @@ -102,6 +113,7 @@ def parse_string_literal(ast): def parse_boolean_literal(ast): + # type: (BooleanValue) -> Optional[bool] if isinstance(ast, BooleanValue): return ast.value return None @@ -116,6 +128,7 @@ def parse_boolean_literal(ast): def parse_id_literal(ast): + # type: (StringValue) -> Optional[str] if isinstance(ast, (StringValue, IntValue)): return ast.value return None diff --git a/graphql/type/schema.py b/graphql/type/schema.py index 088183fa..0905749d 100644 --- a/graphql/type/schema.py +++ b/graphql/type/schema.py @@ -5,6 +5,10 @@ from .introspection import IntrospectionSchema from .typemap import GraphQLTypeMap +if False: + from .definition import GraphQLInterfaceType, GraphQLUnionType, GraphQLType + from typing import Dict, Union, Any, List, Optional + class GraphQLSchema(object): """Schema Definition @@ -30,21 +34,45 @@ class GraphQLSchema(object): directives=specified_directives.extend([MyCustomerDirective]), ) """ - __slots__ = '_query', '_mutation', '_subscription', '_type_map', '_directives', '_implementations', '_possible_type_map' - def __init__(self, query, mutation=None, subscription=None, directives=None, types=None): - assert isinstance(query, GraphQLObjectType), 'Schema query must be Object Type but got: {}.'.format(query) + __slots__ = ( + "_query", + "_mutation", + "_subscription", + "_type_map", + "_directives", + "_implementations", + "_possible_type_map", + ) + + def __init__( + self, + query, # type: GraphQLObjectType + mutation=None, # type: Optional[GraphQLObjectType] + subscription=None, # type: Optional[GraphQLObjectType] + directives=None, # type: Optional[List[GraphQLDirective]] + types=None, # type: Optional[List[GraphQLObjectType]] + ): + # type: (...) -> None + assert isinstance( + query, GraphQLObjectType + ), "Schema query must be Object Type but got: {}.".format(query) if mutation: - assert isinstance(mutation, GraphQLObjectType), \ - 'Schema mutation must be Object Type but got: {}.'.format(mutation) + assert isinstance( + mutation, GraphQLObjectType + ), "Schema mutation must be Object Type but got: {}.".format(mutation) if subscription: - assert isinstance(subscription, GraphQLObjectType), \ - 'Schema subscription must be Object Type but got: {}.'.format(subscription) + assert isinstance( + subscription, GraphQLObjectType + ), "Schema subscription must be Object Type but got: {}.".format( + subscription + ) if types: - assert isinstance(types, Iterable), \ - 'Schema types must be iterable if provided but got: {}.'.format(types) + assert isinstance( + types, Iterable + ), "Schema types must be iterable if provided but got: {}.".format(types) self._query = query self._mutation = mutation @@ -52,49 +80,63 @@ def __init__(self, query, mutation=None, subscription=None, directives=None, typ if directives is None: directives = specified_directives - assert all(isinstance(d, GraphQLDirective) for d in directives), \ - 'Schema directives must be List[GraphQLDirective] if provided but got: {}.'.format( - directives + assert all( + isinstance(d, GraphQLDirective) for d in directives + ), "Schema directives must be List[GraphQLDirective] if provided but got: {}.".format( + directives ) self._directives = directives - initial_types = [ - query, - mutation, - subscription, - IntrospectionSchema - ] + initial_types = [query, mutation, subscription, IntrospectionSchema] if types: initial_types += types - self._type_map = GraphQLTypeMap(initial_types) + self._type_map = GraphQLTypeMap(initial_types) # type: Dict[str, GraphQLType] def get_query_type(self): + # type: () -> GraphQLObjectType return self._query def get_mutation_type(self): + # type: () -> Optional[GraphQLObjectType] return self._mutation def get_subscription_type(self): + # type: () -> Optional[GraphQLObjectType] return self._subscription def get_type_map(self): + # type: () -> Dict[str, GraphQLType] return self._type_map def get_type(self, name): + # type: (str) -> Optional[GraphQLType] return self._type_map.get(name) def get_directives(self): + # type: () -> List[GraphQLDirective] return self._directives def get_directive(self, name): + # type: (str) -> Optional[GraphQLDirective] for directive in self.get_directives(): if directive.name == name: return directive return None - def get_possible_types(self, abstract_type): + def get_possible_types( + self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + ): + # type: (...) -> List[GraphQLObjectType] return self._type_map.get_possible_types(abstract_type) - def is_possible_type(self, abstract_type, possible_type): + def is_possible_type( + self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + possible_type, # type: GraphQLObjectType + ): + # type: (...) -> bool return self._type_map.is_possible_type(abstract_type, possible_type) diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index 1bad09c1..d7953d80 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -7,11 +7,17 @@ GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLUnionType, is_input_type, is_output_type) +if False: + from typing import Any, List, Optional, Union class GraphQLTypeMap(OrderedDict): - def __init__(self, types): + def __init__(self, + # type: Union[List[Optional[GraphQLObjectType]], List[GraphQLObjectType]] + types, + ): + # type: (...) -> None super(GraphQLTypeMap, self).__init__() self.update(reduce(self.reducer, types, OrderedDict())) self._possible_type_map = defaultdict(set) @@ -21,21 +27,32 @@ def __init__(self, types): for gql_type in self.values(): if isinstance(gql_type, GraphQLObjectType): for interface in gql_type.interfaces: - self._implementations.setdefault(interface.name, []).append(gql_type) + self._implementations.setdefault( + interface.name, []).append(gql_type) # Enforce correct interface implementations. for type in self.values(): if isinstance(type, GraphQLObjectType): for interface in type.interfaces: - self.assert_object_implements_interface(self, type, interface) - - def get_possible_types(self, abstract_type): + self.assert_object_implements_interface( + self, type, interface) + + def get_possible_types(self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + ): + # type: (...) -> List[GraphQLObjectType] if isinstance(abstract_type, GraphQLUnionType): return abstract_type.types assert isinstance(abstract_type, GraphQLInterfaceType) return self._implementations.get(abstract_type.name, None) - def is_possible_type(self, abstract_type, possible_type): + def is_possible_type(self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + possible_type, # type: GraphQLObjectType + ): + # type: (...) -> bool possible_types = self.get_possible_types(abstract_type) assert isinstance(possible_types, Sequence), ( 'Could not find possible implementing types for ${} in ' + @@ -44,12 +61,14 @@ def is_possible_type(self, abstract_type, possible_type): ).format(abstract_type) if not self._possible_type_map[abstract_type.name]: - self._possible_type_map[abstract_type.name].update([p.name for p in possible_types]) + self._possible_type_map[abstract_type.name].update( + [p.name for p in possible_types]) return possible_type.name in self._possible_type_map[abstract_type.name] @classmethod def reducer(cls, map, type): + # type: (OrderedDict, Any) -> OrderedDict if not type: return map @@ -81,18 +100,22 @@ def reducer(cls, map, type): for field_name, field in field_map.items(): if type_is_input: assert isinstance(field, GraphQLInputObjectField), ( - '{}.{} must be an instance of GraphQLInputObjectField.'.format(type, field_name) + '{}.{} must be an instance of GraphQLInputObjectField.'.format( + type, field_name) ) assert is_input_type(field.type), ( - '{}.{} field type must be Input Type but got: {}.'.format(type, field_name, field.type) + '{}.{} field type must be Input Type but got: {}.'.format( + type, field_name, field.type) ) else: assert is_output_type(field.type), ( - '{}.{} field type must be Output Type but got: {}.'.format(type, field_name, field.type) + '{}.{} field type must be Output Type but got: {}.'.format( + type, field_name, field.type) ) for arg_name, arg in field.args.items(): assert isinstance(arg, (GraphQLArgument, GraphQLArgument)), ( - '{}.{}({}:) argument must be an instance of GraphQLArgument.'.format(type, field_name, arg_name) + '{}.{}({}:) argument must be an instance of GraphQLArgument.'.format( + type, field_name, arg_name) ) assert is_input_type(arg.type), ( '{}.{}({}:) argument type must be Input Type but got: {}.'.format(type, field_name, arg_name, @@ -100,12 +123,18 @@ def reducer(cls, map, type): ) reduced_map = cls.reducer(reduced_map, arg.type) - reduced_map = cls.reducer(reduced_map, getattr(field, 'type', None)) + reduced_map = cls.reducer( + reduced_map, getattr(field, 'type', None)) return reduced_map @classmethod - def assert_object_implements_interface(cls, schema, object, interface): + def assert_object_implements_interface(cls, + schema, # type: GraphQLTypeMap + object, # type: GraphQLObjectType + interface, # type: GraphQLInterfaceType + ): + # type: (...) -> None object_field_map = object.fields interface_field_map = interface.fields diff --git a/graphql/utils/assert_valid_name.py b/graphql/utils/assert_valid_name.py index 40afe596..2775b9ed 100644 --- a/graphql/utils/assert_valid_name.py +++ b/graphql/utils/assert_valid_name.py @@ -1,9 +1,13 @@ import re -NAME_PATTERN = r'^[_a-zA-Z][_a-zA-Z0-9]*$' +NAME_PATTERN = r"^[_a-zA-Z][_a-zA-Z0-9]*$" COMPILED_NAME_PATTERN = re.compile(NAME_PATTERN) def assert_valid_name(name): - '''Helper to assert that provided names are valid.''' - assert COMPILED_NAME_PATTERN.match(name), 'Names must match /{}/ but "{}" does not.'.format(NAME_PATTERN, name) + # type: (str) -> None + """Helper to assert that provided names are valid.""" + assert COMPILED_NAME_PATTERN.match( + name + ), 'Names must match /{}/ but "{}" does not.'.format(NAME_PATTERN, name) + return None diff --git a/graphql/utils/ast_from_value.py b/graphql/utils/ast_from_value.py index d41a91d8..6773423b 100644 --- a/graphql/utils/ast_from_value.py +++ b/graphql/utils/ast_from_value.py @@ -5,8 +5,12 @@ from six import string_types from ..language import ast -from ..type.definition import (GraphQLEnumType, GraphQLInputObjectType, - GraphQLList, GraphQLNonNull) +from ..type.definition import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, +) from ..type.scalars import GraphQLFloat @@ -41,7 +45,9 @@ def ast_from_value(value, type=None): return ast.FloatValue(string_num) if isinstance(value, string_types): - if isinstance(type, GraphQLEnumType) and re.match(r'^[_a-zA-Z][_a-zA-Z0-9]*$', value): + if isinstance(type, GraphQLEnumType) and re.match( + r"^[_a-zA-Z][_a-zA-Z0-9]*$", value + ): return ast.EnumValue(value) return ast.StringValue(json.dumps(value)[1:-1]) @@ -59,9 +65,6 @@ def ast_from_value(value, type=None): field_value = ast_from_value(field_value, field_type) if field_value: - fields.append(ast.ObjectField( - ast.Name(field_name), - field_value - )) + fields.append(ast.ObjectField(ast.Name(field_name), field_value)) return ast.ObjectValue(fields) diff --git a/graphql/utils/ast_to_code.py b/graphql/utils/ast_to_code.py index 8c307eea..659562c3 100644 --- a/graphql/utils/ast_to_code.py +++ b/graphql/utils/ast_to_code.py @@ -1,49 +1,51 @@ from ..language.ast import Node from ..language.parser import Loc +if False: + from typing import Any + def ast_to_code(ast, indent=0): + # type: (Any, int) -> str """ Converts an ast into a python code representation of the AST. """ code = [] def append(line): - code.append((' ' * indent) + line) + # type: (str) -> None + code.append((" " * indent) + line) if isinstance(ast, Node): - append('ast.{}('.format(ast.__class__.__name__)) + append("ast.{}(".format(ast.__class__.__name__)) indent += 1 for i, k in enumerate(ast._fields, 1): v = getattr(ast, k) - append('{}={},'.format( - k, - ast_to_code(v, indent), - )) + append("{}={},".format(k, ast_to_code(v, indent))) if ast.loc: - append('loc={}'.format(ast_to_code(ast.loc, indent))) + append("loc={}".format(ast_to_code(ast.loc, indent))) indent -= 1 - append(')') + append(")") elif isinstance(ast, Loc): - append('loc({}, {})'.format(ast.start, ast.end)) + append("loc({}, {})".format(ast.start, ast.end)) elif isinstance(ast, list): if ast: - append('[') + append("[") indent += 1 for i, it in enumerate(ast, 1): is_last = i == len(ast) - append(ast_to_code(it, indent) + (',' if not is_last else '')) + append(ast_to_code(it, indent) + ("," if not is_last else "")) indent -= 1 - append(']') + append("]") else: - append('[]') + append("[]") else: append(repr(ast)) - return '\n'.join(code).strip() + return "\n".join(code).strip() diff --git a/graphql/utils/ast_to_dict.py b/graphql/utils/ast_to_dict.py index a2b5cac5..57e6e92b 100644 --- a/graphql/utils/ast_to_dict.py +++ b/graphql/utils/ast_to_dict.py @@ -3,18 +3,13 @@ def ast_to_dict(node, include_loc=False): if isinstance(node, Node): - d = { - 'kind': node.__class__.__name__ - } - if hasattr(node, '_fields'): + d = {"kind": node.__class__.__name__} + if hasattr(node, "_fields"): for field in node._fields: d[field] = ast_to_dict(getattr(node, field), include_loc) - if include_loc and hasattr(node, 'loc') and node.loc: - d['loc'] = { - 'start': node.loc.start, - 'end': node.loc.end - } + if include_loc and hasattr(node, "loc") and node.loc: + d["loc"] = {"start": node.loc.start, "end": node.loc.end} return d diff --git a/graphql/utils/base.py b/graphql/utils/base.py index 54a10346..093b3f6d 100644 --- a/graphql/utils/base.py +++ b/graphql/utils/base.py @@ -44,11 +44,7 @@ from .concat_ast import concat_ast # Comparators for types -from .type_comparators import ( - is_equal_type, - is_type_sub_type_of, - do_types_overlap -) +from .type_comparators import is_equal_type, is_type_sub_type_of, do_types_overlap # Asserts that a string is a valid GraphQL name from .assert_valid_name import assert_valid_name @@ -58,23 +54,23 @@ __all__ = [ - 'introspection_query', - 'get_operation_ast', - 'build_client_schema', - 'build_ast_schema', - 'extend_schema', - 'print_introspection_schema', - 'print_schema', - 'type_from_ast', - 'value_from_ast', - 'ast_from_value', - 'TypeInfo', - 'is_valid_value', - 'is_valid_literal_value', - 'concat_ast', - 'do_types_overlap', - 'is_equal_type', - 'is_type_sub_type_of', - 'assert_valid_name', - 'Undefined', + "introspection_query", + "get_operation_ast", + "build_client_schema", + "build_ast_schema", + "extend_schema", + "print_introspection_schema", + "print_schema", + "type_from_ast", + "value_from_ast", + "ast_from_value", + "TypeInfo", + "is_valid_value", + "is_valid_literal_value", + "concat_ast", + "do_types_overlap", + "is_equal_type", + "is_type_sub_type_of", + "assert_valid_name", + "Undefined", ] diff --git a/graphql/utils/build_ast_schema.py b/graphql/utils/build_ast_schema.py index 8de1df72..8d28f4be 100644 --- a/graphql/utils/build_ast_schema.py +++ b/graphql/utils/build_ast_schema.py @@ -1,18 +1,40 @@ from ..execution.values import get_argument_values from ..language import ast from ..pyutils.ordereddict import OrderedDict -from ..type import (GraphQLArgument, GraphQLBoolean, - GraphQLDeprecatedDirective, GraphQLDirective, - GraphQLEnumType, GraphQLEnumValue, GraphQLField, - GraphQLFloat, GraphQLID, GraphQLIncludeDirective, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInt, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, - GraphQLSchema, GraphQLSkipDirective, GraphQLString, - GraphQLUnionType) -from ..type.introspection import (__Directive, __DirectiveLocation, - __EnumValue, __Field, __InputValue, __Schema, - __Type, __TypeKind) +from ..type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLDeprecatedDirective, + GraphQLDirective, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLFloat, + GraphQLID, + GraphQLIncludeDirective, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLSkipDirective, + GraphQLString, + GraphQLUnionType, +) +from ..type.introspection import ( + __Directive, + __DirectiveLocation, + __EnumValue, + __Field, + __InputValue, + __Schema, + __Type, + __TypeKind, +) from ..utils.value_from_ast import value_from_ast @@ -50,7 +72,7 @@ def _none(*_): def build_ast_schema(document): - assert isinstance(document, ast.Document), 'must pass in Document ast.' + assert isinstance(document, ast.Document), "must pass in Document ast." schema_def = None @@ -69,7 +91,7 @@ def build_ast_schema(document): for d in document.definitions: if isinstance(d, ast.SchemaDefinition): if schema_def: - raise Exception('Must provide only one schema definition.') + raise Exception("Must provide only one schema definition.") schema_def = d if isinstance(d, type_asts): type_defs.append(d) @@ -77,7 +99,7 @@ def build_ast_schema(document): directive_defs.append(d) if not schema_def: - raise Exception('Must provide a schema definition.') + raise Exception("Must provide a schema definition.") query_type_name = None mutation_type_name = None @@ -85,48 +107,60 @@ def build_ast_schema(document): for operation_type in schema_def.operation_types: type_name = operation_type.type.name.value - if operation_type.operation == 'query': + if operation_type.operation == "query": if query_type_name: - raise Exception('Must provide only one query type in schema.') + raise Exception("Must provide only one query type in schema.") query_type_name = type_name - elif operation_type.operation == 'mutation': + elif operation_type.operation == "mutation": if mutation_type_name: - raise Exception('Must provide only one mutation type in schema.') + raise Exception("Must provide only one mutation type in schema.") mutation_type_name = type_name - elif operation_type.operation == 'subscription': + elif operation_type.operation == "subscription": if subscription_type_name: - raise Exception('Must provide only one subscription type in schema.') + raise Exception("Must provide only one subscription type in schema.") subscription_type_name = type_name if not query_type_name: - raise Exception('Must provide schema definition with query type.') + raise Exception("Must provide schema definition with query type.") ast_map = {d.name.value: d for d in type_defs} if query_type_name not in ast_map: - raise Exception('Specified query type "{}" not found in document.'.format(query_type_name)) + raise Exception( + 'Specified query type "{}" not found in document.'.format(query_type_name) + ) if mutation_type_name and mutation_type_name not in ast_map: - raise Exception('Specified mutation type "{}" not found in document.'.format(mutation_type_name)) + raise Exception( + 'Specified mutation type "{}" not found in document.'.format( + mutation_type_name + ) + ) if subscription_type_name and subscription_type_name not in ast_map: - raise Exception('Specified subscription type "{}" not found in document.'.format(subscription_type_name)) - - inner_type_map = OrderedDict([ - ('String', GraphQLString), - ('Int', GraphQLInt), - ('Float', GraphQLFloat), - ('Boolean', GraphQLBoolean), - ('ID', GraphQLID), - ('__Schema', __Schema), - ('__Directive', __Directive), - ('__DirectiveLocation', __DirectiveLocation), - ('__Type', __Type), - ('__Field', __Field), - ('__InputValue', __InputValue), - ('__EnumValue', __EnumValue), - ('__TypeKind', __TypeKind), - ]) + raise Exception( + 'Specified subscription type "{}" not found in document.'.format( + subscription_type_name + ) + ) + + inner_type_map = OrderedDict( + [ + ("String", GraphQLString), + ("Int", GraphQLInt), + ("Float", GraphQLFloat), + ("Boolean", GraphQLBoolean), + ("ID", GraphQLID), + ("__Schema", __Schema), + ("__Directive", __Directive), + ("__DirectiveLocation", __DirectiveLocation), + ("__Type", __Type), + ("__Field", __Field), + ("__InputValue", __InputValue), + ("__EnumValue", __EnumValue), + ("__TypeKind", __TypeKind), + ] + ) def get_directive(directive_ast): return GraphQLDirective( @@ -137,7 +171,7 @@ def get_directive(directive_ast): def get_object_type(type_ast): type = type_def_named(type_ast.name.value) - assert isinstance(type, GraphQLObjectType), 'AST must provide object type' + assert isinstance(type, GraphQLObjectType), "AST must provide object type" return type def produce_type_def(type_ast): @@ -161,11 +195,13 @@ def type_def_named(type_name): def make_schema_def(definition): if not definition: - raise Exception('def must be defined.') + raise Exception("def must be defined.") handler = _schema_def_handlers.get(type(definition)) if not handler: - raise Exception('Type kind "{}" not supported.'.format(type(definition).__name__)) + raise Exception( + 'Type kind "{}" not supported.'.format(type(definition).__name__) + ) return handler(definition) @@ -173,16 +209,19 @@ def make_type_def(definition): return GraphQLObjectType( name=definition.name.value, fields=lambda: make_field_def_map(definition), - interfaces=make_implemented_interfaces(definition) + interfaces=make_implemented_interfaces(definition), ) def make_field_def_map(definition): return OrderedDict( - (f.name.value, GraphQLField( - type=produce_type_def(f.type), - args=make_input_values(f.arguments, GraphQLArgument), - deprecation_reason=get_deprecation_reason(f.directives), - )) + ( + f.name.value, + GraphQLField( + type=produce_type_def(f.type), + args=make_input_values(f.arguments, GraphQLArgument), + deprecation_reason=get_deprecation_reason(f.directives), + ), + ) for f in definition.fields ) @@ -191,10 +230,15 @@ def make_implemented_interfaces(definition): def make_input_values(values, cls): return OrderedDict( - (value.name.value, cls( - type=produce_type_def(value.type), - default_value=value_from_ast(value.default_value, produce_type_def(value.type)) - )) + ( + value.name.value, + cls( + type=produce_type_def(value.type), + default_value=value_from_ast( + value.default_value, produce_type_def(value.type) + ), + ), + ) for value in values ) @@ -202,22 +246,26 @@ def make_interface_def(definition): return GraphQLInterfaceType( name=definition.name.value, resolve_type=_none, - fields=lambda: make_field_def_map(definition) + fields=lambda: make_field_def_map(definition), ) def make_enum_def(definition): - values = OrderedDict((v.name.value, GraphQLEnumValue(deprecation_reason=get_deprecation_reason(v.directives))) - for v in definition.values) - return GraphQLEnumType( - name=definition.name.value, - values=values + values = OrderedDict( + ( + v.name.value, + GraphQLEnumValue( + deprecation_reason=get_deprecation_reason(v.directives) + ), + ) + for v in definition.values ) + return GraphQLEnumType(name=definition.name.value, values=values) def make_union_def(definition): return GraphQLUnionType( name=definition.name.value, resolve_type=_none, - types=[produce_type_def(t) for t in definition.types] + types=[produce_type_def(t) for t in definition.types], ) def make_scalar_def(definition): @@ -228,13 +276,15 @@ def make_scalar_def(definition): # Returning none, however would cause the scalar to fail validation. Returning false, # will cause them to pass. parse_literal=_false, - parse_value=_false + parse_value=_false, ) def make_input_object_def(definition): return GraphQLInputObjectType( name=definition.name.value, - fields=lambda: make_input_values(definition.fields, GraphQLInputObjectField) + fields=lambda: make_input_values( + definition.fields, GraphQLInputObjectField + ), ) _schema_def_handlers = { @@ -243,15 +293,21 @@ def make_input_object_def(definition): ast.EnumTypeDefinition: make_enum_def, ast.UnionTypeDefinition: make_union_def, ast.ScalarTypeDefinition: make_scalar_def, - ast.InputObjectTypeDefinition: make_input_object_def + ast.InputObjectTypeDefinition: make_input_object_def, } types = [type_def_named(definition.name.value) for definition in type_defs] directives = [get_directive(d) for d in directive_defs] # If specified directive were not explicitly declared, add them. - find_skip_directive = (directive.name for directive in directives if directive.name == 'skip') - find_include_directive = (directive.name for directive in directives if directive.name == 'include') - find_deprecated_directive = (directive.name for directive in directives if directive.name == 'deprecated') + find_skip_directive = ( + directive.name for directive in directives if directive.name == "skip" + ) + find_include_directive = ( + directive.name for directive in directives if directive.name == "include" + ) + find_deprecated_directive = ( + directive.name for directive in directives if directive.name == "deprecated" + ) if not next(find_skip_directive, None): directives.append(GraphQLSkipDirective) @@ -262,30 +318,37 @@ def make_input_object_def(definition): if not next(find_deprecated_directive, None): directives.append(GraphQLDeprecatedDirective) - schema_kwargs = {'query': get_object_type(ast_map[query_type_name])} + schema_kwargs = {"query": get_object_type(ast_map[query_type_name])} if mutation_type_name: - schema_kwargs['mutation'] = get_object_type(ast_map[mutation_type_name]) + schema_kwargs["mutation"] = get_object_type(ast_map[mutation_type_name]) if subscription_type_name: - schema_kwargs['subscription'] = get_object_type(ast_map[subscription_type_name]) + schema_kwargs["subscription"] = get_object_type(ast_map[subscription_type_name]) if directive_defs: - schema_kwargs['directives'] = directives + schema_kwargs["directives"] = directives if types: - schema_kwargs['types'] = types + schema_kwargs["types"] = types return GraphQLSchema(**schema_kwargs) def get_deprecation_reason(directives): - deprecated_ast = next((directive for directive in directives - if directive.name.value == GraphQLDeprecatedDirective.name), - None) + deprecated_ast = next( + ( + directive + for directive in directives + if directive.name.value == GraphQLDeprecatedDirective.name + ), + None, + ) if deprecated_ast: - args = get_argument_values(GraphQLDeprecatedDirective.args, deprecated_ast.arguments) - return args['reason'] + args = get_argument_values( + GraphQLDeprecatedDirective.args, deprecated_ast.arguments + ) + return args["reason"] else: return None diff --git a/graphql/utils/build_client_schema.py b/graphql/utils/build_client_schema.py index 4ce0af3b..2ae23aaf 100644 --- a/graphql/utils/build_client_schema.py +++ b/graphql/utils/build_client_schema.py @@ -1,16 +1,39 @@ from ..language.parser import parse_value from ..pyutils.ordereddict import OrderedDict -from ..type import (GraphQLArgument, GraphQLBoolean, GraphQLEnumType, - GraphQLEnumValue, GraphQLField, GraphQLFloat, GraphQLID, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInt, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, - GraphQLSchema, GraphQLString, GraphQLUnionType, - is_input_type, is_output_type) +from ..type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLFloat, + GraphQLID, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, + is_input_type, + is_output_type, +) from ..type.directives import DirectiveLocation, GraphQLDirective -from ..type.introspection import (TypeKind, __Directive, __DirectiveLocation, - __EnumValue, __Field, __InputValue, __Schema, - __Type, __TypeKind) +from ..type.introspection import ( + TypeKind, + __Directive, + __DirectiveLocation, + __EnumValue, + __Field, + __InputValue, + __Schema, + __Type, + __TypeKind, +) from .value_from_ast import value_from_ast @@ -23,50 +46,49 @@ def _none(*_): def no_execution(root, info, **args): - raise Exception('Client Schema cannot be used for execution.') + raise Exception("Client Schema cannot be used for execution.") def build_client_schema(introspection): - schema_introspection = introspection['__schema'] + schema_introspection = introspection["__schema"] - type_introspection_map = {t['name']: t for t in schema_introspection['types']} + type_introspection_map = {t["name"]: t for t in schema_introspection["types"]} type_def_cache = { - 'String': GraphQLString, - 'Int': GraphQLInt, - 'Float': GraphQLFloat, - 'Boolean': GraphQLBoolean, - 'ID': GraphQLID, - '__Schema': __Schema, - '__Directive': __Directive, - '__DirectiveLocation': __DirectiveLocation, - '__Type': __Type, - '__Field': __Field, - '__InputValue': __InputValue, - '__EnumValue': __EnumValue, - '__TypeKind': __TypeKind, - + "String": GraphQLString, + "Int": GraphQLInt, + "Float": GraphQLFloat, + "Boolean": GraphQLBoolean, + "ID": GraphQLID, + "__Schema": __Schema, + "__Directive": __Directive, + "__DirectiveLocation": __DirectiveLocation, + "__Type": __Type, + "__Field": __Field, + "__InputValue": __InputValue, + "__EnumValue": __EnumValue, + "__TypeKind": __TypeKind, } def get_type(type_ref): - kind = type_ref.get('kind') + kind = type_ref.get("kind") if kind == TypeKind.LIST: - item_ref = type_ref.get('ofType') + item_ref = type_ref.get("ofType") if not item_ref: - raise Exception('Decorated type deeper than introspection query.') + raise Exception("Decorated type deeper than introspection query.") return GraphQLList(get_type(item_ref)) elif kind == TypeKind.NON_NULL: - nullable_ref = type_ref.get('ofType') + nullable_ref = type_ref.get("ofType") if not nullable_ref: - raise Exception('Decorated type deeper than introspection query.') + raise Exception("Decorated type deeper than introspection query.") return GraphQLNonNull(get_type(nullable_ref)) - return get_named_type(type_ref['name']) + return get_named_type(type_ref["name"]) def get_named_type(type_name): if type_name in type_def_cache: @@ -75,8 +97,8 @@ def get_named_type(type_name): type_introspection = type_introspection_map.get(type_name) if not type_introspection: raise Exception( - 'Invalid or incomplete schema, unknown type: {}. Ensure that a full introspection query ' - 'is used in order to build a client schema.'.format(type_name) + "Invalid or incomplete schema, unknown type: {}. Ensure that a full introspection query " + "is used in order to build a client schema.".format(type_name) ) type_def = type_def_cache[type_name] = build_type(type_introspection) @@ -84,87 +106,108 @@ def get_named_type(type_name): def get_input_type(type_ref): input_type = get_type(type_ref) - assert is_input_type(input_type), 'Introspection must provide input type for arguments.' + assert is_input_type( + input_type + ), "Introspection must provide input type for arguments." return input_type def get_output_type(type_ref): output_type = get_type(type_ref) - assert is_output_type(output_type), 'Introspection must provide output type for fields.' + assert is_output_type( + output_type + ), "Introspection must provide output type for fields." return output_type def get_object_type(type_ref): object_type = get_type(type_ref) - assert isinstance(object_type, GraphQLObjectType), 'Introspection must provide object type for possibleTypes.' + assert isinstance( + object_type, GraphQLObjectType + ), "Introspection must provide object type for possibleTypes." return object_type def get_interface_type(type_ref): interface_type = get_type(type_ref) - assert isinstance(interface_type, GraphQLInterfaceType), \ - 'Introspection must provide interface type for interfaces.' + assert isinstance( + interface_type, GraphQLInterfaceType + ), "Introspection must provide interface type for interfaces." return interface_type def build_type(type): - type_kind = type.get('kind') + type_kind = type.get("kind") handler = type_builders.get(type_kind) if not handler: raise Exception( - 'Invalid or incomplete schema, unknown kind: {}. Ensure that a full introspection query ' - 'is used in order to build a client schema.'.format(type_kind) + "Invalid or incomplete schema, unknown kind: {}. Ensure that a full introspection query " + "is used in order to build a client schema.".format(type_kind) ) return handler(type) def build_scalar_def(scalar_introspection): return GraphQLScalarType( - name=scalar_introspection['name'], - description=scalar_introspection.get('description'), + name=scalar_introspection["name"], + description=scalar_introspection.get("description"), serialize=_none, parse_value=_false, - parse_literal=_false + parse_literal=_false, ) def build_object_def(object_introspection): return GraphQLObjectType( - name=object_introspection['name'], - description=object_introspection.get('description'), - interfaces=[get_interface_type(i) for i in object_introspection.get('interfaces', [])], - fields=lambda: build_field_def_map(object_introspection) + name=object_introspection["name"], + description=object_introspection.get("description"), + interfaces=[ + get_interface_type(i) + for i in object_introspection.get("interfaces", []) + ], + fields=lambda: build_field_def_map(object_introspection), ) def build_interface_def(interface_introspection): return GraphQLInterfaceType( - name=interface_introspection['name'], - description=interface_introspection.get('description'), + name=interface_introspection["name"], + description=interface_introspection.get("description"), fields=lambda: build_field_def_map(interface_introspection), - resolve_type=no_execution + resolve_type=no_execution, ) def build_union_def(union_introspection): return GraphQLUnionType( - name=union_introspection['name'], - description=union_introspection.get('description'), - types=[get_object_type(t) for t in union_introspection.get('possibleTypes', [])], - resolve_type=no_execution + name=union_introspection["name"], + description=union_introspection.get("description"), + types=[ + get_object_type(t) for t in union_introspection.get("possibleTypes", []) + ], + resolve_type=no_execution, ) def build_enum_def(enum_introspection): return GraphQLEnumType( - name=enum_introspection['name'], - description=enum_introspection.get('description'), - values=OrderedDict([(value_introspection['name'], - GraphQLEnumValue(description=value_introspection.get('description'), - deprecation_reason=value_introspection.get('deprecationReason'))) - for value_introspection in enum_introspection.get('enumValues', []) - ]) + name=enum_introspection["name"], + description=enum_introspection.get("description"), + values=OrderedDict( + [ + ( + value_introspection["name"], + GraphQLEnumValue( + description=value_introspection.get("description"), + deprecation_reason=value_introspection.get( + "deprecationReason" + ), + ), + ) + for value_introspection in enum_introspection.get("enumValues", []) + ] + ), ) def build_input_object_def(input_object_introspection): return GraphQLInputObjectType( - name=input_object_introspection['name'], - description=input_object_introspection.get('description'), + name=input_object_introspection["name"], + description=input_object_introspection.get("description"), fields=lambda: build_input_value_def_map( - input_object_introspection.get('inputFields'), GraphQLInputObjectField - ) + input_object_introspection.get("inputFields"), GraphQLInputObjectField + ), ) type_builders = { @@ -173,78 +216,101 @@ def build_input_object_def(input_object_introspection): TypeKind.INTERFACE: build_interface_def, TypeKind.UNION: build_union_def, TypeKind.ENUM: build_enum_def, - TypeKind.INPUT_OBJECT: build_input_object_def + TypeKind.INPUT_OBJECT: build_input_object_def, } def build_field_def_map(type_introspection): - return OrderedDict([ - (f['name'], GraphQLField( - type=get_output_type(f['type']), - description=f.get('description'), - resolver=no_execution, - deprecation_reason=f.get('deprecationReason'), - args=build_input_value_def_map(f.get('args'), GraphQLArgument))) - for f in type_introspection.get('fields', []) - ]) + return OrderedDict( + [ + ( + f["name"], + GraphQLField( + type=get_output_type(f["type"]), + description=f.get("description"), + resolver=no_execution, + deprecation_reason=f.get("deprecationReason"), + args=build_input_value_def_map(f.get("args"), GraphQLArgument), + ), + ) + for f in type_introspection.get("fields", []) + ] + ) def build_default_value(f): - default_value = f.get('defaultValue') + default_value = f.get("defaultValue") if default_value is None: return None - return value_from_ast(parse_value(default_value), get_input_type(f['type'])) + return value_from_ast(parse_value(default_value), get_input_type(f["type"])) def build_input_value_def_map(input_value_introspection, argument_type): - return OrderedDict([ - (f['name'], build_input_value(f, argument_type)) for f in input_value_introspection - ]) + return OrderedDict( + [ + (f["name"], build_input_value(f, argument_type)) + for f in input_value_introspection + ] + ) def build_input_value(input_value_introspection, argument_type): input_value = argument_type( - description=input_value_introspection['description'], - type=get_input_type(input_value_introspection['type']), - default_value=build_default_value(input_value_introspection) + description=input_value_introspection["description"], + type=get_input_type(input_value_introspection["type"]), + default_value=build_default_value(input_value_introspection), ) return input_value def build_directive(directive_introspection): # Support deprecated `on****` fields for building `locations`, as this # is used by GraphiQL which may need to support outdated servers. - locations = list(directive_introspection.get('locations', [])) + locations = list(directive_introspection.get("locations", [])) if not locations: locations = [] - if directive_introspection.get('onField', False): + if directive_introspection.get("onField", False): locations += list(DirectiveLocation.FIELD_LOCATIONS) - if directive_introspection.get('onOperation', False): + if directive_introspection.get("onOperation", False): locations += list(DirectiveLocation.OPERATION_LOCATIONS) - if directive_introspection.get('onFragment', False): + if directive_introspection.get("onFragment", False): locations += list(DirectiveLocation.FRAGMENT_LOCATIONS) return GraphQLDirective( - name=directive_introspection['name'], - description=directive_introspection.get('description'), + name=directive_introspection["name"], + description=directive_introspection.get("description"), # TODO: {} ? - args=build_input_value_def_map(directive_introspection.get('args', {}), GraphQLArgument), - locations=locations + args=build_input_value_def_map( + directive_introspection.get("args", {}), GraphQLArgument + ), + locations=locations, ) # Iterate through all types, getting the type definition for each, ensuring # that any type not directly referenced by a field will get created. - types = [get_named_type(type_introspection_name) for type_introspection_name in type_introspection_map.keys()] - - query_type = get_object_type(schema_introspection['queryType']) - mutation_type = get_object_type( - schema_introspection['mutationType']) if schema_introspection.get('mutationType') else None - subscription_type = get_object_type(schema_introspection['subscriptionType']) if \ - schema_introspection.get('subscriptionType') else None + types = [ + get_named_type(type_introspection_name) + for type_introspection_name in type_introspection_map.keys() + ] + + query_type = get_object_type(schema_introspection["queryType"]) + mutation_type = ( + get_object_type(schema_introspection["mutationType"]) + if schema_introspection.get("mutationType") + else None + ) + subscription_type = ( + get_object_type(schema_introspection["subscriptionType"]) + if schema_introspection.get("subscriptionType") + else None + ) - directives = [build_directive(d) for d in schema_introspection['directives']] \ - if schema_introspection['directives'] else [] + directives = ( + [build_directive(d) for d in schema_introspection["directives"]] + if schema_introspection["directives"] + else [] + ) return GraphQLSchema( query=query_type, mutation=mutation_type, subscription=subscription_type, directives=directives, - types=types + types=types, ) diff --git a/graphql/utils/concat_ast.py b/graphql/utils/concat_ast.py index 9abebe92..41401829 100644 --- a/graphql/utils/concat_ast.py +++ b/graphql/utils/concat_ast.py @@ -2,8 +2,14 @@ from ..language.ast import Document +if False: + from typing import Iterable + def concat_ast(asts): - return Document(definitions=list(itertools.chain.from_iterable( - document.definitions for document in asts - ))) + # type: (Iterable[Document]) -> Document + return Document( + definitions=list( + itertools.chain.from_iterable(document.definitions for document in asts) + ) + ) diff --git a/graphql/utils/extend_schema.py b/graphql/utils/extend_schema.py index e1bd3451..5c3e031c 100644 --- a/graphql/utils/extend_schema.py +++ b/graphql/utils/extend_schema.py @@ -3,17 +3,37 @@ from ..error import GraphQLError from ..language import ast from ..pyutils.ordereddict import OrderedDict -from ..type.definition import (GraphQLArgument, GraphQLEnumType, - GraphQLEnumValue, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, - GraphQLScalarType, GraphQLUnionType) -from ..type.introspection import (__Directive, __DirectiveLocation, - __EnumValue, __Field, __InputValue, __Schema, - __Type, __TypeKind) -from ..type.scalars import (GraphQLBoolean, GraphQLFloat, GraphQLID, - GraphQLInt, GraphQLString) +from ..type.definition import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLUnionType, +) +from ..type.introspection import ( + __Directive, + __DirectiveLocation, + __EnumValue, + __Field, + __InputValue, + __Schema, + __Type, + __TypeKind, +) +from ..type.scalars import ( + GraphQLBoolean, + GraphQLFloat, + GraphQLID, + GraphQLInt, + GraphQLString, +) from ..type.schema import GraphQLSchema from .value_from_ast import value_from_ast @@ -30,32 +50,37 @@ def extend_schema(schema, documentAST=None): This algorithm copies the provided schema, applying extensions while producing the copy. The original schema remains unaltered.""" - assert isinstance( - schema, GraphQLSchema), 'Must provide valid GraphQLSchema' + assert isinstance(schema, GraphQLSchema), "Must provide valid GraphQLSchema" assert documentAST and isinstance( - documentAST, ast.Document), 'Must provide valid Document AST' + documentAST, ast.Document + ), "Must provide valid Document AST" # Collect the type definitions and extensions found in the document. type_definition_map = {} type_extensions_map = defaultdict(list) for _def in documentAST.definitions: - if isinstance(_def, ( - ast.ObjectTypeDefinition, - ast.InterfaceTypeDefinition, - ast.EnumTypeDefinition, - ast.UnionTypeDefinition, - ast.ScalarTypeDefinition, - ast.InputObjectTypeDefinition, - )): + if isinstance( + _def, + ( + ast.ObjectTypeDefinition, + ast.InterfaceTypeDefinition, + ast.EnumTypeDefinition, + ast.UnionTypeDefinition, + ast.ScalarTypeDefinition, + ast.InputObjectTypeDefinition, + ), + ): # Sanity check that none of the defined types conflict with the # schema's existing types. type_name = _def.name.value if schema.get_type(type_name): raise GraphQLError( - ('Type "{}" already exists in the schema. It cannot also ' + - 'be defined in this type definition.').format(type_name), - [_def] + ( + 'Type "{}" already exists in the schema. It cannot also ' + + "be defined in this type definition." + ).format(type_name), + [_def], ) type_definition_map[type_name] = _def @@ -66,15 +91,16 @@ def extend_schema(schema, documentAST=None): existing_type = schema.get_type(extended_type_name) if not existing_type: raise GraphQLError( - ('Cannot extend type "{}" because it does not ' + - 'exist in the existing schema.').format(extended_type_name), - [_def.definition] + ( + 'Cannot extend type "{}" because it does not ' + + "exist in the existing schema." + ).format(extended_type_name), + [_def.definition], ) if not isinstance(existing_type, GraphQLObjectType): raise GraphQLError( - 'Cannot extend non-object type "{}".'.format( - extended_type_name), - [_def.definition] + 'Cannot extend non-object type "{}".'.format(extended_type_name), + [_def.definition], ) type_extensions_map[extended_type_name].append(_def) @@ -84,17 +110,18 @@ def extend_schema(schema, documentAST=None): def get_type_from_def(type_def): type = _get_named_type(type_def.name) - assert type, 'Invalid schema' + assert type, "Invalid schema" return type def get_type_from_AST(astNode): type = _get_named_type(astNode.name.value) if not type: raise GraphQLError( - ('Unknown type: "{}". Ensure that this type exists ' + - 'either in the original schema, or is added in a type definition.').format( - astNode.name.value), - [astNode] + ( + 'Unknown type: "{}". Ensure that this type exists ' + + "either in the original schema, or is added in a type definition." + ).format(astNode.name.value), + [astNode], ) return type @@ -162,10 +189,11 @@ def extend_implemented_interfaces(type): interface_name = namedType.name.value if any([_def.name == interface_name for _def in interfaces]): raise GraphQLError( - ('Type "{}" already implements "{}". ' + - 'It cannot also be implemented in this type extension.').format( - type.name, interface_name), - [namedType] + ( + 'Type "{}" already implements "{}". ' + + "It cannot also be implemented in this type extension." + ).format(type.name, interface_name), + [namedType], ) interfaces.append(get_type_from_AST(namedType)) @@ -190,10 +218,11 @@ def extend_field_map(type): field_name = field.name.value if field_name in old_field_map: raise GraphQLError( - ('Field "{}.{}" already exists in the ' + - 'schema. It cannot also be defined in this type extension.').format( - type.name, field_name), - [field] + ( + 'Field "{}.{}" already exists in the ' + + "schema. It cannot also be defined in this type extension." + ).format(type.name, field_name), + [field], ) new_field_map[field_name] = GraphQLField( build_field_type(field.type), @@ -217,7 +246,7 @@ def build_type(type_ast): ast.UnionTypeDefinition: build_union_type, ast.ScalarTypeDefinition: build_scalar_type, ast.EnumTypeDefinition: build_enum_type, - ast.InputObjectTypeDefinition: build_input_object_type + ast.InputObjectTypeDefinition: build_input_object_type, } func = _type_build.get(type(type_ast)) if func: @@ -265,8 +294,7 @@ def build_enum_type(type_ast): def build_input_object_type(type_ast): return GraphQLInputObjectType( type_ast.name.value, - fields=lambda: build_input_values( - type_ast.fields, GraphQLInputObjectField), + fields=lambda: build_input_values(type_ast.fields, GraphQLInputObjectField), ) def build_implemented_interfaces(type_ast): @@ -278,7 +306,8 @@ def build_field_map(type_ast): build_field_type(field.type), args=build_input_values(field.arguments), resolver=cannot_execute_client_schema, - ) for field in type_ast.fields + ) + for field in type_ast.fields } def build_input_values(values, input_type=GraphQLArgument): @@ -286,8 +315,7 @@ def build_input_values(values, input_type=GraphQLArgument): for value in values: type = build_field_type(value.type) input_values[value.name.value] = input_type( - type, - default_value=value_from_ast(value.default_value, type) + type, default_value=value_from_ast(value.default_value, type) ) return input_values @@ -309,31 +337,35 @@ def build_field_type(type_ast): # of the closure. type_def_cache = { - 'String': GraphQLString, - 'Int': GraphQLInt, - 'Float': GraphQLFloat, - 'Boolean': GraphQLBoolean, - 'ID': GraphQLID, - '__Schema': __Schema, - '__Directive': __Directive, - '__DirectiveLocation': __DirectiveLocation, - '__Type': __Type, - '__Field': __Field, - '__InputValue': __InputValue, - '__EnumValue': __EnumValue, - '__TypeKind': __TypeKind, + "String": GraphQLString, + "Int": GraphQLInt, + "Float": GraphQLFloat, + "Boolean": GraphQLBoolean, + "ID": GraphQLID, + "__Schema": __Schema, + "__Directive": __Directive, + "__DirectiveLocation": __DirectiveLocation, + "__Type": __Type, + "__Field": __Field, + "__InputValue": __InputValue, + "__EnumValue": __EnumValue, + "__TypeKind": __TypeKind, } # Get the root Query, Mutation, and Subscription types. query_type = get_type_from_def(schema.get_query_type()) existing_mutation_type = schema.get_mutation_type() - mutationType = existing_mutation_type and get_type_from_def( - existing_mutation_type) or None + mutationType = ( + existing_mutation_type and get_type_from_def(existing_mutation_type) or None + ) existing_subscription_type = schema.get_subscription_type() - subscription_type = existing_subscription_type and get_type_from_def( - existing_subscription_type) or None + subscription_type = ( + existing_subscription_type + and get_type_from_def(existing_subscription_type) + or None + ) # Iterate through all types, getting the type definition for each, ensuring # that any type not directly referenced by a field will get created. @@ -349,9 +381,10 @@ def build_field_type(type_ast): subscription=subscription_type, # Copy directives. directives=schema.get_directives(), - types=types + types=types, ) def cannot_execute_client_schema(*args, **kwargs): - raise Exception('Client Schema cannot be used for execution.') + raise Exception("Client Schema cannot be used for execution.") + diff --git a/graphql/utils/get_field_def.py b/graphql/utils/get_field_def.py index 5dbf4e18..c7efca75 100644 --- a/graphql/utils/get_field_def.py +++ b/graphql/utils/get_field_def.py @@ -1,26 +1,36 @@ -from ..type.definition import (GraphQLInterfaceType, GraphQLObjectType, - GraphQLUnionType) -from ..type.introspection import (SchemaMetaFieldDef, TypeMetaFieldDef, - TypeNameMetaFieldDef) +from ..type.definition import GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType +from ..type.introspection import ( + SchemaMetaFieldDef, + TypeMetaFieldDef, + TypeNameMetaFieldDef, +) +if False: + from ..language.ast import Field + from ..type.definition import GraphQLField, GraphQLInterfaceType, GraphQLObjectType + from ..type.schema import GraphQLSchema + from typing import Optional, Union -def get_field_def(schema, parent_type, field_ast): + +def get_field_def( + schema, # type: GraphQLSchema + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType] + field_ast, # type: Field +): + # type: (...) -> Optional[GraphQLField] """Not exactly the same as the executor's definition of get_field_def, in this statically evaluated environment we do not always have an Object type, and need to handle Interface and Union types.""" name = field_ast.name.value - if name == '__schema' and schema.get_query_type() == parent_type: + if name == "__schema" and schema.get_query_type() == parent_type: return SchemaMetaFieldDef - elif name == '__type' and schema.get_query_type() == parent_type: + elif name == "__type" and schema.get_query_type() == parent_type: return TypeMetaFieldDef - elif name == '__typename' and \ - isinstance(parent_type, ( - GraphQLObjectType, - GraphQLInterfaceType, - GraphQLUnionType, - )): + elif name == "__typename" and isinstance( + parent_type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType) + ): return TypeNameMetaFieldDef elif isinstance(parent_type, (GraphQLObjectType, GraphQLInterfaceType)): diff --git a/graphql/utils/get_operation_ast.py b/graphql/utils/get_operation_ast.py index 899e907c..74fd5a2c 100644 --- a/graphql/utils/get_operation_ast.py +++ b/graphql/utils/get_operation_ast.py @@ -1,7 +1,12 @@ from ..language import ast +if False: + from ..language.ast import Document, OperationDefinition + from typing import Optional + def get_operation_ast(document_ast, operation_name=None): + # type: (Document, Optional[str]) -> Optional[OperationDefinition] operation = None for definition in document_ast.definitions: diff --git a/graphql/utils/introspection_query.py b/graphql/utils/introspection_query.py index 2b87ec13..f8b82936 100644 --- a/graphql/utils/introspection_query.py +++ b/graphql/utils/introspection_query.py @@ -1,4 +1,4 @@ -introspection_query = ''' +introspection_query = """ query IntrospectionQuery { __schema { queryType { name } @@ -87,4 +87,4 @@ } } } -''' +""" diff --git a/graphql/utils/is_valid_literal_value.py b/graphql/utils/is_valid_literal_value.py index d329d3b2..f91c842b 100644 --- a/graphql/utils/is_valid_literal_value.py +++ b/graphql/utils/is_valid_literal_value.py @@ -1,12 +1,23 @@ from ..language import ast from ..language.printer import print_ast -from ..type.definition import (GraphQLEnumType, GraphQLInputObjectType, - GraphQLList, GraphQLNonNull, GraphQLScalarType) +from ..type.definition import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, +) -_empty_list = [] +if False: + from ..language.ast import ObjectValue, StringValue + from ..type.definition import GraphQLInputObjectType, GraphQLScalarType + from typing import Union, Any, List + +_empty_list = [] # type: List def is_valid_literal_value(type, value_ast): + # type: (Union[GraphQLInputObjectType, GraphQLScalarType], Any) -> List if isinstance(type, GraphQLNonNull): of_type = type.of_type if not value_ast: @@ -28,7 +39,7 @@ def is_valid_literal_value(type, value_ast): for i, item_ast in enumerate(value_ast.values): item_errors = is_valid_literal_value(item_type, item_ast) for error in item_errors: - errors.append(u'In element #{}: {}'.format(i, error)) + errors.append(u"In element #{}: {}".format(i, error)) return errors @@ -44,24 +55,36 @@ def is_valid_literal_value(type, value_ast): errors = [] for provided_field_ast in field_asts: if provided_field_ast.name.value not in fields: - errors.append(u'In field "{}": Unknown field.'.format(provided_field_ast.name.value)) + errors.append( + u'In field "{}": Unknown field.'.format( + provided_field_ast.name.value + ) + ) field_ast_map = {field_ast.name.value: field_ast for field_ast in field_asts} def get_field_ast_value(field_name): + # type: (str) -> Union[None, ObjectValue, StringValue] if field_name in field_ast_map: return field_ast_map[field_name].value + return None for field_name, field in fields.items(): - subfield_errors = is_valid_literal_value(field.type, get_field_ast_value(field_name)) - errors.extend(u'In field "{}": {}'.format(field_name, e) for e in subfield_errors) + subfield_errors = is_valid_literal_value( + field.type, get_field_ast_value(field_name) + ) + errors.extend( + u'In field "{}": {}'.format(field_name, e) for e in subfield_errors + ) return errors - assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), 'Must be input type' + assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type" parse_result = type.parse_literal(value_ast) if parse_result is None: - return [u'Expected type "{}", found {}.'.format(type.name, print_ast(value_ast))] + return [ + u'Expected type "{}", found {}.'.format(type.name, print_ast(value_ast)) + ] return _empty_list diff --git a/graphql/utils/is_valid_value.py b/graphql/utils/is_valid_value.py index b3d5d054..857b724a 100644 --- a/graphql/utils/is_valid_value.py +++ b/graphql/utils/is_valid_value.py @@ -7,13 +7,22 @@ from six import string_types -from ..type import (GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, GraphQLScalarType) +from ..type import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, +) -_empty_list = [] +if False: + from typing import Any, List + +_empty_list = [] # type: List def is_valid_value(value, type): + # type: (Any, Any) -> List """Given a type and any value, return True if that value is valid.""" if isinstance(type, GraphQLNonNull): of_type = type.of_type @@ -27,12 +36,14 @@ def is_valid_value(value, type): if isinstance(type, GraphQLList): item_type = type.of_type - if not isinstance(value, string_types) and isinstance(value, collections.Iterable): + if not isinstance(value, string_types) and isinstance( + value, collections.Iterable + ): errors = [] for i, item in enumerate(value): item_errors = is_valid_value(item, item_type) for error in item_errors: - errors.append(u'In element #{}: {}'.format(i, error)) + errors.append(u"In element #{}: {}".format(i, error)) return errors @@ -52,12 +63,13 @@ def is_valid_value(value, type): for field_name, field in fields.items(): subfield_errors = is_valid_value(value.get(field_name), field.type) - errors.extend(u'In field "{}": {}'.format(field_name, e) for e in subfield_errors) + errors.extend( + u'In field "{}": {}'.format(field_name, e) for e in subfield_errors + ) return errors - assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), \ - 'Must be input type' + assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type" # Scalar/Enum input checks to ensure the type can parse the value to # a non-null value. diff --git a/graphql/utils/quoted_or_list.py b/graphql/utils/quoted_or_list.py index 9f98bcd8..22d6aa48 100644 --- a/graphql/utils/quoted_or_list.py +++ b/graphql/utils/quoted_or_list.py @@ -1,19 +1,26 @@ import functools +if False: + from typing import List + + MAX_LENGTH = 5 def quoted_or_list(items): - '''Given [ A, B, C ] return '"A", "B" or "C"'.''' + # type: (List[str]) -> str + """Given [ A, B, C ] return '"A", "B" or "C"'.""" selected = items[:MAX_LENGTH] quoted_items = ('"{}"'.format(t) for t in selected) def quoted_or_text(text, quoted_and_index): index = quoted_and_index[0] quoted_item = quoted_and_index[1] - text += ((', ' if len(selected) > 2 and not index == len(selected) - 1 else ' ') + - ('or ' if index == len(selected) - 1 else '') + - quoted_item) + text += ( + (", " if len(selected) > 2 and not index == len(selected) - 1 else " ") + + ("or " if index == len(selected) - 1 else "") + + quoted_item + ) return text enumerated_items = enumerate(quoted_items) diff --git a/graphql/utils/schema_printer.py b/graphql/utils/schema_printer.py index 168a17ec..13146d10 100644 --- a/graphql/utils/schema_printer.py +++ b/graphql/utils/schema_printer.py @@ -1,71 +1,105 @@ from ..language.printer import print_ast -from ..type.definition import (GraphQLEnumType, GraphQLInputObjectType, - GraphQLInterfaceType, GraphQLObjectType, - GraphQLScalarType, GraphQLUnionType) +from ..type.definition import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLObjectType, + GraphQLScalarType, + GraphQLUnionType, +) from ..type.directives import DEFAULT_DEPRECATION_REASON from .ast_from_value import ast_from_value +if False: + from ..type.definition import ( + GraphQLArgument, + GraphQLType, + GraphQLField, + GraphQLInputObjectField, + GraphQLEnumValue, + ) + from ..type.schema import GraphQLSchema + from ..type.directives import GraphQLDirective + from typing import Any, Union, Callable + + def print_schema(schema): - return _print_filtered_schema(schema, lambda n: not(is_spec_directive(n)), _is_defined_type) + # type: (GraphQLSchema) -> str + return _print_filtered_schema( + schema, lambda n: not (is_spec_directive(n)), _is_defined_type + ) def print_introspection_schema(schema): + # type: (GraphQLSchema) -> str return _print_filtered_schema(schema, is_spec_directive, _is_introspection_type) def is_spec_directive(directive_name): - return directive_name in ('skip', 'include', 'deprecated') + # type: (str) -> bool + return directive_name in ("skip", "include", "deprecated") def _is_defined_type(typename): + # type: (Any) -> bool return not _is_introspection_type(typename) and not _is_builtin_scalar(typename) def _is_introspection_type(typename): - return typename.startswith('__') + # type: (str) -> bool + return typename.startswith("__") -_builtin_scalars = frozenset(['String', 'Boolean', 'Int', 'Float', 'ID']) +_builtin_scalars = frozenset(["String", "Boolean", "Int", "Float", "ID"]) def _is_builtin_scalar(typename): + # type: (str) -> bool return typename in _builtin_scalars def _print_filtered_schema(schema, directive_filter, type_filter): - return '\n\n'.join([ - _print_schema_definition(schema) - ] + [ - _print_directive(directive) - for directive in schema.get_directives() - if directive_filter(directive.name) - ] + [ - _print_type(type) - for typename, type in sorted(schema.get_type_map().items()) - if type_filter(typename) - ]) + '\n' + # type: (GraphQLSchema, Callable[[str], bool], Callable[[str], bool]) -> str + return ( + "\n\n".join( + [_print_schema_definition(schema)] + + [ + _print_directive(directive) + for directive in schema.get_directives() + if directive_filter(directive.name) + ] + + [ + _print_type(type) + for typename, type in sorted(schema.get_type_map().items()) + if type_filter(typename) + ] + ) + + "\n" + ) def _print_schema_definition(schema): + # type: (GraphQLSchema) -> str operation_types = [] query_type = schema.get_query_type() if query_type: - operation_types.append(' query: {}'.format(query_type)) + operation_types.append(" query: {}".format(query_type)) mutation_type = schema.get_mutation_type() if mutation_type: - operation_types.append(' mutation: {}'.format(mutation_type)) + operation_types.append(" mutation: {}".format(mutation_type)) subscription_type = schema.get_subscription_type() if subscription_type: - operation_types.append(' subscription: {}'.format(subscription_type)) + operation_types.append(" subscription: {}".format(subscription_type)) - return 'schema {{\n{}\n}}'.format('\n'.join(operation_types)) + return "schema {{\n{}\n}}".format("\n".join(operation_types)) def _print_type(type): + # type: (GraphQLType) -> str if isinstance(type, GraphQLScalarType): return _print_scalar(type) @@ -86,83 +120,100 @@ def _print_type(type): def _print_scalar(type): - return 'scalar {}'.format(type.name) + # type: (GraphQLScalarType) -> str + return "scalar {}".format(type.name) def _print_object(type): + # type: (GraphQLObjectType) -> str interfaces = type.interfaces - implemented_interfaces = \ - ' implements {}'.format(', '.join(i.name for i in interfaces)) if interfaces else '' + implemented_interfaces = ( + " implements {}".format(", ".join(i.name for i in interfaces)) + if interfaces + else "" + ) - return ( - 'type {}{} {{\n' - '{}\n' - '}}' - ).format(type.name, implemented_interfaces, _print_fields(type)) + return ("type {}{} {{\n" "{}\n" "}}").format( + type.name, implemented_interfaces, _print_fields(type) + ) def _print_interface(type): - return ( - 'interface {} {{\n' - '{}\n' - '}}' - ).format(type.name, _print_fields(type)) + # type: (GraphQLInterfaceType) -> str + return ("interface {} {{\n" "{}\n" "}}").format(type.name, _print_fields(type)) def _print_union(type): - return 'union {} = {}'.format(type.name, ' | '.join(str(t) for t in type.types)) + # type: (GraphQLUnionType) -> str + return "union {} = {}".format(type.name, " | ".join(str(t) for t in type.types)) def _print_enum(type): - return ( - 'enum {} {{\n' - '{}\n' - '}}' - ).format(type.name, '\n'.join(' ' + v.name + _print_deprecated(v) for v in type.values)) + # type: (GraphQLEnumType) -> str + return ("enum {} {{\n" "{}\n" "}}").format( + type.name, "\n".join(" " + v.name + _print_deprecated(v) for v in type.values) + ) def _print_input_object(type): - return ( - 'input {} {{\n' - '{}\n' - '}}' - ).format(type.name, '\n'.join(' ' + _print_input_value(name, field) for name, field in type.fields.items())) + # type: (GraphQLInputObjectType) -> str + return ("input {} {{\n" "{}\n" "}}").format( + type.name, + "\n".join( + " " + _print_input_value(name, field) + for name, field in type.fields.items() + ), + ) def _print_fields(type): - return '\n'.join(' {}{}: {}{}'.format(f_name, _print_args(f), f.type, _print_deprecated(f)) - for f_name, f in type.fields.items()) + # type: (Union[GraphQLObjectType, GraphQLInterfaceType]) -> str + return "\n".join( + " {}{}: {}{}".format(f_name, _print_args(f), f.type, _print_deprecated(f)) + for f_name, f in type.fields.items() + ) def _print_deprecated(field_or_enum_value): + # type: (Union[GraphQLField, GraphQLEnumValue]) -> str reason = field_or_enum_value.deprecation_reason if reason is None: - return '' - elif reason in ('', DEFAULT_DEPRECATION_REASON): - return ' @deprecated' + return "" + elif reason in ("", DEFAULT_DEPRECATION_REASON): + return " @deprecated" else: - return ' @deprecated(reason: {})'.format(print_ast(ast_from_value(reason))) + return " @deprecated(reason: {})".format(print_ast(ast_from_value(reason))) def _print_args(field_or_directives): + # type: (Union[GraphQLField, GraphQLDirective]) -> str if not field_or_directives.args: - return '' + return "" - return '({})'.format(', '.join(_print_input_value(arg_name, arg) for arg_name, arg in field_or_directives.args.items())) + return "({})".format( + ", ".join( + _print_input_value(arg_name, arg) + for arg_name, arg in field_or_directives.args.items() + ) + ) def _print_input_value(name, arg): + # type: (str, GraphQLArgument) -> str if arg.default_value is not None: - default_value = ' = ' + print_ast(ast_from_value(arg.default_value, arg.type)) + default_value = " = " + print_ast(ast_from_value(arg.default_value, arg.type)) else: - default_value = '' + default_value = "" - return '{}: {}{}'.format(name, arg.type, default_value) + return "{}: {}{}".format(name, arg.type, default_value) def _print_directive(directive): - return 'directive @{}{} on {}'.format(directive.name, _print_args(directive), ' | '.join(directive.locations)) + # type: (GraphQLDirective) -> str + return "directive @{}{} on {}".format( + directive.name, _print_args(directive), " | ".join(directive.locations) + ) -__all__ = ['print_schema', 'print_introspection_schema'] +__all__ = ["print_schema", "print_introspection_schema"] diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index 93ebb045..90388fd5 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -1,6 +1,22 @@ -from ..type.definition import (GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, - GraphQLUnionType, is_abstract_type) +from ..type.definition import ( + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLUnionType, + is_abstract_type, +) + +if False: + from ..type.typemap import GraphQLTypeMap + from ..type.definition import ( + GraphQLScalarType, + GraphQLInterfaceType, + GraphQLObjectType, + GraphQLUnionType, + ) + from ..type.schema import GraphQLSchema + from typing import Union def is_equal_type(type_a, type_b): @@ -17,32 +33,44 @@ def is_equal_type(type_a, type_b): def is_type_sub_type_of(schema, maybe_subtype, super_type): + # type: (GraphQLTypeMap, GraphQLScalarType, GraphQLScalarType) -> bool if maybe_subtype is super_type: return True if isinstance(super_type, GraphQLNonNull): if isinstance(maybe_subtype, GraphQLNonNull): - return is_type_sub_type_of(schema, maybe_subtype.of_type, super_type.of_type) + return is_type_sub_type_of( + schema, maybe_subtype.of_type, super_type.of_type + ) return False elif isinstance(maybe_subtype, GraphQLNonNull): return is_type_sub_type_of(schema, maybe_subtype.of_type, super_type) if isinstance(super_type, GraphQLList): if isinstance(maybe_subtype, GraphQLList): - return is_type_sub_type_of(schema, maybe_subtype.of_type, super_type.of_type) + return is_type_sub_type_of( + schema, maybe_subtype.of_type, super_type.of_type + ) return False elif isinstance(maybe_subtype, GraphQLList): return False - if is_abstract_type(super_type) and isinstance( - maybe_subtype, GraphQLObjectType) and schema.is_possible_type( - super_type, maybe_subtype): + if ( + is_abstract_type(super_type) + and isinstance(maybe_subtype, GraphQLObjectType) + and schema.is_possible_type(super_type, maybe_subtype) + ): return True return False -def do_types_overlap(schema, t1, t2): +def do_types_overlap( + schema, # type: GraphQLSchema + t1, # type: GraphQLObjectType + t2, # type: Union[GraphQLInterfaceType, GraphQLUnionType] +): + # type: (...) -> bool # print 'do_types_overlap', t1, t2 if t1 == t2: # print '1' @@ -52,7 +80,12 @@ def do_types_overlap(schema, t1, t2): if isinstance(t2, (GraphQLInterfaceType, GraphQLUnionType)): # If both types are abstract, then determine if there is any intersection # between possible concrete types of each. - s = any([schema.is_possible_type(t2, type) for type in schema.get_possible_types(t1)]) + s = any( + [ + schema.is_possible_type(t2, type) + for type in schema.get_possible_types(t1) + ] + ) # print '2',s return s # Determine if the latter type is a possible concrete type of the former. diff --git a/graphql/utils/type_from_ast.py b/graphql/utils/type_from_ast.py index 8689f27a..58719c41 100644 --- a/graphql/utils/type_from_ast.py +++ b/graphql/utils/type_from_ast.py @@ -1,8 +1,14 @@ from ..language import ast from ..type.definition import GraphQLList, GraphQLNonNull +if False: + from ..language.ast import ListType, NamedType, NonNullType + from ..type.schema import GraphQLSchema + from typing import Any, Union + def type_from_ast(schema, input_type_ast): + # type: (GraphQLSchema, Union[ListType, NamedType, NonNullType]) -> Any if isinstance(input_type_ast, ast.ListType): inner_type = type_from_ast(schema, input_type_ast.type) if inner_type: @@ -17,5 +23,5 @@ def type_from_ast(schema, input_type_ast): else: return None - assert isinstance(input_type_ast, ast.NamedType), 'Must be a type name.' + assert isinstance(input_type_ast, ast.NamedType), "Must be a type name." return schema.get_type(input_type_ast.name.value) diff --git a/graphql/utils/type_info.py b/graphql/utils/type_info.py index c74beca7..de07ddb7 100644 --- a/graphql/utils/type_info.py +++ b/graphql/utils/type_info.py @@ -1,14 +1,38 @@ import six from ..language import visitor_meta -from ..type.definition import (GraphQLInputObjectType, GraphQLList, - get_named_type, get_nullable_type, - is_composite_type) +from ..type.definition import ( + GraphQLInputObjectType, + GraphQLList, + get_named_type, + get_nullable_type, + is_composite_type, +) from .get_field_def import get_field_def from .type_from_ast import type_from_ast +if False: + from ..type.schema import GraphQLSchema + from ..type.definition import ( + GraphQLType, + GraphQLInputObjectType, + GraphQLField, + GraphQLArgument, + ) + from ..type.directives import GraphQLDirective + from ..language.ast import ( + SelectionSet, + Field, + OperationDefinition, + InlineFragment, + Argument, + ObjectField, + ) + from typing import Callable, Optional, Any, List + def pop(lst): + # type: (Any) -> None if lst: lst.pop() @@ -16,52 +40,76 @@ def pop(lst): # noinspection PyPep8Naming @six.add_metaclass(visitor_meta.VisitorMeta) class TypeInfo(object): - __slots__ = '_schema', '_type_stack', '_parent_type_stack', '_input_type_stack', '_field_def_stack', '_directive', \ - '_argument', '_get_field_def_fn' + __slots__ = ( + "_schema", + "_type_stack", + "_parent_type_stack", + "_input_type_stack", + "_field_def_stack", + "_directive", + "_argument", + "_get_field_def_fn", + ) def __init__(self, schema, get_field_def_fn=get_field_def): + # type: (GraphQLSchema, Callable) -> None self._schema = schema - self._type_stack = [] - self._parent_type_stack = [] - self._input_type_stack = [] - self._field_def_stack = [] - self._directive = None - self._argument = None + self._type_stack = [] # type: List[GraphQLType] + self._parent_type_stack = [] # type: List[GraphQLType] + self._input_type_stack = [] # type: List[GraphQLInputObjectType] + self._field_def_stack = [] # type: List[GraphQLField] + self._directive = None # type: Optional[GraphQLDirective] + self._argument = None # type: Optional[GraphQLArgument] self._get_field_def_fn = get_field_def_fn def get_type(self): + # type: () -> Optional[GraphQLType] if self._type_stack: return self._type_stack[-1] + return None def get_parent_type(self): + # type: () -> Optional[GraphQLType] if self._parent_type_stack: return self._parent_type_stack[-1] + return None def get_input_type(self): + # type: () -> Optional[GraphQLInputObjectType] if self._input_type_stack: return self._input_type_stack[-1] + return None def get_field_def(self): + # type: () -> Optional[GraphQLField] if self._field_def_stack: return self._field_def_stack[-1] + return None def get_directive(self): + # type: () -> Optional[Any] return self._directive def get_argument(self): + # type: () -> Optional[GraphQLArgument] return self._argument def leave(self, node): - method = self._get_leave_handler(type(node)) + # type: (Any) -> Optional[Any] + method = self._get_leave_handler(type(node)) # type: ignore if method: return method(self) + return None def enter(self, node): - method = self._get_enter_handler(type(node)) + # type: (Any) -> Optional[Any] + method = self._get_enter_handler(type(node)) # type: ignore if method: return method(self, node) + return None def enter_SelectionSet(self, node): + # type: (SelectionSet) -> None named_type = get_named_type(self.get_type()) composite_type = None if is_composite_type(named_type): @@ -69,30 +117,37 @@ def enter_SelectionSet(self, node): self._parent_type_stack.append(composite_type) def enter_Field(self, node): + # type: (Field) -> None parent_type = self.get_parent_type() field_def = None if parent_type: field_def = self._get_field_def_fn(self._schema, parent_type, node) self._field_def_stack.append(field_def) - self._type_stack.append(field_def and field_def.type) + self._type_stack.append(field_def.type if field_def else None) def enter_Directive(self, node): self._directive = self._schema.get_directive(node.name.value) def enter_OperationDefinition(self, node): + # type: (OperationDefinition) -> None definition_type = None - if node.operation == 'query': + if node.operation == "query": definition_type = self._schema.get_query_type() - elif node.operation == 'mutation': + elif node.operation == "mutation": definition_type = self._schema.get_mutation_type() - elif node.operation == 'subscription': + elif node.operation == "subscription": definition_type = self._schema.get_subscription_type() self._type_stack.append(definition_type) def enter_InlineFragment(self, node): + # type: (InlineFragment) -> None type_condition_ast = node.type_condition - type = type_from_ast(self._schema, type_condition_ast) if type_condition_ast else self.get_type() + type = ( + type_from_ast(self._schema, type_condition_ast) + if type_condition_ast + else self.get_type() + ) self._type_stack.append(type) enter_FragmentDefinition = enter_InlineFragment @@ -101,6 +156,7 @@ def enter_VariableDefinition(self, node): self._input_type_stack.append(type_from_ast(self._schema, node.type)) def enter_Argument(self, node): + # type: (Argument) -> None arg_def = None arg_type = None field_or_directive = self.get_directive() or self.get_field_def() @@ -118,6 +174,7 @@ def enter_ListValue(self, node): ) def enter_ObjectField(self, node): + # type: (ObjectField) -> None object_type = get_named_type(self.get_input_type()) field_type = None if isinstance(object_type, GraphQLInputObjectType): @@ -126,9 +183,11 @@ def enter_ObjectField(self, node): self._input_type_stack.append(field_type) def leave_SelectionSet(self): + # type: () -> None pop(self._parent_type_stack) def leave_Field(self): + # type: () -> None pop(self._field_def_stack) pop(self._type_stack) @@ -136,6 +195,7 @@ def leave_Directive(self): self._directive = None def leave_OperationDefinition(self): + # type: () -> None pop(self._type_stack) leave_InlineFragment = leave_OperationDefinition @@ -145,10 +205,12 @@ def leave_VariableDefinition(self): pop(self._input_type_stack) def leave_Argument(self): + # type: () -> None self._argument = None pop(self._input_type_stack) def leave_ListValue(self): + # type: () -> None pop(self._input_type_stack) leave_ObjectField = leave_ListValue diff --git a/graphql/utils/undefined.py b/graphql/utils/undefined.py index 19ef2ba0..db8f80a9 100644 --- a/graphql/utils/undefined.py +++ b/graphql/utils/undefined.py @@ -2,12 +2,14 @@ class _Undefined(object): """A representation of an Undefined value distinct from a None value""" def __bool__(self): + # type: () -> bool return False __nonzero__ = __bool__ def __repr__(self): - return 'Undefined' + # type: () -> str + return "Undefined" Undefined = _Undefined() diff --git a/graphql/utils/value_from_ast.py b/graphql/utils/value_from_ast.py index 55026680..f7a730f0 100644 --- a/graphql/utils/value_from_ast.py +++ b/graphql/utils/value_from_ast.py @@ -1,9 +1,20 @@ from ..language import ast -from ..type import (GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, GraphQLScalarType) +from ..type import ( + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, +) + +if False: + from ..language.ast import Node + from ..type.definition import GraphQLType + from typing import Any, Dict, Union, Optional, List def value_from_ast(value_ast, type, variables=None): + # type: (Optional[Node], GraphQLType, Optional[Dict[str, Union[List, Dict, int, float, bool, str, None]]]) -> Union[List, Dict, int, float, bool, str, None] """Given a type and a value AST node known to match this type, build a runtime value.""" if isinstance(type, GraphQLNonNull): @@ -26,8 +37,10 @@ def value_from_ast(value_ast, type, variables=None): if isinstance(type, GraphQLList): item_type = type.of_type if isinstance(value_ast, ast.ListValue): - return [value_from_ast(item_ast, item_type, variables) - for item_ast in value_ast.values] + return [ + value_from_ast(item_ast, item_type, variables) + for item_ast in value_ast.values + ] else: return [value_from_ast(value_ast, item_type, variables)] @@ -39,8 +52,8 @@ def value_from_ast(value_ast, type, variables=None): field_asts = {} - for field in value_ast.fields: - field_asts[field.name.value] = field + for field_ast in value_ast.fields: + field_asts[field_ast.name.value] = field_ast obj = {} for field_name, field in fields.items(): @@ -52,11 +65,9 @@ def value_from_ast(value_ast, type, variables=None): continue - field_ast = field_asts.get(field_name) + field_ast = field_asts[field_name] field_value_ast = field_ast.value - field_value = value_from_ast( - field_value_ast, field.type, variables - ) + field_value = value_from_ast(field_value_ast, field.type, variables) # We use out_name as the output name for the # dict if exists @@ -64,7 +75,6 @@ def value_from_ast(value_ast, type, variables=None): return type.create_container(obj) - assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), \ - 'Must be input type' + assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type" return type.parse_literal(value_ast) diff --git a/graphql/validation/rules/arguments_of_correct_type.py b/graphql/validation/rules/arguments_of_correct_type.py index 011fae79..416e36bd 100644 --- a/graphql/validation/rules/arguments_of_correct_type.py +++ b/graphql/validation/rules/arguments_of_correct_type.py @@ -3,22 +3,36 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule +if False: + from ...language.ast import Argument + from typing import Any, List, Union -class ArgumentsOfCorrectType(ValidationRule): - def enter_Argument(self, node, key, parent, path, ancestors): +class ArgumentsOfCorrectType(ValidationRule): + def enter_Argument( + self, + node, # type: Argument + key, # type: int + parent, # type: List[Argument] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> bool arg_def = self.context.get_argument() if arg_def: errors = is_valid_literal_value(arg_def.type, node.value) if errors: - self.context.report_error(GraphQLError( - self.bad_value_message(node.name.value, arg_def.type, - print_ast(node.value), errors), - [node.value] - )) + self.context.report_error( + GraphQLError( + self.bad_value_message( + node.name.value, arg_def.type, print_ast(node.value), errors + ), + [node.value], + ) + ) return False @staticmethod def bad_value_message(arg_name, type, value, verbose_errors): - message = (u'\n' + u'\n'.join(verbose_errors)) if verbose_errors else '' + message = (u"\n" + u"\n".join(verbose_errors)) if verbose_errors else "" return 'Argument "{}" has invalid value {}.{}'.format(arg_name, value, message) diff --git a/graphql/validation/rules/base.py b/graphql/validation/rules/base.py index 43bb53b7..368dc168 100644 --- a/graphql/validation/rules/base.py +++ b/graphql/validation/rules/base.py @@ -1,8 +1,12 @@ from ...language.visitor import Visitor +if False: + from ..validation import ValidationContext + class ValidationRule(Visitor): - __slots__ = 'context', + __slots__ = ("context",) def __init__(self, context): + # type: (ValidationContext) -> None self.context = context diff --git a/graphql/validation/rules/default_values_of_correct_type.py b/graphql/validation/rules/default_values_of_correct_type.py index ad6346b4..3b2f52f8 100644 --- a/graphql/validation/rules/default_values_of_correct_type.py +++ b/graphql/validation/rules/default_values_of_correct_type.py @@ -4,30 +4,47 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule +if False: + from ...language.ast import Document, OperationDefinition, SelectionSet + from typing import List, Union -class DefaultValuesOfCorrectType(ValidationRule): +class DefaultValuesOfCorrectType(ValidationRule): def enter_VariableDefinition(self, node, key, parent, path, ancestors): name = node.variable.name.value default_value = node.default_value type = self.context.get_input_type() if isinstance(type, GraphQLNonNull) and default_value: - self.context.report_error(GraphQLError( - self.default_for_non_null_arg_message(name, type, type.of_type), - [default_value] - )) + self.context.report_error( + GraphQLError( + self.default_for_non_null_arg_message(name, type, type.of_type), + [default_value], + ) + ) if type and default_value: errors = is_valid_literal_value(type, default_value) if errors: - self.context.report_error(GraphQLError( - self.bad_value_for_default_arg_message(name, type, print_ast(default_value), errors), - [default_value] - )) + self.context.report_error( + GraphQLError( + self.bad_value_for_default_arg_message( + name, type, print_ast(default_value), errors + ), + [default_value], + ) + ) return False - def enter_SelectionSet(self, node, key, parent, path, ancestors): + def enter_SelectionSet( + self, + node, # type: SelectionSet + key, # type: str + parent, # type: OperationDefinition + path, # type: List[Union[int, str]] + ancestors, # type: List[Union[List[OperationDefinition], Document]] + ): + # type: (...) -> bool return False def enter_FragmentDefinition(self, node, key, parent, path, ancestors): @@ -35,10 +52,14 @@ def enter_FragmentDefinition(self, node, key, parent, path, ancestors): @staticmethod def default_for_non_null_arg_message(var_name, type, guess_type): - return u'Variable "${}" of type "{}" is required and will not use the default value. ' \ - u'Perhaps you meant to use type "{}".'.format(var_name, type, guess_type) + return ( + u'Variable "${}" of type "{}" is required and will not use the default value. ' + u'Perhaps you meant to use type "{}".'.format(var_name, type, guess_type) + ) @staticmethod def bad_value_for_default_arg_message(var_name, type, value, verbose_errors): - message = (u'\n' + u'\n'.join(verbose_errors)) if verbose_errors else u'' - return u'Variable "${}" of type "{}" has invalid default value: {}.{}'.format(var_name, type, value, message) + message = (u"\n" + u"\n".join(verbose_errors)) if verbose_errors else u"" + return u'Variable "${}" of type "{}" has invalid default value: {}.{}'.format( + var_name, type, value, message + ) diff --git a/graphql/validation/rules/fields_on_correct_type.py b/graphql/validation/rules/fields_on_correct_type.py index 55bb2221..4ce057eb 100644 --- a/graphql/validation/rules/fields_on_correct_type.py +++ b/graphql/validation/rules/fields_on_correct_type.py @@ -2,12 +2,15 @@ from ...error import GraphQLError from ...pyutils.ordereddict import OrderedDict -from ...type.definition import (GraphQLInterfaceType, GraphQLObjectType, - GraphQLUnionType) +from ...type.definition import GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType from ...utils.quoted_or_list import quoted_or_list from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +if False: + from ...language.ast import Field, InlineFragment + from typing import Any, List, Union + try: # Python 2 from itertools import izip @@ -16,8 +19,7 @@ izip = zip -def _undefined_field_message(field_name, type, suggested_types, - suggested_fields): +def _undefined_field_message(field_name, type, suggested_types, suggested_fields): message = 'Cannot query field "{}" on type "{}".'.format(field_name, type) if suggested_types: @@ -35,13 +37,21 @@ class OrderedCounter(Counter, OrderedDict): class FieldsOnCorrectType(ValidationRule): - '''Fields on correct type + """Fields on correct type A GraphQL document is only valid if all fields selected are defined by the parent type, or are an allowed meta field such as __typenamme - ''' - - def enter_Field(self, node, key, parent, path, ancestors): + """ + + def enter_Field( + self, + node, # type: Field + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[Field]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None parent_type = self.context.get_parent_type() if not parent_type: return @@ -53,22 +63,35 @@ def enter_Field(self, node, key, parent, path, ancestors): field_name = node.name.value # First determine if there are any suggested types to condition on. - suggested_type_names = get_suggested_type_names(schema, parent_type, field_name) + suggested_type_names = get_suggested_type_names( + schema, parent_type, field_name + ) # if there are no suggested types perhaps it was a typo? - suggested_field_names = [] if suggested_type_names else get_suggested_field_names(schema, parent_type, field_name) + suggested_field_names = ( + [] + if suggested_type_names + else get_suggested_field_names(schema, parent_type, field_name) + ) # report an error including helpful suggestions. - self.context.report_error(GraphQLError( - _undefined_field_message(field_name, parent_type.name, suggested_type_names, suggested_field_names), - [node] - )) + self.context.report_error( + GraphQLError( + _undefined_field_message( + field_name, + parent_type.name, + suggested_type_names, + suggested_field_names, + ), + [node], + ) + ) def get_suggested_type_names(schema, output_type, field_name): - '''Go through all of the implementations of type, as well as the interfaces + """Go through all of the implementations of type, as well as the interfaces that they implement. If any of those types include the provided field, suggest them, sorted by how often the type is referenced, starting - with Interfaces.''' + with Interfaces.""" if isinstance(output_type, (GraphQLInterfaceType, GraphQLUnionType)): suggested_object_types = [] @@ -86,11 +109,15 @@ def get_suggested_type_names(schema, output_type, field_name): # This interface type defines this field. interface_usage_count[possible_interface.name] = ( - interface_usage_count.get(possible_interface.name, 0) + 1) + interface_usage_count.get(possible_interface.name, 0) + 1 + ) # Suggest interface types based on how common they are. - suggested_interface_types = sorted(list(interface_usage_count.keys()), key=lambda k: interface_usage_count[k], - reverse=True) + suggested_interface_types = sorted( + list(interface_usage_count.keys()), + key=lambda k: interface_usage_count[k], + reverse=True, + ) # Suggest both interface and object types. suggested_interface_types.extend(suggested_object_types) @@ -101,8 +128,8 @@ def get_suggested_type_names(schema, output_type, field_name): def get_suggested_field_names(schema, graphql_type, field_name): - '''For the field name provided, determine if there are any similar field names - that may be the result of a typo.''' + """For the field name provided, determine if there are any similar field names + that may be the result of a typo.""" if isinstance(graphql_type, (GraphQLInterfaceType, GraphQLObjectType)): possible_field_names = list(graphql_type.fields.keys()) diff --git a/graphql/validation/rules/fragments_on_composite_types.py b/graphql/validation/rules/fragments_on_composite_types.py index a95e247c..1873ac5f 100644 --- a/graphql/validation/rules/fragments_on_composite_types.py +++ b/graphql/validation/rules/fragments_on_composite_types.py @@ -3,26 +3,45 @@ from ...type.definition import is_composite_type from .base import ValidationRule +if False: + from ...language.ast import Field, InlineFragment + from typing import Any, List, Union -class FragmentsOnCompositeTypes(ValidationRule): - def enter_InlineFragment(self, node, key, parent, path, ancestors): +class FragmentsOnCompositeTypes(ValidationRule): + def enter_InlineFragment( + self, + node, # type: InlineFragment + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[InlineFragment]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None type = self.context.get_type() if node.type_condition and type and not is_composite_type(type): - self.context.report_error(GraphQLError( - self.inline_fragment_on_non_composite_error_message(print_ast(node.type_condition)), - [node.type_condition] - )) + self.context.report_error( + GraphQLError( + self.inline_fragment_on_non_composite_error_message( + print_ast(node.type_condition) + ), + [node.type_condition], + ) + ) def enter_FragmentDefinition(self, node, key, parent, path, ancestors): type = self.context.get_type() if type and not is_composite_type(type): - self.context.report_error(GraphQLError( - self.fragment_on_non_composite_error_message(node.name.value, print_ast(node.type_condition)), - [node.type_condition] - )) + self.context.report_error( + GraphQLError( + self.fragment_on_non_composite_error_message( + node.name.value, print_ast(node.type_condition) + ), + [node.type_condition], + ) + ) @staticmethod def inline_fragment_on_non_composite_error_message(type): @@ -30,4 +49,6 @@ def inline_fragment_on_non_composite_error_message(type): @staticmethod def fragment_on_non_composite_error_message(frag_name, type): - return 'Fragment "{}" cannot condition on non composite type "{}".'.format(frag_name, type) + return 'Fragment "{}" cannot condition on non composite type "{}".'.format( + frag_name, type + ) diff --git a/graphql/validation/rules/known_argument_names.py b/graphql/validation/rules/known_argument_names.py index 2b586039..b9a7b1fd 100644 --- a/graphql/validation/rules/known_argument_names.py +++ b/graphql/validation/rules/known_argument_names.py @@ -4,26 +4,41 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +if False: + from ...language.ast import Argument + from typing import Any, List, Union + def _unknown_arg_message(arg_name, field_name, type, suggested_args): - message = 'Unknown argument "{}" on field "{}" of type "{}".'.format(arg_name, field_name, type) + message = 'Unknown argument "{}" on field "{}" of type "{}".'.format( + arg_name, field_name, type + ) if suggested_args: - message += ' Did you mean {}?'.format(quoted_or_list(suggested_args)) + message += " Did you mean {}?".format(quoted_or_list(suggested_args)) return message def _unknown_directive_arg_message(arg_name, directive_name, suggested_args): - message = 'Unknown argument "{}" on directive "@{}".'.format(arg_name, directive_name) + message = 'Unknown argument "{}" on directive "@{}".'.format( + arg_name, directive_name + ) if suggested_args: - message += ' Did you mean {}?'.format(quoted_or_list(suggested_args)) + message += " Did you mean {}?".format(quoted_or_list(suggested_args)) return message class KnownArgumentNames(ValidationRule): - - def enter_Argument(self, node, key, parent, path, ancestors): + def enter_Argument( + self, + node, # type: Argument + key, # type: int + parent, # type: List[Argument] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None argument_of = ancestors[-1] if isinstance(argument_of, ast.Field): @@ -36,18 +51,20 @@ def enter_Argument(self, node, key, parent, path, ancestors): if not field_arg_def: parent_type = self.context.get_parent_type() assert parent_type - self.context.report_error(GraphQLError( - _unknown_arg_message( - node.name.value, - argument_of.name.value, - parent_type.name, - suggestion_list( + self.context.report_error( + GraphQLError( + _unknown_arg_message( node.name.value, - (arg_name for arg_name in field_def.args.keys()) - ) - ), - [node] - )) + argument_of.name.value, + parent_type.name, + suggestion_list( + node.name.value, + (arg_name for arg_name in field_def.args.keys()), + ), + ), + [node], + ) + ) elif isinstance(argument_of, ast.Directive): directive = self.context.get_directive() @@ -57,14 +74,16 @@ def enter_Argument(self, node, key, parent, path, ancestors): directive_arg_def = directive.args.get(node.name.value) if not directive_arg_def: - self.context.report_error(GraphQLError( - _unknown_directive_arg_message( - node.name.value, - directive.name, - suggestion_list( + self.context.report_error( + GraphQLError( + _unknown_directive_arg_message( node.name.value, - (arg_name for arg_name in directive.args.keys()) - ) - ), - [node] - )) + directive.name, + suggestion_list( + node.name.value, + (arg_name for arg_name in directive.args.keys()), + ), + ), + [node], + ) + ) diff --git a/graphql/validation/rules/known_type_names.py b/graphql/validation/rules/known_type_names.py index d7d13699..7f147a98 100644 --- a/graphql/validation/rules/known_type_names.py +++ b/graphql/validation/rules/known_type_names.py @@ -3,17 +3,20 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +if False: + from ...language.ast import NamedType + from typing import Any + def _unknown_type_message(type, suggested_types): message = 'Unknown type "{}".'.format(type) if suggested_types: - message += ' Perhaps you meant {}?'.format(quoted_or_list(suggested_types)) + message += " Perhaps you meant {}?".format(quoted_or_list(suggested_types)) return message class KnownTypeNames(ValidationRule): - def enter_ObjectTypeDefinition(self, node, *args): return False @@ -27,6 +30,7 @@ def enter_InputObjectTypeDefinition(self, node, *args): return False def enter_NamedType(self, node, *args): + # type: (NamedType, *Any) -> None schema = self.context.get_schema() type_name = node.name.value type = schema.get_type(type_name) @@ -36,8 +40,8 @@ def enter_NamedType(self, node, *args): GraphQLError( _unknown_type_message( type_name, - suggestion_list(type_name, list(schema.get_type_map().keys())) + suggestion_list(type_name, list(schema.get_type_map().keys())), ), - [node] + [node], ) ) diff --git a/graphql/validation/rules/lone_anonymous_operation.py b/graphql/validation/rules/lone_anonymous_operation.py index 462a67f3..2699f759 100644 --- a/graphql/validation/rules/lone_anonymous_operation.py +++ b/graphql/validation/rules/lone_anonymous_operation.py @@ -2,22 +2,42 @@ from ...language import ast from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import Any, List, Optional, Union + class LoneAnonymousOperation(ValidationRule): - __slots__ = 'operation_count', + __slots__ = ("operation_count",) def __init__(self, context): + # type: (ValidationContext) -> None self.operation_count = 0 super(LoneAnonymousOperation, self).__init__(context) def enter_Document(self, node, key, parent, path, ancestors): - self.operation_count = \ - sum(1 for definition in node.definitions if isinstance(definition, ast.OperationDefinition)) + # type: (Document, Optional[Any], Optional[Any], List, List) -> None + self.operation_count = sum( + 1 + for definition in node.definitions + if isinstance(definition, ast.OperationDefinition) + ) - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> None if not node.name and self.operation_count > 1: - self.context.report_error(GraphQLError(self.anonymous_operation_not_alone_message(), [node])) + self.context.report_error( + GraphQLError(self.anonymous_operation_not_alone_message(), [node]) + ) @staticmethod def anonymous_operation_not_alone_message(): - return 'This anonymous operation must be the only defined operation.' + return "This anonymous operation must be the only defined operation." diff --git a/graphql/validation/rules/no_fragment_cycles.py b/graphql/validation/rules/no_fragment_cycles.py index d2e0d79f..ccd9f8f3 100644 --- a/graphql/validation/rules/no_fragment_cycles.py +++ b/graphql/validation/rules/no_fragment_cycles.py @@ -1,18 +1,32 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class NoFragmentCycles(ValidationRule): - __slots__ = 'errors', 'visited_frags', 'spread_path', 'spread_path_index_by_name' + __slots__ = "errors", "visited_frags", "spread_path", "spread_path_index_by_name" def __init__(self, context): + # type: (ValidationContext) -> None super(NoFragmentCycles, self).__init__(context) self.errors = [] self.visited_frags = set() self.spread_path = [] self.spread_path_index_by_name = {} - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> bool return False def enter_FragmentDefinition(self, node, key, parent, path, ancestors): @@ -43,17 +57,18 @@ def detect_cycle_recursive(self, fragment): self.spread_path.pop() else: cycle_path = self.spread_path[cycle_index:] - self.context.report_error(GraphQLError( - self.cycle_error_message( - spread_name, - [s.name.value for s in cycle_path] - ), - cycle_path + [spread_node] - )) + self.context.report_error( + GraphQLError( + self.cycle_error_message( + spread_name, [s.name.value for s in cycle_path] + ), + cycle_path + [spread_node], + ) + ) self.spread_path_index_by_name[fragment_name] = None @staticmethod def cycle_error_message(fragment_name, spread_names): - via = ' via {}'.format(', '.join(spread_names)) if spread_names else '' + via = " via {}".format(", ".join(spread_names)) if spread_names else "" return 'Cannot spread fragment "{}" within itself{}.'.format(fragment_name, via) diff --git a/graphql/validation/rules/no_undefined_variables.py b/graphql/validation/rules/no_undefined_variables.py index 81c9c495..afa0db1b 100644 --- a/graphql/validation/rules/no_undefined_variables.py +++ b/graphql/validation/rules/no_undefined_variables.py @@ -1,11 +1,17 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class NoUndefinedVariables(ValidationRule): - __slots__ = 'defined_variable_names', + __slots__ = ("defined_variable_names",) def __init__(self, context): + # type: (ValidationContext) -> None self.defined_variable_names = set() super(NoUndefinedVariables, self).__init__(context) @@ -17,20 +23,40 @@ def undefined_var_message(var_name, op_name=None): ) return 'Variable "${}" is not defined.'.format(var_name) - def enter_OperationDefinition(self, operation, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + operation, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> None self.defined_variable_names = set() - def leave_OperationDefinition(self, operation, key, parent, path, ancestors): + def leave_OperationDefinition( + self, + operation, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[str] + ancestors, # type: List[Document] + ): + # type: (...) -> None usages = self.context.get_recursive_variable_usages(operation) for variable_usage in usages: node = variable_usage.node var_name = node.name.value if var_name not in self.defined_variable_names: - self.context.report_error(GraphQLError( - self.undefined_var_message(var_name, operation.name and operation.name.value), - [node, operation] - )) + self.context.report_error( + GraphQLError( + self.undefined_var_message( + var_name, operation.name and operation.name.value + ), + [node, operation], + ) + ) def enter_VariableDefinition(self, node, key, parent, path, ancestors): self.defined_variable_names.add(node.variable.name.value) diff --git a/graphql/validation/rules/no_unused_fragments.py b/graphql/validation/rules/no_unused_fragments.py index 8d35f483..b4ba428a 100644 --- a/graphql/validation/rules/no_unused_fragments.py +++ b/graphql/validation/rules/no_unused_fragments.py @@ -1,16 +1,35 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union, Any, Optional + class NoUnusedFragments(ValidationRule): - __slots__ = 'fragment_definitions', 'operation_definitions', 'fragment_adjacencies', 'spread_names' + __slots__ = ( + "fragment_definitions", + "operation_definitions", + "fragment_adjacencies", + "spread_names", + ) def __init__(self, context): + # type: (ValidationContext) -> None super(NoUnusedFragments, self).__init__(context) self.operation_definitions = [] self.fragment_definitions = [] - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> bool self.operation_definitions.append(node) return False @@ -19,6 +38,7 @@ def enter_FragmentDefinition(self, node, key, parent, path, ancestors): return False def leave_Document(self, node, key, parent, path, ancestors): + # type: (Document, Optional[Any], Optional[Any], List, List) -> None fragment_names_used = set() for operation in self.operation_definitions: @@ -28,10 +48,12 @@ def leave_Document(self, node, key, parent, path, ancestors): for fragment_definition in self.fragment_definitions: if fragment_definition.name.value not in fragment_names_used: - self.context.report_error(GraphQLError( - self.unused_fragment_message(fragment_definition.name.value), - [fragment_definition] - )) + self.context.report_error( + GraphQLError( + self.unused_fragment_message(fragment_definition.name.value), + [fragment_definition], + ) + ) @staticmethod def unused_fragment_message(fragment_name): diff --git a/graphql/validation/rules/no_unused_variables.py b/graphql/validation/rules/no_unused_variables.py index a799e826..ed7b77fc 100644 --- a/graphql/validation/rules/no_unused_variables.py +++ b/graphql/validation/rules/no_unused_variables.py @@ -1,18 +1,40 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class NoUnusedVariables(ValidationRule): - __slots__ = 'variable_definitions' + __slots__ = "variable_definitions" def __init__(self, context): + # type: (ValidationContext) -> None self.variable_definitions = [] super(NoUnusedVariables, self).__init__(context) - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> None self.variable_definitions = [] - def leave_OperationDefinition(self, operation, key, parent, path, ancestors): + def leave_OperationDefinition( + self, + operation, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[str] + ancestors, # type: List[Document] + ): + # type: (...) -> None variable_name_used = set() usages = self.context.get_recursive_variable_usages(operation) op_name = operation.name and operation.name.value or None @@ -22,10 +44,14 @@ def leave_OperationDefinition(self, operation, key, parent, path, ancestors): for variable_definition in self.variable_definitions: if variable_definition.variable.name.value not in variable_name_used: - self.context.report_error(GraphQLError( - self.unused_variable_message(variable_definition.variable.name.value, op_name), - [variable_definition] - )) + self.context.report_error( + GraphQLError( + self.unused_variable_message( + variable_definition.variable.name.value, op_name + ), + [variable_definition], + ) + ) def enter_VariableDefinition(self, node, key, parent, path, ancestors): self.variable_definitions.append(node) @@ -33,5 +59,7 @@ def enter_VariableDefinition(self, node, key, parent, path, ancestors): @staticmethod def unused_variable_message(variable_name, op_name): if op_name: - return 'Variable "${}" is never used in operation "{}".'.format(variable_name, op_name) + return 'Variable "${}" is never used in operation "{}".'.format( + variable_name, op_name + ) return 'Variable "${}" is never used.'.format(variable_name) diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index 2dbca1cd..74a1e188 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -5,18 +5,31 @@ from ...language import ast from ...language.printer import print_ast from ...pyutils.pair_set import PairSet -from ...type.definition import (GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, - get_named_type, is_leaf_type) +from ...type.definition import ( + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + get_named_type, + is_leaf_type, +) from ...utils.type_comparators import is_equal_type from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import OperationDefinition, Field, InlineFragment, SelectionSet + from ...type.definition import GraphQLUnionType, GraphQLField, GraphQLScalarType + from ...pyutils.pair_set import PairSet + from typing import List, Union, Any, Optional, Dict + class OverlappingFieldsCanBeMerged(ValidationRule): - __slots__ = ('_compared_fragments', '_cached_fields_and_fragment_names', ) + __slots__ = ("_compared_fragments", "_cached_fields_and_fragment_names") def __init__(self, context): + # type: (ValidationContext) -> None super(OverlappingFieldsCanBeMerged, self).__init__(context) # A memoization for when two fragments are compared "between" each other for # conflicts. Two fragments may be compared many times, so memoizing this can @@ -28,7 +41,15 @@ def __init__(self, context): # times, so this improves the performance of this validator. self._cached_fields_and_fragment_names = {} - def leave_SelectionSet(self, node, key, parent, path, ancestors): + def leave_SelectionSet( + self, + node, # type: SelectionSet + key, # type: str + parent, # type: Union[Field, InlineFragment, OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None # Note: we validate on the reverse traversal so deeper conflicts will be # caught first, for correct calculation of mutual exclusivity and for # clearer error messages. @@ -39,15 +60,21 @@ def leave_SelectionSet(self, node, key, parent, path, ancestors): # ) # conflicts = _find_conflicts(self.context, False, field_map, self.compared_set) - conflicts = _find_conflicts_within_selection_set(self.context, self._cached_fields_and_fragment_names, - self._compared_fragments, self.context.get_parent_type(), - node) + conflicts = _find_conflicts_within_selection_set( + self.context, + self._cached_fields_and_fragment_names, + self._compared_fragments, + self.context.get_parent_type(), + node, + ) for (reason_name, reason), fields1, fields2 in conflicts: - self.context.report_error(GraphQLError( - self.fields_conflict_message(reason_name, reason), - list(fields1) + list(fields2) - )) + self.context.report_error( + GraphQLError( + self.fields_conflict_message(reason_name, reason), + list(fields1) + list(fields2), + ) + ) @staticmethod def same_type(type1, type2): @@ -58,15 +85,19 @@ def same_type(type1, type2): def fields_conflict_message(cls, reason_name, reason): return ( 'Fields "{}" conflict because {}. ' - 'Use different aliases on the fields to fetch both if this was ' - 'intentional.' + "Use different aliases on the fields to fetch both if this was " + "intentional." ).format(reason_name, cls.reason_message(reason)) @classmethod def reason_message(cls, reason): if isinstance(reason, list): - return ' and '.join('subfields "{}" conflict because {}'.format(reason_name, cls.reason_message(sub_reason)) - for reason_name, sub_reason in reason) + return " and ".join( + 'subfields "{}" conflict because {}'.format( + reason_name, cls.reason_message(sub_reason) + ) + for reason_name, sub_reason in reason + ) return reason @@ -123,16 +154,24 @@ def reason_message(cls, reason): # J) Also, if two fragments are referenced in both selection sets, then a # comparison is made "between" the two fragments. -def _find_conflicts_within_selection_set(context, cached_fields_and_fragment_names, compared_fragments, parent_type, - selection_set): + +def _find_conflicts_within_selection_set( + context, # type: ValidationContext + cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + compared_fragments, # type: PairSet + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + selection_set, # type: SelectionSet +): + # type: (...) -> List """Find all conflicts found "within" a selection set, including those found via spreading in fragments. Called when visiting each SelectionSet in the GraphQL Document. """ conflicts = [] - field_map, fragment_names = _get_fields_and_fragments_names(context, cached_fields_and_fragment_names, parent_type, - selection_set) + field_map, fragment_names = _get_fields_and_fragments_names( + context, cached_fields_and_fragment_names, parent_type, selection_set + ) # (A) Find all conflicts "within" the fields of this selection set. # Note: this is the *only place* `collect_conflicts_within` is called. @@ -141,7 +180,7 @@ def _find_conflicts_within_selection_set(context, cached_fields_and_fragment_nam conflicts, cached_fields_and_fragment_names, compared_fragments, - field_map + field_map, ) # (B) Then collect conflicts between these fields and those represented by @@ -161,7 +200,7 @@ def _find_conflicts_within_selection_set(context, cached_fields_and_fragment_nam # selection set to collect conflicts within fragments spread together. # This compares each item in the list of fragment names to every other item # in that same list (except for itself). - for other_fragment_name in fragment_names[i + 1:]: + for other_fragment_name in fragment_names[i + 1 :]: _collect_conflicts_between_fragments( context, conflicts, @@ -175,35 +214,62 @@ def _find_conflicts_within_selection_set(context, cached_fields_and_fragment_nam return conflicts -def _collect_conflicts_between_fields_and_fragment(context, conflicts, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, field_map, - fragment_name): +def _collect_conflicts_between_fields_and_fragment( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map, + fragment_name, +): fragment = context.get_fragment(fragment_name) if not fragment: return None - field_map2, fragment_names2 = _get_referenced_fields_and_fragment_names(context, cached_fields_and_fragment_names, - fragment) + field_map2, fragment_names2 = _get_referenced_fields_and_fragment_names( + context, cached_fields_and_fragment_names, fragment + ) # (D) First collect any conflicts between the provided collection of fields # and the collection of fields represented by the given fragment. - _collect_conflicts_between(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, field_map, field_map2) + _collect_conflicts_between( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map, + field_map2, + ) # (E) Then collect any conflicts between the provided collection of fields # and any fragment names found in the given fragment. for fragment_name2 in fragment_names2: - _collect_conflicts_between_fields_and_fragment(context, conflicts, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, field_map, - fragment_name2) + _collect_conflicts_between_fields_and_fragment( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map, + fragment_name2, + ) # Collect all conflicts found between two fragments, including via spreading in # any nested fragments -def _collect_conflicts_between_fragments(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, fragment_name1, fragment_name2): +def _collect_conflicts_between_fragments( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + fragment_name1, + fragment_name2, +): fragment1 = context.get_fragment(fragment_name1) fragment2 = context.get_fragment(fragment_name2) @@ -221,33 +287,63 @@ def _collect_conflicts_between_fragments(context, conflicts, cached_fields_and_f compared_fragments.add(fragment_name1, fragment_name2, are_mutually_exclusive) - field_map1, fragment_names1 = _get_referenced_fields_and_fragment_names(context, cached_fields_and_fragment_names, - fragment1) + field_map1, fragment_names1 = _get_referenced_fields_and_fragment_names( + context, cached_fields_and_fragment_names, fragment1 + ) - field_map2, fragment_names2 = _get_referenced_fields_and_fragment_names(context, cached_fields_and_fragment_names, - fragment2) + field_map2, fragment_names2 = _get_referenced_fields_and_fragment_names( + context, cached_fields_and_fragment_names, fragment2 + ) # (F) First, collect all conflicts between these two collections of fields # (not including any nested fragments) - _collect_conflicts_between(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, field_map1, field_map2) + _collect_conflicts_between( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map1, + field_map2, + ) # (G) Then collect conflicts between the first fragment and any nested # fragments spread in the second fragment. for _fragment_name2 in fragment_names2: - _collect_conflicts_between_fragments(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, fragment_name1, _fragment_name2) + _collect_conflicts_between_fragments( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + fragment_name1, + _fragment_name2, + ) # (G) Then collect conflicts between the second fragment and any nested # fragments spread in the first fragment. for _fragment_name1 in fragment_names1: - _collect_conflicts_between_fragments(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, _fragment_name1, fragment_name2) + _collect_conflicts_between_fragments( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + _fragment_name1, + fragment_name2, + ) -def _find_conflicts_between_sub_selection_sets(context, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, parent_type1, selection_set1, - parent_type2, selection_set2): +def _find_conflicts_between_sub_selection_sets( + context, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + parent_type1, + selection_set1, + parent_type2, + selection_set2, +): """Find all conflicts found between two selection sets. Includes those found via spreading in fragments. Called when determining if conflicts exist @@ -256,43 +352,77 @@ def _find_conflicts_between_sub_selection_sets(context, cached_fields_and_fragme conflicts = [] - field_map1, fragment_names1 = _get_fields_and_fragments_names(context, cached_fields_and_fragment_names, - parent_type1, selection_set1) + field_map1, fragment_names1 = _get_fields_and_fragments_names( + context, cached_fields_and_fragment_names, parent_type1, selection_set1 + ) - field_map2, fragment_names2 = _get_fields_and_fragments_names(context, cached_fields_and_fragment_names, - parent_type2, selection_set2) + field_map2, fragment_names2 = _get_fields_and_fragments_names( + context, cached_fields_and_fragment_names, parent_type2, selection_set2 + ) # (H) First, collect all conflicts between these two collections of field. - _collect_conflicts_between(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - are_mutually_exclusive, field_map1, field_map2) + _collect_conflicts_between( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map1, + field_map2, + ) # (I) Then collect conflicts between the first collection of fields and # those referenced by each fragment name associated with the second. for fragment_name2 in fragment_names2: - _collect_conflicts_between_fields_and_fragment(context, conflicts, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, field_map1, - fragment_name2) + _collect_conflicts_between_fields_and_fragment( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map1, + fragment_name2, + ) # (I) Then collect conflicts between the second collection of fields and # those referenced by each fragment name associated with the first. for fragment_name1 in fragment_names1: - _collect_conflicts_between_fields_and_fragment(context, conflicts, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, field_map2, - fragment_name1) + _collect_conflicts_between_fields_and_fragment( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + field_map2, + fragment_name1, + ) # (J) Also collect conflicts between any fragment names by the first and # fragment names by the second. This compares each item in the first set of # names to each item in the second set of names. for fragment_name1 in fragment_names1: for fragment_name2 in fragment_names2: - _collect_conflicts_between_fragments(context, conflicts, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, - fragment_name1, fragment_name2) + _collect_conflicts_between_fragments( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + fragment_name1, + fragment_name2, + ) return conflicts -def _collect_conflicts_within(context, conflicts, cached_fields_and_fragment_names, compared_fragments, field_map): +def _collect_conflicts_within( + context, # type: ValidationContext + conflicts, # type: List + cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + compared_fragments, # type: PairSet + field_map, # type: OrderedDict +): + # type: (...) -> None """Collect all Conflicts "within" one collection of fields.""" # field map is a keyed collection, where each key represents a response @@ -304,16 +434,30 @@ def _collect_conflicts_within(context, conflicts, cached_fields_and_fragment_nam # (except to itself). If the list only has one item, nothing needs to # be compared. for i, field in enumerate(fields): - for other_field in fields[i + 1:]: + for other_field in fields[i + 1 :]: # within one collection is never mutually exclusive - conflict = _find_conflict(context, cached_fields_and_fragment_names, compared_fragments, False, - response_name, field, other_field) + conflict = _find_conflict( + context, + cached_fields_and_fragment_names, + compared_fragments, + False, + response_name, + field, + other_field, + ) if conflict: conflicts.append(conflict) -def _collect_conflicts_between(context, conflicts, cached_fields_and_fragment_names, compared_fragments, - parent_fields_are_mutually_exclusive, field_map1, field_map2): +def _collect_conflicts_between( + context, + conflicts, + cached_fields_and_fragment_names, + compared_fragments, + parent_fields_are_mutually_exclusive, + field_map1, + field_map2, +): """Collect all Conflicts between two collections of fields. This is similar to, but different from the `collect_conflicts_within` function above. This check assumes that @@ -331,15 +475,30 @@ def _collect_conflicts_between(context, conflicts, cached_fields_and_fragment_na if fields2: for field1 in fields1: for field2 in fields2: - conflict = _find_conflict(context, cached_fields_and_fragment_names, compared_fragments, - parent_fields_are_mutually_exclusive, response_name, field1, field2) + conflict = _find_conflict( + context, + cached_fields_and_fragment_names, + compared_fragments, + parent_fields_are_mutually_exclusive, + response_name, + field1, + field2, + ) if conflict: conflicts.append(conflict) -def _find_conflict(context, cached_fields_and_fragment_names, compared_fragments, parent_fields_are_mutually_exclusive, - response_name, field1, field2): +def _find_conflict( + context, # type: ValidationContext + cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + compared_fragments, # type: PairSet + parent_fields_are_mutually_exclusive, # type: bool + response_name, # type: str + field1, # type: List[Union[Field, GraphQLField, GraphQLObjectType]] + field2, # type: List[Union[Field, GraphQLField, GraphQLObjectType]] +): + # type: (...) -> Optional[Any] """Determines if there is a conflict between two particular fields.""" parent_type1, ast1, def1 = field1 parent_type2, ast2, def2 = field2 @@ -353,12 +512,10 @@ def _find_conflict(context, cached_fields_and_fragment_names, compared_fragments # in the current state of the schema, then perhaps in some future version, # thus may not safely diverge. - are_mutually_exclusive = ( - parent_fields_are_mutually_exclusive or ( - parent_type1 != parent_type2 and - isinstance(parent_type1, GraphQLObjectType) and - isinstance(parent_type2, GraphQLObjectType) - ) + are_mutually_exclusive = parent_fields_are_mutually_exclusive or ( + parent_type1 != parent_type2 + and isinstance(parent_type1, GraphQLObjectType) + and isinstance(parent_type2, GraphQLObjectType) ) # The return type for each field. @@ -372,24 +529,23 @@ def _find_conflict(context, cached_fields_and_fragment_names, compared_fragments if name1 != name2: return ( - (response_name, '{} and {} are different fields'.format(name1, name2)), + (response_name, "{} and {} are different fields".format(name1, name2)), [ast1], - [ast2] + [ast2], ) # Two field calls must have the same arguments. if not _same_arguments(ast1.arguments, ast2.arguments): - return ( - (response_name, 'they have differing arguments'), - [ast1], - [ast2] - ) + return ((response_name, "they have differing arguments"), [ast1], [ast2]) if type1 and type2 and do_types_conflict(type1, type2): return ( - (response_name, 'they return conflicting types {} and {}'.format(type1, type2)), + ( + response_name, + "they return conflicting types {} and {}".format(type1, type2), + ), [ast1], - [ast2] + [ast2], ) # Collect and compare sub-fields. Use the same "visited fragment names" list @@ -399,28 +555,44 @@ def _find_conflict(context, cached_fields_and_fragment_names, compared_fragments selection_set2 = ast2.selection_set if selection_set1 and selection_set2: - conflicts = _find_conflicts_between_sub_selection_sets(context, cached_fields_and_fragment_names, - compared_fragments, are_mutually_exclusive, - get_named_type(type1), selection_set1, - get_named_type(type2), selection_set2) + conflicts = _find_conflicts_between_sub_selection_sets( + context, + cached_fields_and_fragment_names, + compared_fragments, + are_mutually_exclusive, + get_named_type(type1), + selection_set1, + get_named_type(type2), + selection_set2, + ) return _subfield_conflicts(conflicts, response_name, ast1, ast2) -def _get_fields_and_fragments_names(context, cached_fields_and_fragment_names, parent_type, selection_set): +def _get_fields_and_fragments_names( + context, # type: ValidationContext + cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + selection_set, # type: SelectionSet +): + # type: (...) -> List[Union[List, OrderedDict]] cached = cached_fields_and_fragment_names.get(selection_set) if not cached: ast_and_defs = OrderedDict() fragment_names = OrderedDict() - _collect_fields_and_fragment_names(context, parent_type, selection_set, ast_and_defs, fragment_names) + _collect_fields_and_fragment_names( + context, parent_type, selection_set, ast_and_defs, fragment_names + ) cached = [ast_and_defs, list(fragment_names.keys())] cached_fields_and_fragment_names[selection_set] = cached return cached -def _get_referenced_fields_and_fragment_names(context, cached_fields_and_fragment_names, fragment): +def _get_referenced_fields_and_fragment_names( + context, cached_fields_and_fragment_names, fragment +): """Given a reference to a fragment, return the represented collection of fields as well as a list of nested fragment names referenced via fragment spreads.""" @@ -432,11 +604,19 @@ def _get_referenced_fields_and_fragment_names(context, cached_fields_and_fragmen fragment_type = type_from_ast(context.get_schema(), fragment.type_condition) - return _get_fields_and_fragments_names(context, cached_fields_and_fragment_names, - fragment_type, fragment.selection_set) + return _get_fields_and_fragments_names( + context, cached_fields_and_fragment_names, fragment_type, fragment.selection_set + ) -def _collect_fields_and_fragment_names(context, parent_type, selection_set, ast_and_defs, fragment_names): +def _collect_fields_and_fragment_names( + context, # type: ValidationContext + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + selection_set, # type: SelectionSet + ast_and_defs, # type: OrderedDict + fragment_names, # type: OrderedDict +): + # type: (...) -> None for selection in selection_set.selections: if isinstance(selection, ast.Field): @@ -458,12 +638,19 @@ def _collect_fields_and_fragment_names(context, parent_type, selection_set, ast_ elif isinstance(selection, ast.InlineFragment): type_condition = selection.type_condition if type_condition: - inline_fragment_type = type_from_ast(context.get_schema(), selection.type_condition) + inline_fragment_type = type_from_ast( + context.get_schema(), selection.type_condition + ) else: inline_fragment_type = parent_type - _collect_fields_and_fragment_names(context, inline_fragment_type, selection.selection_set, ast_and_defs, - fragment_names) + _collect_fields_and_fragment_names( + context, + inline_fragment_type, + selection.selection_set, + ast_and_defs, + fragment_names, + ) def _subfield_conflicts(conflicts, response_name, ast1, ast2): @@ -472,11 +659,12 @@ def _subfield_conflicts(conflicts, response_name, ast1, ast2): return ( (response_name, [conflict[0] for conflict in conflicts]), tuple(itertools.chain([ast1], *[conflict[1] for conflict in conflicts])), - tuple(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])) + tuple(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])), ) def do_types_conflict(type1, type2): + # type: (GraphQLScalarType, GraphQLScalarType) -> bool if isinstance(type1, GraphQLList): if isinstance(type2, GraphQLList): return do_types_conflict(type1.of_type, type2.of_type) diff --git a/graphql/validation/rules/possible_fragment_spreads.py b/graphql/validation/rules/possible_fragment_spreads.py index b9cc4165..3cd8f1aa 100644 --- a/graphql/validation/rules/possible_fragment_spreads.py +++ b/graphql/validation/rules/possible_fragment_spreads.py @@ -3,29 +3,54 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +if False: + from ..language.ast import Field, InlineFragment + from typing import Any, List, Union -class PossibleFragmentSpreads(ValidationRule): - def enter_InlineFragment(self, node, key, parent, path, ancestors): +class PossibleFragmentSpreads(ValidationRule): + def enter_InlineFragment( + self, + node, # type: InlineFragment + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[InlineFragment]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None frag_type = self.context.get_type() parent_type = self.context.get_parent_type() schema = self.context.get_schema() - if frag_type and parent_type and not do_types_overlap(schema, frag_type, parent_type): - self.context.report_error(GraphQLError( - self.type_incompatible_anon_spread_message(parent_type, frag_type), - [node] - )) + if ( + frag_type + and parent_type + and not do_types_overlap(schema, frag_type, parent_type) + ): + self.context.report_error( + GraphQLError( + self.type_incompatible_anon_spread_message(parent_type, frag_type), + [node], + ) + ) def enter_FragmentSpread(self, node, key, parent, path, ancestors): frag_name = node.name.value frag_type = self.get_fragment_type(self.context, frag_name) parent_type = self.context.get_parent_type() schema = self.context.get_schema() - if frag_type and parent_type and not do_types_overlap(schema, frag_type, parent_type): - self.context.report_error(GraphQLError( - self.type_incompatible_spread_message(frag_name, parent_type, frag_type), - [node] - )) + if ( + frag_type + and parent_type + and not do_types_overlap(schema, frag_type, parent_type) + ): + self.context.report_error( + GraphQLError( + self.type_incompatible_spread_message( + frag_name, parent_type, frag_type + ), + [node], + ) + ) @staticmethod def get_fragment_type(context, name): @@ -34,11 +59,12 @@ def get_fragment_type(context, name): @staticmethod def type_incompatible_spread_message(frag_name, parent_type, frag_type): - return 'Fragment {} cannot be spread here as objects of type {} can never be of type {}'.format(frag_name, - parent_type, - frag_type) + return "Fragment {} cannot be spread here as objects of type {} can never be of type {}".format( + frag_name, parent_type, frag_type + ) @staticmethod def type_incompatible_anon_spread_message(parent_type, frag_type): - return 'Fragment cannot be spread here as objects of type {} can never be of type {}'.format(parent_type, - frag_type) + return "Fragment cannot be spread here as objects of type {} can never be of type {}".format( + parent_type, frag_type + ) diff --git a/graphql/validation/rules/provided_non_null_arguments.py b/graphql/validation/rules/provided_non_null_arguments.py index 09507277..190e9d03 100644 --- a/graphql/validation/rules/provided_non_null_arguments.py +++ b/graphql/validation/rules/provided_non_null_arguments.py @@ -2,10 +2,21 @@ from ...type.definition import GraphQLNonNull from .base import ValidationRule +if False: + from ...language.ast import Field, InlineFragment + from typing import Any, List, Optional, Union -class ProvidedNonNullArguments(ValidationRule): - def leave_Field(self, node, key, parent, path, ancestors): +class ProvidedNonNullArguments(ValidationRule): + def leave_Field( + self, + node, # type: Field + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[Field]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> Optional[Any] field_def = self.context.get_field_def() if not field_def: return False @@ -16,10 +27,14 @@ def leave_Field(self, node, key, parent, path, ancestors): for arg_name, arg_def in field_def.args.items(): arg_ast = arg_ast_map.get(arg_name, None) if not arg_ast and isinstance(arg_def.type, GraphQLNonNull): - self.context.report_error(GraphQLError( - self.missing_field_arg_message(node.name.value, arg_name, arg_def.type), - [node] - )) + self.context.report_error( + GraphQLError( + self.missing_field_arg_message( + node.name.value, arg_name, arg_def.type + ), + [node], + ) + ) def leave_Directive(self, node, key, parent, path, ancestors): directive_def = self.context.get_directive() @@ -32,15 +47,23 @@ def leave_Directive(self, node, key, parent, path, ancestors): for arg_name, arg_def in directive_def.args.items(): arg_ast = arg_ast_map.get(arg_name, None) if not arg_ast and isinstance(arg_def.type, GraphQLNonNull): - self.context.report_error(GraphQLError( - self.missing_directive_arg_message(node.name.value, arg_name, arg_def.type), - [node] - )) + self.context.report_error( + GraphQLError( + self.missing_directive_arg_message( + node.name.value, arg_name, arg_def.type + ), + [node], + ) + ) @staticmethod def missing_field_arg_message(name, arg_name, type): - return 'Field "{}" argument "{}" of type "{}" is required but not provided.'.format(name, arg_name, type) + return 'Field "{}" argument "{}" of type "{}" is required but not provided.'.format( + name, arg_name, type + ) @staticmethod def missing_directive_arg_message(name, arg_name, type): - return 'Directive "{}" argument "{}" of type "{}" is required but not provided.'.format(name, arg_name, type) + return 'Directive "{}" argument "{}" of type "{}" is required but not provided.'.format( + name, arg_name, type + ) diff --git a/graphql/validation/rules/scalar_leafs.py b/graphql/validation/rules/scalar_leafs.py index f03efbc7..97755de0 100644 --- a/graphql/validation/rules/scalar_leafs.py +++ b/graphql/validation/rules/scalar_leafs.py @@ -2,10 +2,21 @@ from ...type.definition import get_named_type, is_leaf_type from .base import ValidationRule +if False: + from ...language.ast import Field, InlineFragment + from typing import Any, List, Union -class ScalarLeafs(ValidationRule): - def enter_Field(self, node, key, parent, path, ancestors): +class ScalarLeafs(ValidationRule): + def enter_Field( + self, + node, # type: Field + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[Field]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None type = self.context.get_type() if not type: @@ -13,20 +24,25 @@ def enter_Field(self, node, key, parent, path, ancestors): if is_leaf_type(get_named_type(type)): if node.selection_set: - self.context.report_error(GraphQLError( - self.no_subselection_allowed_message(node.name.value, type), - [node.selection_set] - )) + self.context.report_error( + GraphQLError( + self.no_subselection_allowed_message(node.name.value, type), + [node.selection_set], + ) + ) elif not node.selection_set: - self.context.report_error(GraphQLError( - self.required_subselection_message(node.name.value, type), - [node] - )) + self.context.report_error( + GraphQLError( + self.required_subselection_message(node.name.value, type), [node] + ) + ) @staticmethod def no_subselection_allowed_message(field, type): - return 'Field "{}" of type "{}" must not have a sub selection.'.format(field, type) + return 'Field "{}" of type "{}" must not have a sub selection.'.format( + field, type + ) @staticmethod def required_subselection_message(field, type): diff --git a/graphql/validation/rules/unique_argument_names.py b/graphql/validation/rules/unique_argument_names.py index 9e25c75c..b0f0adfb 100644 --- a/graphql/validation/rules/unique_argument_names.py +++ b/graphql/validation/rules/unique_argument_names.py @@ -1,28 +1,52 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Field, InlineFragment, Argument + from typing import Any, List, Union + class UniqueArgumentNames(ValidationRule): - __slots__ = 'known_arg_names', + __slots__ = ("known_arg_names",) def __init__(self, context): + # type: (ValidationContext) -> None super(UniqueArgumentNames, self).__init__(context) self.known_arg_names = {} - def enter_Field(self, node, key, parent, path, ancestors): + def enter_Field( + self, + node, # type: Field + key, # type: int + parent, # type: Union[List[Union[Field, InlineFragment]], List[Field]] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None self.known_arg_names = {} def enter_Directive(self, node, key, parent, path, ancestors): self.known_arg_names = {} - def enter_Argument(self, node, key, parent, path, ancestors): + def enter_Argument( + self, + node, # type: Argument + key, # type: int + parent, # type: List[Argument] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> bool arg_name = node.name.value if arg_name in self.known_arg_names: - self.context.report_error(GraphQLError( - self.duplicate_arg_message(arg_name), - [self.known_arg_names[arg_name], node.name] - )) + self.context.report_error( + GraphQLError( + self.duplicate_arg_message(arg_name), + [self.known_arg_names[arg_name], node.name], + ) + ) else: self.known_arg_names[arg_name] = node.name return False diff --git a/graphql/validation/rules/unique_fragment_names.py b/graphql/validation/rules/unique_fragment_names.py index 91de3271..ff1003f8 100644 --- a/graphql/validation/rules/unique_fragment_names.py +++ b/graphql/validation/rules/unique_fragment_names.py @@ -1,24 +1,40 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class UniqueFragmentNames(ValidationRule): - __slots__ = 'known_fragment_names', + __slots__ = ("known_fragment_names",) def __init__(self, context): + # type: (ValidationContext) -> None super(UniqueFragmentNames, self).__init__(context) self.known_fragment_names = {} - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> bool return False def enter_FragmentDefinition(self, node, key, parent, path, ancestors): fragment_name = node.name.value if fragment_name in self.known_fragment_names: - self.context.report_error(GraphQLError( - self.duplicate_fragment_name_message(fragment_name), - [self.known_fragment_names[fragment_name], node.name] - )) + self.context.report_error( + GraphQLError( + self.duplicate_fragment_name_message(fragment_name), + [self.known_fragment_names[fragment_name], node.name], + ) + ) else: self.known_fragment_names[fragment_name] = node.name return False diff --git a/graphql/validation/rules/unique_input_field_names.py b/graphql/validation/rules/unique_input_field_names.py index 6fe18bab..f5afbeb1 100644 --- a/graphql/validation/rules/unique_input_field_names.py +++ b/graphql/validation/rules/unique_input_field_names.py @@ -1,29 +1,61 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Argument, ObjectValue, ObjectField + from typing import Any, List, Union + class UniqueInputFieldNames(ValidationRule): - __slots__ = 'known_names', 'known_names_stack' + __slots__ = "known_names", "known_names_stack" def __init__(self, context): + # type: (ValidationContext) -> None super(UniqueInputFieldNames, self).__init__(context) self.known_names = {} self.known_names_stack = [] - def enter_ObjectValue(self, node, key, parent, path, ancestors): + def enter_ObjectValue( + self, + node, # type: ObjectValue + key, # type: str + parent, # type: Argument + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None self.known_names_stack.append(self.known_names) self.known_names = {} - def leave_ObjectValue(self, node, key, parent, path, ancestors): + def leave_ObjectValue( + self, + node, # type: ObjectValue + key, # type: str + parent, # type: Argument + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> None self.known_names = self.known_names_stack.pop() - def enter_ObjectField(self, node, key, parent, path, ancestors): + def enter_ObjectField( + self, + node, # type: ObjectField + key, # type: int + parent, # type: List[ObjectField] + path, # type: List[Union[int, str]] + ancestors, # type: List[Any] + ): + # type: (...) -> bool field_name = node.name.value if field_name in self.known_names: - self.context.report_error(GraphQLError( - self.duplicate_input_field_message(field_name), - [self.known_names[field_name], node.name] - )) + self.context.report_error( + GraphQLError( + self.duplicate_input_field_message(field_name), + [self.known_names[field_name], node.name], + ) + ) else: self.known_names[field_name] = node.name return False diff --git a/graphql/validation/rules/unique_operation_names.py b/graphql/validation/rules/unique_operation_names.py index 1fccbb9b..da097447 100644 --- a/graphql/validation/rules/unique_operation_names.py +++ b/graphql/validation/rules/unique_operation_names.py @@ -1,24 +1,40 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import Any, List, Optional, Union + class UniqueOperationNames(ValidationRule): - __slots__ = 'known_operation_names', + __slots__ = ("known_operation_names",) def __init__(self, context): + # type: (ValidationContext) -> None super(UniqueOperationNames, self).__init__(context) self.known_operation_names = {} - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> Optional[Any] operation_name = node.name if not operation_name: return if operation_name.value in self.known_operation_names: - self.context.report_error(GraphQLError( - self.duplicate_operation_name_message(operation_name.value), - [self.known_operation_names[operation_name.value], operation_name] - )) + self.context.report_error( + GraphQLError( + self.duplicate_operation_name_message(operation_name.value), + [self.known_operation_names[operation_name.value], operation_name], + ) + ) else: self.known_operation_names[operation_name.value] = operation_name return False diff --git a/graphql/validation/rules/unique_variable_names.py b/graphql/validation/rules/unique_variable_names.py index f471e346..8d2ce3d3 100644 --- a/graphql/validation/rules/unique_variable_names.py +++ b/graphql/validation/rules/unique_variable_names.py @@ -1,24 +1,40 @@ from ...error import GraphQLError from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class UniqueVariableNames(ValidationRule): - __slots__ = 'known_variable_names', + __slots__ = ("known_variable_names",) def __init__(self, context): + # type: (ValidationContext) -> None super(UniqueVariableNames, self).__init__(context) self.known_variable_names = {} - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> None self.known_variable_names = {} def enter_VariableDefinition(self, node, key, parent, path, ancestors): variable_name = node.variable.name.value if variable_name in self.known_variable_names: - self.context.report_error(GraphQLError( - self.duplicate_variable_message(variable_name), - [self.known_variable_names[variable_name], node.variable.name] - )) + self.context.report_error( + GraphQLError( + self.duplicate_variable_message(variable_name), + [self.known_variable_names[variable_name], node.variable.name], + ) + ) else: self.known_variable_names[variable_name] = node.variable.name diff --git a/graphql/validation/rules/variables_in_allowed_position.py b/graphql/validation/rules/variables_in_allowed_position.py index 4117e0f8..6c62f449 100644 --- a/graphql/validation/rules/variables_in_allowed_position.py +++ b/graphql/validation/rules/variables_in_allowed_position.py @@ -4,18 +4,40 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +if False: + from ..validation import ValidationContext + from ...language.ast import Document, OperationDefinition + from typing import List, Union + class VariablesInAllowedPosition(ValidationRule): - __slots__ = 'var_def_map' + __slots__ = "var_def_map" def __init__(self, context): + # type: (ValidationContext) -> None super(VariablesInAllowedPosition, self).__init__(context) self.var_def_map = {} - def enter_OperationDefinition(self, node, key, parent, path, ancestors): + def enter_OperationDefinition( + self, + node, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[Union[int, str]] + ancestors, # type: List[Document] + ): + # type: (...) -> None self.var_def_map = {} - def leave_OperationDefinition(self, operation, key, parent, path, ancestors): + def leave_OperationDefinition( + self, + operation, # type: OperationDefinition + key, # type: int + parent, # type: List[OperationDefinition] + path, # type: List[str] + ancestors, # type: List[Document] + ): + # type: (...) -> None usages = self.context.get_recursive_variable_usages(operation) for usage in usages: @@ -31,11 +53,15 @@ def leave_OperationDefinition(self, operation, key, parent, path, ancestors): # than the expected item type (contravariant). schema = self.context.get_schema() var_type = type_from_ast(schema, var_def.type) - if var_type and not is_type_sub_type_of(schema, self.effective_type(var_type, var_def), type): - self.context.report_error(GraphQLError( - self.bad_var_pos_message(var_name, var_type, type), - [var_def, node] - )) + if var_type and not is_type_sub_type_of( + schema, self.effective_type(var_type, var_def), type + ): + self.context.report_error( + GraphQLError( + self.bad_var_pos_message(var_name, var_type, type), + [var_def, node], + ) + ) def enter_VariableDefinition(self, node, key, parent, path, ancestors): self.var_def_map[node.variable.name.value] = node @@ -49,5 +75,6 @@ def effective_type(var_type, var_def): @staticmethod def bad_var_pos_message(var_name, var_type, expected_type): - return 'Variable "{}" of type "{}" used in position expecting type "{}".'.format(var_name, var_type, - expected_type) + return 'Variable "{}" of type "{}" used in position expecting type "{}".'.format( + var_name, var_type, expected_type + ) diff --git a/graphql/validation/validation.py b/graphql/validation/validation.py index 3610dbf4..70596a34 100644 --- a/graphql/validation/validation.py +++ b/graphql/validation/validation.py @@ -1,20 +1,36 @@ -from ..language.ast import (FragmentDefinition, FragmentSpread, - OperationDefinition) +from ..language.ast import FragmentDefinition, FragmentSpread, OperationDefinition from ..language.visitor import ParallelVisitor, TypeInfoVisitor, Visitor, visit from ..type import GraphQLSchema from ..utils.type_info import TypeInfo from .rules import specified_rules +if False: + from typing import List, Union + from ..language.ast import Document, OperationDefinition, SelectionSet + from ..language.visitor_meta import VisitorMeta + from ..type.schema import GraphQLSchema + from ..type.definition import ( + GraphQLList, + GraphQLObjectType, + GraphQLScalarType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLField, + GraphQLArgument, + ) + def validate(schema, ast, rules=specified_rules): - assert schema, 'Must provide schema' - assert ast, 'Must provide document' + # type: (GraphQLSchema, Document, List[VisitorMeta]) -> List + assert schema, "Must provide schema" + assert ast, "Must provide document" assert isinstance(schema, GraphQLSchema) type_info = TypeInfo(schema) return visit_using_rules(schema, type_info, ast, rules) def visit_using_rules(schema, type_info, ast, rules): + # type: (GraphQLSchema, TypeInfo, Document, List[VisitorMeta]) -> List context = ValidationContext(schema, ast, type_info) visitors = [rule(context) for rule in rules] visit(ast, TypeInfoVisitor(type_info, ParallelVisitor(visitors))) @@ -22,7 +38,7 @@ def visit_using_rules(schema, type_info, ast, rules): class VariableUsage(object): - __slots__ = 'node', 'type' + __slots__ = "node", "type" def __init__(self, node, type): self.node = node @@ -30,9 +46,10 @@ def __init__(self, node, type): class UsageVisitor(Visitor): - __slots__ = 'usages', 'type_info' + __slots__ = "usages", "type_info" def __init__(self, usages, type_info): + # type: (List, TypeInfo) -> None self.usages = usages self.type_info = type_info @@ -45,10 +62,20 @@ def enter_Variable(self, node, key, parent, path, ancestors): class ValidationContext(object): - __slots__ = ('_schema', '_ast', '_type_info', '_errors', '_fragments', '_fragment_spreads', - '_recursively_referenced_fragments', '_variable_usages', '_recursive_variable_usages') + __slots__ = ( + "_schema", + "_ast", + "_type_info", + "_errors", + "_fragments", + "_fragment_spreads", + "_recursively_referenced_fragments", + "_variable_usages", + "_recursive_variable_usages", + ) def __init__(self, schema, ast, type_info): + # type: (GraphQLSchema, Document, TypeInfo) -> None self._schema = schema self._ast = ast self._type_info = type_info @@ -63,12 +90,15 @@ def report_error(self, error): self._errors.append(error) def get_errors(self): + # type: () -> List return self._errors def get_schema(self): + # type: () -> GraphQLSchema return self._schema def get_variable_usages(self, node): + # type: (OperationDefinition) -> List usages = self._variable_usages.get(node) if usages is None: usages = [] @@ -79,6 +109,7 @@ def get_variable_usages(self, node): return usages def get_recursive_variable_usages(self, operation): + # type: (OperationDefinition) -> List assert isinstance(operation, OperationDefinition) usages = self._recursive_variable_usages.get(operation) if usages is None: @@ -91,6 +122,7 @@ def get_recursive_variable_usages(self, operation): return usages def get_recursively_referenced_fragments(self, operation): + # type: (OperationDefinition) -> List assert isinstance(operation, OperationDefinition) fragments = self._recursively_referenced_fragments.get(operation) if not fragments: @@ -112,6 +144,7 @@ def get_recursively_referenced_fragments(self, operation): return fragments def get_fragment_spreads(self, node): + # type: (SelectionSet) -> List spreads = self._fragment_spreads.get(node) if not spreads: spreads = [] @@ -140,19 +173,23 @@ def get_fragment(self, name): return fragments.get(name) def get_type(self): + # type: () -> Union[GraphQLList, GraphQLObjectType, GraphQLScalarType] return self._type_info.get_type() def get_parent_type(self): + # type: () -> Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] return self._type_info.get_parent_type() def get_input_type(self): return self._type_info.get_input_type() def get_field_def(self): + # type: () -> GraphQLField return self._type_info.get_field_def() def get_directive(self): return self._type_info.get_directive() def get_argument(self): + # type: () -> GraphQLArgument return self._type_info.get_argument() diff --git a/setup.cfg b/setup.cfg index e02e00cf..722f81b1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [flake8] exclude = tests,scripts,setup.py,docs,graphql/execution/executors/asyncio_utils.py -max-line-length = 160 +max-line-length = 200 [coverage:run] omit=graphql/backend/quiver_cloud.py,tests,*/tests/* @@ -10,3 +10,6 @@ omit=graphql/backend/quiver_cloud.py,tests,*/tests/* [bdist_wheel] universal=1 + +[mypy-graphql.*.tests.*] +ignore_errors=true From cd1c50faa184b35365237e64afc37ceec66fa4be Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sat, 23 Jun 2018 12:14:23 -0700 Subject: [PATCH 02/12] Run Black autoformatting on all the files --- graphql/__init__.py | 233 +-- graphql/backend/quiver_cloud.py | 4 +- graphql/backend/tests/schema.py | 9 +- graphql/backend/tests/test_base.py | 2 +- graphql/backend/tests/test_cache.py | 4 +- .../backend/tests/test_compileddocument.py | 29 +- graphql/backend/tests/test_document.py | 61 +- graphql/error/tests/test_base.py | 41 +- graphql/execution/executor.py | 12 +- graphql/execution/executors/asyncio_utils.py | 1 - graphql/execution/tests/test_abstract.py | 1 - graphql/execution/tests/test_directives.py | 1 - graphql/execution/tests/test_executor.py | 806 +++---- graphql/execution/tests/test_lists.py | 1 - graphql/execution/tests/test_nonnull.py | 1 - graphql/execution/tests/test_variables.py | 1 - graphql/execution/utils.py | 7 +- graphql/language/ast.py | 1 - graphql/language/base.py | 20 +- graphql/language/parser.py | 6 +- graphql/language/printer.py | 1 - graphql/language/source.py | 16 +- graphql/language/tests/test_lexer.py | 266 ++- graphql/language/tests/test_location.py | 2 +- graphql/language/tests/test_parser.py | 241 ++- graphql/language/tests/test_printer.py | 53 +- graphql/language/tests/test_schema_parser.py | 470 ++--- graphql/language/tests/test_schema_printer.py | 12 +- graphql/language/tests/test_visitor.py | 1623 ++++++++------- graphql/language/tests/test_visitor_meta.py | 3 - graphql/language/visitor_meta.py | 91 +- graphql/pyutils/ordereddict.py | 2 +- .../tests/test_default_ordered_dict.py | 46 +- graphql/pyutils/version.py | 33 +- graphql/type/__init__.py | 9 +- graphql/type/definition.py | 1 - graphql/type/directives.py | 132 +- graphql/type/introspection.py | 1 - graphql/type/scalars.py | 66 +- graphql/type/tests/test_definition.py | 405 ++-- graphql/type/tests/test_enum_type.py | 259 ++- graphql/type/tests/test_introspection.py | 1843 +++++++++-------- graphql/type/tests/test_schema.py | 36 +- graphql/type/tests/test_serialization.py | 27 +- graphql/type/tests/test_validation.py | 1756 ++++++++-------- graphql/type/typemap.py | 159 +- graphql/utils/extend_schema.py | 1 - graphql/utils/suggestion_list.py | 22 +- graphql/utils/tests/test_ast_from_value.py | 98 +- graphql/utils/tests/test_ast_to_code.py | 5 +- graphql/utils/tests/test_ast_to_dict.py | 201 +- graphql/utils/tests/test_build_ast_schema.py | 237 ++- .../utils/tests/test_build_client_schema.py | 826 ++++---- graphql/utils/tests/test_concat_ast.py | 15 +- graphql/utils/tests/test_extend_schema.py | 346 ++-- graphql/utils/tests/test_get_operation_ast.py | 38 +- graphql/utils/tests/test_quoted_or_list.py | 8 +- graphql/utils/tests/test_schema_printer.py | 450 ++-- graphql/utils/tests/test_suggestion_list.py | 12 +- graphql/utils/tests/test_type_comparators.py | 50 +- graphql/validation/__init__.py | 2 +- graphql/validation/rules/__init__.py | 52 +- graphql/validation/rules/known_directives.py | 59 +- .../validation/rules/known_fragment_names.py | 8 +- .../rules/variables_are_input_types.py | 17 +- .../tests/test_arguments_of_correct_type.py | 595 ++++-- .../test_default_values_of_correct_type.py | 118 +- .../tests/test_fields_on_correct_type.py | 224 +- .../test_fragments_on_composite_types.py | 87 +- .../tests/test_known_argument_names.py | 117 +- .../validation/tests/test_known_directives.py | 122 +- .../tests/test_known_fragment_names.py | 27 +- .../validation/tests/test_known_type_names.py | 43 +- .../tests/test_lone_anonymous_operation.py | 63 +- .../tests/test_no_fragment_cycles.py | 184 +- .../tests/test_no_undefined_variables.py | 188 +- .../tests/test_no_unused_fragments.py | 50 +- .../tests/test_no_unused_variables.py | 109 +- .../test_overlapping_fields_can_be_merged.py | 744 ++++--- .../tests/test_possible_fragment_spreads.py | 177 +- .../tests/test_provided_non_null_arguments.py | 151 +- graphql/validation/tests/test_scalar_leafs.py | 92 +- .../tests/test_unique_argument_names.py | 108 +- .../tests/test_unique_fragment_names.py | 59 +- .../tests/test_unique_input_field_names.py | 56 +- .../tests/test_unique_operation_names.py | 76 +- .../tests/test_unique_variable_names.py | 29 +- graphql/validation/tests/test_validation.py | 35 +- .../tests/test_variables_are_input_types.py | 29 +- .../test_variables_in_allowed_position.py | 224 +- graphql/validation/tests/utils.py | 425 ++-- 91 files changed, 8553 insertions(+), 6820 deletions(-) diff --git a/graphql/__init__.py b/graphql/__init__.py index 434b5a75..7b6e0574 100644 --- a/graphql/__init__.py +++ b/graphql/__init__.py @@ -1,4 +1,4 @@ -''' +""" GraphQL.js provides a reference implementation for the GraphQL specification but is also a useful utility for operating on GraphQL files and building sophisticated tools. @@ -20,18 +20,15 @@ from graphql import parse from graphql.language.base import parse -''' +""" from .pyutils.version import get_version # The primary entry point into fulfilling a GraphQL request. -from .graphql import ( - graphql -) +from .graphql import graphql # Create and operate on GraphQL type definitions and schema. from .type import ( # no import order GraphQLSchema, - # Definitions GraphQLScalarType, GraphQLObjectType, @@ -45,32 +42,25 @@ GraphQLField, GraphQLInputObjectField, GraphQLArgument, - # "Enum" of Type Kinds TypeKind, - # "Enum" of Directive locations DirectiveLocation, - # Scalars GraphQLInt, GraphQLFloat, GraphQLString, GraphQLBoolean, GraphQLID, - # Directive definition GraphQLDirective, - # Built-in directives defined by the Spec specified_directives, GraphQLSkipDirective, GraphQLIncludeDirective, GraphQLDeprecatedDirective, - # Constant Deprecation Reason DEFAULT_DEPRECATION_REASON, - # GraphQL Types for introspection. __Schema, __Directive, @@ -80,12 +70,10 @@ __InputValue, __EnumValue, __TypeKind, - # Meta-field definitions. SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef, - # Predicates is_type, is_input_type, @@ -93,7 +81,6 @@ is_leaf_type, is_composite_type, is_abstract_type, - # Un-modifiers get_nullable_type, get_named_type, @@ -103,14 +90,11 @@ from .language.base import ( # no import order Source, get_location, - # Parse parse, parse_value, - # Print print_ast, - # Visit visit, ParallelVisitor, @@ -124,72 +108,51 @@ subscribe, ResolveInfo, MiddlewareManager, - middlewares + middlewares, ) # Validate GraphQL queries. -from .validation import ( # no import order - validate, - specified_rules, -) +from .validation import validate, specified_rules # no import order # Create and format GraphQL errors. -from .error import ( - GraphQLError, - format_error, -) +from .error import GraphQLError, format_error # Utilities for operating on GraphQL type schema and parsed sources. from .utils.base import ( # The GraphQL query recommended for a full schema introspection. introspection_query, - # Gets the target Operation from a Document get_operation_ast, - # Build a GraphQLSchema from an introspection result. build_client_schema, - # Build a GraphQLSchema from a parsed GraphQL Schema language AST. build_ast_schema, - # Extends an existing GraphQLSchema from a parsed GraphQL Schema # language AST. extend_schema, - # Print a GraphQLSchema to GraphQL Schema language. print_schema, - # Create a GraphQLType from a GraphQL language AST. type_from_ast, - # Create a JavaScript value from a GraphQL language AST. value_from_ast, - # Create a GraphQL language AST from a JavaScript value. ast_from_value, - # A helper to use within recursive-descent visitors which need to be aware of # the GraphQL type system. TypeInfo, - # Determine if JavaScript values adhere to a GraphQL type. is_valid_value, - # Determine if AST values adhere to a GraphQL type. is_valid_literal_value, - # Concatenates multiple AST together. concat_ast, - # Comparators for types is_equal_type, is_type_sub_type_of, do_types_overlap, - # Asserts a string is a valid GraphQL name. assert_valid_name, - # Undefined const Undefined, ) @@ -205,100 +168,100 @@ set_default_backend, ) -VERSION = (2, 1, 0, 'rc', 2) +VERSION = (2, 1, 0, "rc", 2) __version__ = get_version(VERSION) __all__ = ( - '__version__', - 'graphql', - 'GraphQLBoolean', - 'GraphQLEnumType', - 'GraphQLEnumValue', - 'GraphQLFloat', - 'GraphQLID', - 'GraphQLInputObjectType', - 'GraphQLInt', - 'GraphQLInterfaceType', - 'GraphQLList', - 'GraphQLNonNull', - 'GraphQLField', - 'GraphQLInputObjectField', - 'GraphQLArgument', - 'GraphQLObjectType', - 'GraphQLScalarType', - 'GraphQLSchema', - 'GraphQLString', - 'GraphQLUnionType', - 'GraphQLDirective', - 'specified_directives', - 'GraphQLSkipDirective', - 'GraphQLIncludeDirective', - 'GraphQLDeprecatedDirective', - 'DEFAULT_DEPRECATION_REASON', - 'TypeKind', - 'DirectiveLocation', - '__Schema', - '__Directive', - '__DirectiveLocation', - '__Type', - '__Field', - '__InputValue', - '__EnumValue', - '__TypeKind', - 'SchemaMetaFieldDef', - 'TypeMetaFieldDef', - 'TypeNameMetaFieldDef', - 'get_named_type', - 'get_nullable_type', - 'is_abstract_type', - 'is_composite_type', - 'is_input_type', - 'is_leaf_type', - 'is_output_type', - 'is_type', - 'BREAK', - 'ParallelVisitor', - 'Source', - 'TypeInfoVisitor', - 'get_location', - 'parse', - 'parse_value', - 'print_ast', - 'visit', - 'execute', - 'subscribe', - 'ResolveInfo', - 'MiddlewareManager', - 'middlewares', - 'specified_rules', - 'validate', - 'GraphQLError', - 'format_error', - 'TypeInfo', - 'assert_valid_name', - 'ast_from_value', - 'build_ast_schema', - 'build_client_schema', - 'concat_ast', - 'do_types_overlap', - 'extend_schema', - 'get_operation_ast', - 'introspection_query', - 'is_equal_type', - 'is_type_sub_type_of', - 'is_valid_literal_value', - 'is_valid_value', - 'print_schema', - 'type_from_ast', - 'value_from_ast', - 'get_version', - 'Undefined', - 'GraphQLBackend', - 'GraphQLDocument', - 'GraphQLCoreBackend', - 'GraphQLDeciderBackend', - 'GraphQLCachedBackend', - 'get_default_backend', - 'set_default_backend', + "__version__", + "graphql", + "GraphQLBoolean", + "GraphQLEnumType", + "GraphQLEnumValue", + "GraphQLFloat", + "GraphQLID", + "GraphQLInputObjectType", + "GraphQLInt", + "GraphQLInterfaceType", + "GraphQLList", + "GraphQLNonNull", + "GraphQLField", + "GraphQLInputObjectField", + "GraphQLArgument", + "GraphQLObjectType", + "GraphQLScalarType", + "GraphQLSchema", + "GraphQLString", + "GraphQLUnionType", + "GraphQLDirective", + "specified_directives", + "GraphQLSkipDirective", + "GraphQLIncludeDirective", + "GraphQLDeprecatedDirective", + "DEFAULT_DEPRECATION_REASON", + "TypeKind", + "DirectiveLocation", + "__Schema", + "__Directive", + "__DirectiveLocation", + "__Type", + "__Field", + "__InputValue", + "__EnumValue", + "__TypeKind", + "SchemaMetaFieldDef", + "TypeMetaFieldDef", + "TypeNameMetaFieldDef", + "get_named_type", + "get_nullable_type", + "is_abstract_type", + "is_composite_type", + "is_input_type", + "is_leaf_type", + "is_output_type", + "is_type", + "BREAK", + "ParallelVisitor", + "Source", + "TypeInfoVisitor", + "get_location", + "parse", + "parse_value", + "print_ast", + "visit", + "execute", + "subscribe", + "ResolveInfo", + "MiddlewareManager", + "middlewares", + "specified_rules", + "validate", + "GraphQLError", + "format_error", + "TypeInfo", + "assert_valid_name", + "ast_from_value", + "build_ast_schema", + "build_client_schema", + "concat_ast", + "do_types_overlap", + "extend_schema", + "get_operation_ast", + "introspection_query", + "is_equal_type", + "is_type_sub_type_of", + "is_valid_literal_value", + "is_valid_value", + "print_schema", + "type_from_ast", + "value_from_ast", + "get_version", + "Undefined", + "GraphQLBackend", + "GraphQLDocument", + "GraphQLCoreBackend", + "GraphQLDeciderBackend", + "GraphQLCachedBackend", + "get_default_backend", + "set_default_backend", ) diff --git a/graphql/backend/quiver_cloud.py b/graphql/backend/quiver_cloud.py index 24f7a97b..d8eb7c45 100644 --- a/graphql/backend/quiver_cloud.py +++ b/graphql/backend/quiver_cloud.py @@ -78,9 +78,9 @@ def generate_source(self, schema, query): json_payload={"query": GRAPHQL_QUERY, "variables": variables}, ) - errors = json_response.get('errors') + errors = json_response.get("errors") if errors: - raise Exception(errors[0].get('message')) + raise Exception(errors[0].get("message")) data = json_response.get("data", {}) code_generation = data.get("generateCode", {}) code = code_generation.get("code") diff --git a/graphql/backend/tests/schema.py b/graphql/backend/tests/schema.py index a01f0d62..00a7f937 100644 --- a/graphql/backend/tests/schema.py +++ b/graphql/backend/tests/schema.py @@ -1,9 +1,8 @@ -from graphql.type import (GraphQLField, GraphQLObjectType, - GraphQLSchema, GraphQLString) +from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -Query = GraphQLObjectType('Query', lambda: { - 'hello': GraphQLField(GraphQLString, resolver=lambda *_: "World"), -}) +Query = GraphQLObjectType( + "Query", lambda: {"hello": GraphQLField(GraphQLString, resolver=lambda *_: "World")} +) schema = GraphQLSchema(Query) diff --git a/graphql/backend/tests/test_base.py b/graphql/backend/tests/test_base.py index c084c91c..c9a8dfda 100644 --- a/graphql/backend/tests/test_base.py +++ b/graphql/backend/tests/test_base.py @@ -22,5 +22,5 @@ def test_set_default_backend_fails_if_invalid_backend(): default_backend = get_default_backend() with pytest.raises(Exception) as exc_info: set_default_backend(object()) - assert str(exc_info.value) == 'backend must be an instance of GraphQLBackend.' + assert str(exc_info.value) == "backend must be an instance of GraphQLBackend." assert get_default_backend() == default_backend diff --git a/graphql/backend/tests/test_cache.py b/graphql/backend/tests/test_cache.py index 3f25345a..a20a18c1 100644 --- a/graphql/backend/tests/test_cache.py +++ b/graphql/backend/tests/test_cache.py @@ -20,7 +20,9 @@ def test_cached_backend(): def test_cached_backend_with_use_consistent_hash(): # type: () -> None - cached_backend = GraphQLCachedBackend(GraphQLCoreBackend(), use_consistent_hash=True) + cached_backend = GraphQLCachedBackend( + GraphQLCoreBackend(), use_consistent_hash=True + ) document1 = cached_backend.document_from_string(schema, "{ hello }") document2 = cached_backend.document_from_string(schema, "{ hello }") assert document1 == document2 diff --git a/graphql/backend/tests/test_compileddocument.py b/graphql/backend/tests/test_compileddocument.py index 892af9bd..787089ab 100644 --- a/graphql/backend/tests/test_compileddocument.py +++ b/graphql/backend/tests/test_compileddocument.py @@ -6,16 +6,17 @@ def test_compileddocument_from_module_dict(): # type: () -> None - document_string = '{ hello }' + document_string = "{ hello }" document_ast = parse(document_string) - document = GraphQLCompiledDocument.from_module_dict(schema, { - 'document_string': document_string, - 'document_ast': document_ast, - 'execute': lambda *_: True - }) - assert document.operations_map == { - None: 'query' - } + document = GraphQLCompiledDocument.from_module_dict( + schema, + { + "document_string": document_string, + "document_ast": document_ast, + "execute": lambda *_: True, + }, + ) + assert document.operations_map == {None: "query"} assert document.document_string == document_string assert document.document_ast == document_ast assert document.schema == schema @@ -24,7 +25,7 @@ def test_compileddocument_from_module_dict(): def test_compileddocument_from_code(): # type: () -> None - document_string = '{ hello }' + document_string = "{ hello }" document_ast = parse(document_string) code = ''' # -*- coding: utf-8 -*- @@ -47,11 +48,11 @@ def loc(start, end): def execute(*_): return True -'''.format(document_string=document_string, document_ast=ast_to_code(document_ast)) +'''.format( + document_string=document_string, document_ast=ast_to_code(document_ast) + ) document = GraphQLCompiledDocument.from_code(schema, code) - assert document.operations_map == { - None: 'query' - } + assert document.operations_map == {None: "query"} assert document.document_string == document_string assert document.document_ast == document_ast assert document.schema == schema diff --git a/graphql/backend/tests/test_document.py b/graphql/backend/tests/test_document.py index aaf4c619..e3b74c95 100644 --- a/graphql/backend/tests/test_document.py +++ b/graphql/backend/tests/test_document.py @@ -11,68 +11,73 @@ def create_document(document_string): schema=schema, document_string=document_string, document_ast=document_ast, - execute=lambda *_: None + execute=lambda *_: None, ) def test_document_operations_map_unnamed_operation(): # type: () -> None - document = create_document('{ hello }') - assert document.operations_map == { - None: 'query' - } + document = create_document("{ hello }") + assert document.operations_map == {None: "query"} def test_document_operations_map_multiple_queries(): - document = create_document(''' + document = create_document( + """ query MyQuery1 { hello } query MyQuery2 { hello } - ''') - assert document.operations_map == { - 'MyQuery1': 'query', - 'MyQuery2': 'query' - } + """ + ) + assert document.operations_map == {"MyQuery1": "query", "MyQuery2": "query"} def test_document_operations_map_multiple_queries(): # type: () -> None - document = create_document(''' + document = create_document( + """ query MyQuery { hello } mutation MyMutation { hello } subscription MySubscription { hello } - ''') + """ + ) assert document.operations_map == { - 'MyQuery': 'query', - 'MyMutation': 'mutation', - 'MySubscription': 'subscription' + "MyQuery": "query", + "MyMutation": "mutation", + "MySubscription": "subscription", } def test_document_get_operation_type_unnamed_operation(): # type: () -> None - document = create_document(''' + document = create_document( + """ query { hello } - ''') - assert document.get_operation_type(None) == 'query' - assert document.get_operation_type('Unknown') is None + """ + ) + assert document.get_operation_type(None) == "query" + assert document.get_operation_type("Unknown") is None def test_document_get_operation_type_multiple_operations(): # type: () -> None - document = create_document(''' + document = create_document( + """ query MyQuery { hello } mutation MyMutation {hello} - ''') + """ + ) assert document.get_operation_type(None) is None - assert document.get_operation_type('MyQuery') == 'query' - assert document.get_operation_type('MyMutation') == 'mutation' - assert document.get_operation_type('Unexistent') is None + assert document.get_operation_type("MyQuery") == "query" + assert document.get_operation_type("MyMutation") == "mutation" + assert document.get_operation_type("Unexistent") is None def test_document_get_operation_type_multiple_operations_empty_operation_name(): # type: () -> None - document = create_document(''' + document = create_document( + """ query MyQuery { hello } mutation {hello} - ''') - assert document.get_operation_type(None) is 'mutation' + """ + ) + assert document.get_operation_type(None) is "mutation" diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index d91b3a18..1f905fae 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -3,8 +3,7 @@ from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString) +from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString from graphql.execution.base import ResolveInfo from mypy_extensions import NoReturn from typing import Any @@ -13,31 +12,31 @@ def test_raise(): # type: () -> None - ast = parse('query Example { a }') + ast = parse("query Example { a }") def resolver(context, *_): # type: (Optional[Any], *ResolveInfo) -> NoReturn - raise Exception('Failed') + raise Exception("Failed") - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - }) + Type = GraphQLObjectType( + "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)} + ) result = execute(GraphQLSchema(Type), ast) - assert str(result.errors[0]) == 'Failed' + assert str(result.errors[0]) == "Failed" def test_reraise(): # type: () -> None - ast = parse('query Example { a }') + ast = parse("query Example { a }") def resolver(context, *_): # type: (Optional[Any], *ResolveInfo) -> NoReturn - raise Exception('Failed') + raise Exception("Failed") - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver), - }) + Type = GraphQLObjectType( + "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)} + ) result = execute(GraphQLSchema(Type), ast) with pytest.raises(Exception) as exc_info: @@ -45,15 +44,19 @@ def resolver(context, *_): extracted = traceback.extract_tb(exc_info.tb) formatted_tb = [row[2:] for row in extracted] - if formatted_tb[2][0] == 'reraise': + if formatted_tb[2][0] == "reraise": formatted_tb[2:] = formatted_tb[3:] assert formatted_tb == [ - ('test_reraise', 'result.errors[0].reraise()'), - ('reraise', 'six.reraise(type(self), self, self.stack)'), + ("test_reraise", "result.errors[0].reraise()"), + ("reraise", "six.reraise(type(self), self, self.stack)"), # ('reraise', 'raise value.with_traceback(tb)'), - ('resolve_or_error', 'return executor.execute(resolve_fn, source, info, **args)'), - ('execute', 'return fn(*args, **kwargs)'), ('resolver', "raise Exception('Failed')") + ( + "resolve_or_error", + "return executor.execute(resolve_fn, source, info, **args)", + ), + ("execute", "return fn(*args, **kwargs)"), + ("resolver", 'raise Exception("Failed")'), ] # assert formatted_tb == [ # ('test_reraise', 'result.errors[0].reraise()'), @@ -65,4 +68,4 @@ def resolver(context, *_): # ('resolver', "raise Exception('Failed')") # ] - assert str(exc_info.value) == 'Failed' + assert str(exc_info.value) == "Failed" diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 82e802bf..f35043be 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -116,17 +116,17 @@ def execute( allow_subscriptions, ) - def executor(v): # type: Optional[Any] - # type: (...) -> Union[OrderedDict, Promise, AnonymousObservable] + def executor(v): + # type: (Optional[Any]) -> Union[OrderedDict, Promise, AnonymousObservable] return execute_operation(exe_context, exe_context.operation, root) - def on_rejected(error): # type: Union[Exception, GraphQLError, GraphQLLocatedError] - # type: (...) -> Optional[Any] + def on_rejected(error): + # type: (Exception) -> Optional[Any] exe_context.errors.append(error) return None - def on_resolve(data): # type: Union[None, OrderedDict, AnonymousObservable] - # type: (...) -> Union[ExecutionResult, AnonymousObservable] + def on_resolve(data): + # type: (Union[None, OrderedDict, AnonymousObservable]) -> Union[ExecutionResult, AnonymousObservable] if isinstance(data, Observable): return data diff --git a/graphql/execution/executors/asyncio_utils.py b/graphql/execution/executors/asyncio_utils.py index 363e8a55..17ec5c79 100644 --- a/graphql/execution/executors/asyncio_utils.py +++ b/graphql/execution/executors/asyncio_utils.py @@ -28,4 +28,3 @@ async def iterate_asyncgen(asyncgen, observer): pass except Exception as e: observer.on_error(e) - diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py index b8f8b3ee..ef3eacd3 100644 --- a/graphql/execution/tests/test_abstract.py +++ b/graphql/execution/tests/test_abstract.py @@ -388,4 +388,3 @@ def type_string_resolver(obj, *_): assert result.data == { "pets": [{"woofs": True, "name": "Odie"}, {"name": "Garfield", "meows": False}] } - diff --git a/graphql/execution/tests/test_directives.py b/graphql/execution/tests/test_directives.py index 7ab221e1..acc1ac14 100644 --- a/graphql/execution/tests/test_directives.py +++ b/graphql/execution/tests/test_directives.py @@ -275,4 +275,3 @@ def test_works_directives_no_include_or_skip(): result = execute_test_query("{ a, b @include(if: false) @skip(if: false) }") assert not result.errors assert result.data == {"a": "a"} - diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index 6d72e494..88e5b693 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -6,25 +6,34 @@ from graphql.error import GraphQLError from graphql.execution import MiddlewareManager, execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLBoolean, GraphQLField, - GraphQLInt, GraphQLList, GraphQLObjectType, - GraphQLSchema, GraphQLString, GraphQLNonNull, GraphQLID) +from graphql.type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLField, + GraphQLInt, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLNonNull, + GraphQLID, +) from promise import Promise def test_executes_arbitary_code(): # type: () -> None class Data(object): - a = 'Apple' - b = 'Banana' - c = 'Cookie' - d = 'Donut' - e = 'Egg' - f = 'Fish' + a = "Apple" + b = "Banana" + c = "Cookie" + d = "Donut" + e = "Egg" + f = "Fish" def pic(self, size=50): # type: (int) -> str - return 'Pic of size: {}'.format(size) + return "Pic of size: {}".format(size) def deep(self): # type: () -> DeepData @@ -36,15 +45,15 @@ def promise(self): return Data() class DeepData(object): - a = 'Already Been Done' - b = 'Boring' - c = ['Contrived', None, 'Confusing'] + a = "Already Been Done" + b = "Boring" + c = ["Contrived", None, "Confusing"] def deeper(self): # type: () -> List[Optional[Data]] return [Data(), None, Data()] - doc = ''' + doc = """ query Example($size: Int) { a, b, @@ -71,62 +80,72 @@ def deeper(self): d e } - ''' + """ ast = parse(doc) expected = { - 'a': 'Apple', - 'b': 'Banana', - 'x': 'Cookie', - 'd': 'Donut', - 'e': 'Egg', - 'f': 'Fish', - 'pic': 'Pic of size: 100', - 'promise': {'a': 'Apple'}, - 'deep': { - 'a': 'Already Been Done', - 'b': 'Boring', - 'c': ['Contrived', None, 'Confusing'], - 'deeper': [ - {'a': 'Apple', 'b': 'Banana'}, + "a": "Apple", + "b": "Banana", + "x": "Cookie", + "d": "Donut", + "e": "Egg", + "f": "Fish", + "pic": "Pic of size: 100", + "promise": {"a": "Apple"}, + "deep": { + "a": "Already Been Done", + "b": "Boring", + "c": ["Contrived", None, "Confusing"], + "deeper": [ + {"a": "Apple", "b": "Banana"}, None, - {'a': 'Apple', 'b': 'Banana'}]} + {"a": "Apple", "b": "Banana"}, + ], + }, } - DataType = GraphQLObjectType('DataType', lambda: { - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - 'c': GraphQLField(GraphQLString), - 'd': GraphQLField(GraphQLString), - 'e': GraphQLField(GraphQLString), - 'f': GraphQLField(GraphQLString), - 'pic': GraphQLField( - args={'size': GraphQLArgument(GraphQLInt)}, - type=GraphQLString, - resolver=lambda obj, info, size: obj.pic(size), - ), - 'deep': GraphQLField(DeepDataType), - 'promise': GraphQLField(DataType), - }) - - DeepDataType = GraphQLObjectType('DeepDataType', { - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - 'c': GraphQLField(GraphQLList(GraphQLString)), - 'deeper': GraphQLField(GraphQLList(DataType)), - }) + DataType = GraphQLObjectType( + "DataType", + lambda: { + "a": GraphQLField(GraphQLString), + "b": GraphQLField(GraphQLString), + "c": GraphQLField(GraphQLString), + "d": GraphQLField(GraphQLString), + "e": GraphQLField(GraphQLString), + "f": GraphQLField(GraphQLString), + "pic": GraphQLField( + args={"size": GraphQLArgument(GraphQLInt)}, + type=GraphQLString, + resolver=lambda obj, info, size: obj.pic(size), + ), + "deep": GraphQLField(DeepDataType), + "promise": GraphQLField(DataType), + }, + ) + + DeepDataType = GraphQLObjectType( + "DeepDataType", + { + "a": GraphQLField(GraphQLString), + "b": GraphQLField(GraphQLString), + "c": GraphQLField(GraphQLList(GraphQLString)), + "deeper": GraphQLField(GraphQLList(DataType)), + }, + ) schema = GraphQLSchema(query=DataType) - result = execute(schema, ast, Data(), - operation_name='Example', variable_values={'size': 100}) + result = execute( + schema, ast, Data(), operation_name="Example", variable_values={"size": 100} + ) assert not result.errors assert result.data == expected def test_merges_parallel_fragments(): # type: () -> None - ast = parse(''' + ast = parse( + """ { a, deep {...FragOne, ...FragTwo} } fragment FragOne on Type { @@ -138,298 +157,285 @@ def test_merges_parallel_fragments(): c deep { c, deeper: deep { c } } } - ''') - - Type = GraphQLObjectType('Type', lambda: { - 'a': GraphQLField(GraphQLString, - resolver=lambda *_: 'Apple'), - 'b': GraphQLField(GraphQLString, - resolver=lambda *_: 'Banana'), - 'c': GraphQLField(GraphQLString, - resolver=lambda *_: 'Cherry'), - 'deep': GraphQLField(Type, resolver=lambda *_: {}), - }) + """ + ) + + Type = GraphQLObjectType( + "Type", + lambda: { + "a": GraphQLField(GraphQLString, resolver=lambda *_: "Apple"), + "b": GraphQLField(GraphQLString, resolver=lambda *_: "Banana"), + "c": GraphQLField(GraphQLString, resolver=lambda *_: "Cherry"), + "deep": GraphQLField(Type, resolver=lambda *_: {}), + }, + ) schema = GraphQLSchema(query=Type) result = execute(schema, ast) assert not result.errors - assert result.data == \ - { - 'a': 'Apple', - 'deep': { - 'b': 'Banana', - 'c': 'Cherry', - 'deep': { - 'b': 'Banana', - 'c': 'Cherry', - 'deeper': { - 'b': 'Banana', - 'c': 'Cherry'}}} - } + assert result.data == { + "a": "Apple", + "deep": { + "b": "Banana", + "c": "Cherry", + "deep": { + "b": "Banana", + "c": "Cherry", + "deeper": {"b": "Banana", "c": "Cherry"}, + }, + }, + } def test_threads_root_value_context_correctly(): # type: () -> None - doc = 'query Example { a }' + doc = "query Example { a }" class Data(object): - context_thing = 'thing' + context_thing = "thing" ast = parse(doc) def resolver(root_value, *_): # type: (Data, *ResolveInfo) -> None - assert root_value.context_thing == 'thing' + assert root_value.context_thing == "thing" resolver.got_here = True resolver.got_here = False - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString, resolver=resolver) - }) + Type = GraphQLObjectType( + "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)} + ) - result = execute(GraphQLSchema(Type), ast, - Data(), operation_name='Example') + result = execute(GraphQLSchema(Type), ast, Data(), operation_name="Example") assert not result.errors assert resolver.got_here def test_correctly_threads_arguments(): # type: () -> None - doc = ''' + doc = """ query Example { b(numArg: 123, stringArg: "foo") } - ''' + """ def resolver(source, info, numArg, stringArg): # type: (Optional[Any], ResolveInfo, int, str) -> None assert numArg == 123 - assert stringArg == 'foo' + assert stringArg == "foo" resolver.got_here = True resolver.got_here = False doc_ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'b': GraphQLField( - GraphQLString, - args={ - 'numArg': GraphQLArgument(GraphQLInt), - 'stringArg': GraphQLArgument(GraphQLString), - }, - resolver=resolver), - }) + Type = GraphQLObjectType( + "Type", + { + "b": GraphQLField( + GraphQLString, + args={ + "numArg": GraphQLArgument(GraphQLInt), + "stringArg": GraphQLArgument(GraphQLString), + }, + resolver=resolver, + ) + }, + ) - result = execute(GraphQLSchema(Type), doc_ast, - None, operation_name='Example') + result = execute(GraphQLSchema(Type), doc_ast, None, operation_name="Example") assert not result.errors assert resolver.got_here def test_nulls_out_error_subtrees(): # type: () -> None - doc = '''{ + doc = """{ ok, error - }''' + }""" class Data(object): - def ok(self): # type: () -> str - return 'ok' + return "ok" def error(self): # type: () -> NoReturn - raise Exception('Error getting error') + raise Exception("Error getting error") doc_ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'ok': GraphQLField(GraphQLString), - 'error': GraphQLField(GraphQLString), - }) + Type = GraphQLObjectType( + "Type", + {"ok": GraphQLField(GraphQLString), "error": GraphQLField(GraphQLString)}, + ) result = execute(GraphQLSchema(Type), doc_ast, Data()) - assert result.data == {'ok': 'ok', 'error': None} + assert result.data == {"ok": "ok", "error": None} assert len(result.errors) == 1 - assert result.errors[0].message == 'Error getting error' + assert result.errors[0].message == "Error getting error" # TODO: check error location def test_uses_the_inline_operation_if_no_operation_name_is_provided(): # type: () -> None - doc = '{ a }' + doc = "{ a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Type), ast, Data()) assert not result.errors - assert result.data == {'a': 'b'} + assert result.data == {"a": "b"} def test_uses_the_only_operation_if_no_operation_name_is_provided(): # type: () -> None - doc = 'query Example { a }' + doc = "query Example { a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Type), ast, Data()) assert not result.errors - assert result.data == {'a': 'b'} + assert result.data == {"a": "b"} def test_uses_the_named_operation_if_operation_name_is_provided(): # type: () -> None - doc = 'query Example { first: a } query OtherExample { second: a }' + doc = "query Example { first: a } query OtherExample { second: a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) - result = execute(GraphQLSchema(Type), ast, Data(), - operation_name='OtherExample') + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) + result = execute(GraphQLSchema(Type), ast, Data(), operation_name="OtherExample") assert not result.errors - assert result.data == {'second': 'b'} + assert result.data == {"second": "b"} def test_raises_if_no_operation_is_provided(): # type: () -> None - doc = 'fragment Example on Type { a }' + doc = "fragment Example on Type { a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) with raises(GraphQLError) as excinfo: execute(GraphQLSchema(Type), ast, Data()) - assert 'Must provide an operation.' == str(excinfo.value) + assert "Must provide an operation." == str(excinfo.value) def test_raises_if_no_operation_name_is_provided_with_multiple_operations(): # type: () -> None - doc = 'query Example { a } query OtherExample { a }' + doc = "query Example { a } query OtherExample { a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) with raises(GraphQLError) as excinfo: - execute(GraphQLSchema(Type), ast, Data(), - operation_name="UnknownExample") + execute(GraphQLSchema(Type), ast, Data(), operation_name="UnknownExample") assert 'Unknown operation named "UnknownExample".' == str(excinfo.value) def test_raises_if_unknown_operation_name_is_provided(): # type: () -> None - doc = 'query Example { a } query OtherExample { a }' + doc = "query Example { a } query OtherExample { a }" class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) with raises(GraphQLError) as excinfo: execute(GraphQLSchema(Type), ast, Data()) - assert 'Must provide operation name if query contains multiple operations.' == str( - excinfo.value) + assert "Must provide operation name if query contains multiple operations." == str( + excinfo.value + ) def test_uses_the_query_schema_for_queries(): # type: () -> None - doc = 'query Q { a } mutation M { c } subscription S { a }' + doc = "query Q { a } mutation M { c } subscription S { a }" class Data(object): - a = 'b' - c = 'd' + a = "b" + c = "d" ast = parse(doc) - Q = GraphQLObjectType('Q', { - 'a': GraphQLField(GraphQLString) - }) - M = GraphQLObjectType('M', { - 'c': GraphQLField(GraphQLString) - }) - S = GraphQLObjectType('S', { - 'a': GraphQLField(GraphQLString) - }) - result = execute(GraphQLSchema(Q, M, S), ast, Data(), operation_name='Q') + Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)}) + M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)}) + S = GraphQLObjectType("S", {"a": GraphQLField(GraphQLString)}) + result = execute(GraphQLSchema(Q, M, S), ast, Data(), operation_name="Q") assert not result.errors - assert result.data == {'a': 'b'} + assert result.data == {"a": "b"} def test_uses_the_mutation_schema_for_queries(): # type: () -> None - doc = 'query Q { a } mutation M { c }' + doc = "query Q { a } mutation M { c }" class Data(object): - a = 'b' - c = 'd' + a = "b" + c = "d" ast = parse(doc) - Q = GraphQLObjectType('Q', { - 'a': GraphQLField(GraphQLString) - }) - M = GraphQLObjectType('M', { - 'c': GraphQLField(GraphQLString) - }) - result = execute(GraphQLSchema(Q, M), ast, Data(), operation_name='M') + Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)}) + M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)}) + result = execute(GraphQLSchema(Q, M), ast, Data(), operation_name="M") assert not result.errors - assert result.data == {'c': 'd'} + assert result.data == {"c": "d"} def test_uses_the_subscription_schema_for_subscriptions(): # type: () -> None from rx import Observable - doc = 'query Q { a } subscription S { a }' + + doc = "query Q { a } subscription S { a }" class Data(object): - a = 'b' - c = 'd' + a = "b" + c = "d" ast = parse(doc) - Q = GraphQLObjectType('Q', { - 'a': GraphQLField(GraphQLString) - }) - S = GraphQLObjectType('S', { - 'a': GraphQLField(GraphQLString, resolver=lambda root, info: Observable.from_(['b'])) - }) - result = execute(GraphQLSchema(Q, subscription=S), - ast, Data(), operation_name='S', allow_subscriptions=True) + Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)}) + S = GraphQLObjectType( + "S", + { + "a": GraphQLField( + GraphQLString, resolver=lambda root, info: Observable.from_(["b"]) + ) + }, + ) + result = execute( + GraphQLSchema(Q, subscription=S), + ast, + Data(), + operation_name="S", + allow_subscriptions=True, + ) assert isinstance(result, Observable) l = [] result.subscribe(l.append) result = l[0] assert not result.errors - assert result.data == {'a': 'b'} + assert result.data == {"a": "b"} def test_avoids_recursion(): # type: () -> None - doc = ''' + doc = """ query Q { a ...Frag @@ -439,30 +445,24 @@ def test_avoids_recursion(): a, ...Frag } - ''' + """ class Data(object): - a = 'b' + a = "b" ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'a': GraphQLField(GraphQLString) - }) - result = execute(GraphQLSchema(Type), ast, Data(), operation_name='Q') + Type = GraphQLObjectType("Type", {"a": GraphQLField(GraphQLString)}) + result = execute(GraphQLSchema(Type), ast, Data(), operation_name="Q") assert not result.errors - assert result.data == {'a': 'b'} + assert result.data == {"a": "b"} def test_does_not_include_illegal_fields_in_output(): # type: () -> None - doc = 'mutation M { thisIsIllegalDontIncludeMe }' + doc = "mutation M { thisIsIllegalDontIncludeMe }" ast = parse(doc) - Q = GraphQLObjectType('Q', { - 'a': GraphQLField(GraphQLString) - }) - M = GraphQLObjectType('M', { - 'c': GraphQLField(GraphQLString) - }) + Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)}) + M = GraphQLObjectType("M", {"c": GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Q, M), ast) assert not result.errors assert result.data == {} @@ -470,114 +470,105 @@ def test_does_not_include_illegal_fields_in_output(): def test_does_not_include_arguments_that_were_not_set(): # type: () -> None - schema = GraphQLSchema(GraphQLObjectType( - 'Type', - { - 'field': GraphQLField( - GraphQLString, - resolver=lambda source, info, **args: args and json.dumps( - args, sort_keys=True, separators=(',', ':')), - args={ - 'a': GraphQLArgument(GraphQLBoolean), - 'b': GraphQLArgument(GraphQLBoolean), - 'c': GraphQLArgument(GraphQLBoolean), - 'd': GraphQLArgument(GraphQLInt), - 'e': GraphQLArgument(GraphQLInt), - } - ) - } - )) + schema = GraphQLSchema( + GraphQLObjectType( + "Type", + { + "field": GraphQLField( + GraphQLString, + resolver=lambda source, info, **args: args + and json.dumps(args, sort_keys=True, separators=(",", ":")), + args={ + "a": GraphQLArgument(GraphQLBoolean), + "b": GraphQLArgument(GraphQLBoolean), + "c": GraphQLArgument(GraphQLBoolean), + "d": GraphQLArgument(GraphQLInt), + "e": GraphQLArgument(GraphQLInt), + }, + ) + }, + ) + ) - ast = parse('{ field(a: true, c: false, e: 0) }') + ast = parse("{ field(a: true, c: false, e: 0) }") result = execute(schema, ast) - assert result.data == { - 'field': '{"a":true,"c":false,"e":0}' - } + assert result.data == {"field": '{"a":true,"c":false,"e":0}'} def test_fails_when_an_is_type_of_check_is_not_met(): # type: () -> None class Special(object): - def __init__(self, value): # type: (str) -> None self.value = value class NotSpecial(object): - def __init__(self, value): # type: (str) -> None self.value = value SpecialType = GraphQLObjectType( - 'SpecialType', - fields={ - 'value': GraphQLField(GraphQLString), - }, - is_type_of=lambda obj, info: isinstance(obj, Special) + "SpecialType", + fields={"value": GraphQLField(GraphQLString)}, + is_type_of=lambda obj, info: isinstance(obj, Special), ) schema = GraphQLSchema( GraphQLObjectType( - name='Query', + name="Query", fields={ - 'specials': GraphQLField( - GraphQLList(SpecialType), - resolver=lambda root, *_: root['specials'] + "specials": GraphQLField( + GraphQLList(SpecialType), resolver=lambda root, *_: root["specials"] ) - } + }, ) ) - query = parse('{ specials { value } }') - value = { - 'specials': [Special('foo'), NotSpecial('bar')] - } + query = parse("{ specials { value } }") + value = {"specials": [Special("foo"), NotSpecial("bar")]} result = execute(schema, query, value) - assert result.data == { - 'specials': [ - {'value': 'foo'}, - None - ] - } + assert result.data == {"specials": [{"value": "foo"}, None]} assert 'Expected value of type "SpecialType" but got: NotSpecial.' in [ - str(e) for e in result.errors] + str(e) for e in result.errors + ] def test_fails_to_execute_a_query_containing_a_type_definition(): # type: () -> None - query = parse(''' + query = parse( + """ { foo } type Query { foo: String } - ''') + """ + ) schema = GraphQLSchema( - GraphQLObjectType( - name='Query', - fields={ - 'foo': GraphQLField(GraphQLString) - } - ) + GraphQLObjectType(name="Query", fields={"foo": GraphQLField(GraphQLString)}) ) with raises(GraphQLError) as excinfo: execute(schema, query) - assert excinfo.value.message == 'GraphQL cannot execute a request containing a ObjectTypeDefinition.' + assert ( + excinfo.value.message + == "GraphQL cannot execute a request containing a ObjectTypeDefinition." + ) def test_exceptions_are_reraised_if_specified(mocker): # type: (MockFixture) -> None - logger = mocker.patch('graphql.execution.executor.logger') + logger = mocker.patch("graphql.execution.executor.logger") - query = parse(''' + query = parse( + """ { foo } - ''') + """ + ) def resolver(*_): # type: (*Any) -> NoReturn @@ -585,41 +576,38 @@ def resolver(*_): schema = GraphQLSchema( GraphQLObjectType( - name='Query', - fields={ - 'foo': GraphQLField(GraphQLString, resolver=resolver) - } + name="Query", fields={"foo": GraphQLField(GraphQLString, resolver=resolver)} ) ) execute(schema, query) logger.exception.assert_called_with( - "An error occurred while resolving field Query.foo") + "An error occurred while resolving field Query.foo" + ) def test_middleware(): # type: () -> None - doc = '''{ + doc = """{ ok not_ok - }''' + }""" class Data(object): - def ok(self): # type: () -> str - return 'ok' + return "ok" def not_ok(self): # type: () -> str - return 'not_ok' + return "not_ok" doc_ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'ok': GraphQLField(GraphQLString), - 'not_ok': GraphQLField(GraphQLString), - }) + Type = GraphQLObjectType( + "Type", + {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)}, + ) def reversed_middleware(next, *args, **kwargs): # type: (Callable, *Any, **Any) -> Promise @@ -627,34 +615,32 @@ def reversed_middleware(next, *args, **kwargs): return p.then(lambda x: x[::-1]) middlewares = MiddlewareManager(reversed_middleware) - result = execute(GraphQLSchema(Type), doc_ast, - Data(), middleware=middlewares) - assert result.data == {'ok': 'ko', 'not_ok': 'ko_ton'} + result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares) + assert result.data == {"ok": "ko", "not_ok": "ko_ton"} def test_middleware_class(): # type: () -> None - doc = '''{ + doc = """{ ok not_ok - }''' + }""" class Data(object): - def ok(self): # type: () -> str - return 'ok' + return "ok" def not_ok(self): # type: () -> str - return 'not_ok' + return "not_ok" doc_ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'ok': GraphQLField(GraphQLString), - 'not_ok': GraphQLField(GraphQLString), - }) + Type = GraphQLObjectType( + "Type", + {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)}, + ) class MyMiddleware(object): def resolve(self, next, *args, **kwargs): @@ -663,34 +649,32 @@ def resolve(self, next, *args, **kwargs): return p.then(lambda x: x[::-1]) middlewares = MiddlewareManager(MyMiddleware()) - result = execute(GraphQLSchema(Type), doc_ast, - Data(), middleware=middlewares) - assert result.data == {'ok': 'ko', 'not_ok': 'ko_ton'} + result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares) + assert result.data == {"ok": "ko", "not_ok": "ko_ton"} def test_middleware_skip_promise_wrap(): # type: () -> None - doc = '''{ + doc = """{ ok not_ok - }''' + }""" class Data(object): - def ok(self): # type: () -> str - return 'ok' + return "ok" def not_ok(self): # type: () -> str - return 'not_ok' + return "not_ok" doc_ast = parse(doc) - Type = GraphQLObjectType('Type', { - 'ok': GraphQLField(GraphQLString), - 'not_ok': GraphQLField(GraphQLString), - }) + Type = GraphQLObjectType( + "Type", + {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)}, + ) class MyPromiseMiddleware(object): def resolve(self, next, *args, **kwargs): @@ -703,89 +687,111 @@ def resolve(self, next, *args, **kwargs): return next(*args, **kwargs) middlewares_with_promise = MiddlewareManager( - MyPromiseMiddleware(), wrap_in_promise=False) + MyPromiseMiddleware(), wrap_in_promise=False + ) middlewares_without_promise = MiddlewareManager( - MyEmptyMiddleware(), wrap_in_promise=False) + MyEmptyMiddleware(), wrap_in_promise=False + ) - result1 = execute(GraphQLSchema(Type), doc_ast, Data(), - middleware=middlewares_with_promise) - result2 = execute(GraphQLSchema(Type), doc_ast, Data(), - middleware=middlewares_without_promise) + result1 = execute( + GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares_with_promise + ) + result2 = execute( + GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares_without_promise + ) assert result1.data == result2.data and result1.data == { - 'ok': 'ok', 'not_ok': 'not_ok'} + "ok": "ok", + "not_ok": "not_ok", + } def test_executor_properly_propogates_path_data(mocker): # type: (MockFixture) -> None - time_mock = mocker.patch('time.time') + time_mock = mocker.patch("time.time") time_mock.side_effect = range(0, 10000) - BlogImage = GraphQLObjectType('BlogImage', { - 'url': GraphQLField(GraphQLString), - 'width': GraphQLField(GraphQLInt), - 'height': GraphQLField(GraphQLInt), - }) - - BlogAuthor = GraphQLObjectType('Author', lambda: { - 'id': GraphQLField(GraphQLString), - 'name': GraphQLField(GraphQLString), - 'pic': GraphQLField(BlogImage, - args={ - 'width': GraphQLArgument(GraphQLInt), - 'height': GraphQLArgument(GraphQLInt), - }, - resolver=lambda obj, info, **args: - obj.pic(args['width'], args['height']) - ), - 'recentArticle': GraphQLField(BlogArticle), - }) - - BlogArticle = GraphQLObjectType('Article', { - 'id': GraphQLField(GraphQLNonNull(GraphQLString)), - 'isPublished': GraphQLField(GraphQLBoolean), - 'author': GraphQLField(BlogAuthor), - 'title': GraphQLField(GraphQLString), - 'body': GraphQLField(GraphQLString), - 'keywords': GraphQLField(GraphQLList(GraphQLString)), - }) - - BlogQuery = GraphQLObjectType('Query', { - 'article': GraphQLField( - BlogArticle, - args={'id': GraphQLArgument(GraphQLID)}, - resolver=lambda obj, info, **args: Article(args['id'])), - 'feed': GraphQLField( - GraphQLList(BlogArticle), - resolver=lambda *_: map(Article, range(1, 2 + 1))), - }) + BlogImage = GraphQLObjectType( + "BlogImage", + { + "url": GraphQLField(GraphQLString), + "width": GraphQLField(GraphQLInt), + "height": GraphQLField(GraphQLInt), + }, + ) + + BlogAuthor = GraphQLObjectType( + "Author", + lambda: { + "id": GraphQLField(GraphQLString), + "name": GraphQLField(GraphQLString), + "pic": GraphQLField( + BlogImage, + args={ + "width": GraphQLArgument(GraphQLInt), + "height": GraphQLArgument(GraphQLInt), + }, + resolver=lambda obj, info, **args: obj.pic( + args["width"], args["height"] + ), + ), + "recentArticle": GraphQLField(BlogArticle), + }, + ) + + BlogArticle = GraphQLObjectType( + "Article", + { + "id": GraphQLField(GraphQLNonNull(GraphQLString)), + "isPublished": GraphQLField(GraphQLBoolean), + "author": GraphQLField(BlogAuthor), + "title": GraphQLField(GraphQLString), + "body": GraphQLField(GraphQLString), + "keywords": GraphQLField(GraphQLList(GraphQLString)), + }, + ) + + BlogQuery = GraphQLObjectType( + "Query", + { + "article": GraphQLField( + BlogArticle, + args={"id": GraphQLArgument(GraphQLID)}, + resolver=lambda obj, info, **args: Article(args["id"]), + ), + "feed": GraphQLField( + GraphQLList(BlogArticle), + resolver=lambda *_: map(Article, range(1, 2 + 1)), + ), + }, + ) BlogSchema = GraphQLSchema(BlogQuery) class Article(object): - def __init__(self, id): # type: (int) -> None self.id = id self.isPublished = True self.author = Author() - self.title = 'My Article {}'.format(id) - self.body = 'This is a post' - self.hidden = 'This data is not exposed in the schema' - self.keywords = ['foo', 'bar', 1, True, None] + self.title = "My Article {}".format(id) + self.body = "This is a post" + self.hidden = "This data is not exposed in the schema" + self.keywords = ["foo", "bar", 1, True, None] class Author(object): id = 123 - name = 'John Smith' + name = "John Smith" def pic(self, width, height): return Pic(123, width, height) @property - def recentArticle(self): return Article(1) + def recentArticle(self): + return Article(1) class Pic(object): def __init__(self, uid, width, height): - self.url = 'cdn://{}'.format(uid) + self.url = "cdn://{}".format(uid) self.width = str(width) self.height = str(height) @@ -794,18 +800,19 @@ def __init__(self): # type: () -> None self.paths = [] - def resolve(self, - _next, # type: Callable - root, # type: Optional[Article] - info, # type: ResolveInfo - *args, # type: Any - **kwargs # type: Any - ): + def resolve( + self, + _next, # type: Callable + root, # type: Optional[Article] + info, # type: ResolveInfo + *args, # type: Any + **kwargs # type: Any + ): # type: (...) -> Promise self.paths.append(info.path) return _next(root, info, *args, **kwargs) - request = ''' + request = """ { feed { id @@ -822,53 +829,52 @@ def resolve(self, body, hidden, } - ''' + """ paths_middleware = PathCollectorMiddleware() - result = execute(BlogSchema, parse(request), middleware=(paths_middleware, )) + result = execute(BlogSchema, parse(request), middleware=(paths_middleware,)) assert not result.errors - assert result.data == \ - { - "feed": [ - { - "id": "1", - "title": "My Article 1", - "body": "This is a post", - "author": { - "id": "123", - "name": "John Smith", - "nameAlias": "John Smith" - } + assert result.data == { + "feed": [ + { + "id": "1", + "title": "My Article 1", + "body": "This is a post", + "author": { + "id": "123", + "name": "John Smith", + "nameAlias": "John Smith", }, - { - "id": "2", - "title": "My Article 2", - "body": "This is a post", - "author": { - "id": "123", - "name": "John Smith", - "nameAlias": "John Smith" - } + }, + { + "id": "2", + "title": "My Article 2", + "body": "This is a post", + "author": { + "id": "123", + "name": "John Smith", + "nameAlias": "John Smith", }, - ], - } + }, + ] + } traversed_paths = paths_middleware.paths assert traversed_paths == [ - ['feed'], - ['feed', 0, 'id'], - ['feed', 0, 'title'], - ['feed', 0, 'body'], - ['feed', 0, 'author'], - ['feed', 1, 'id'], - ['feed', 1, 'title'], - ['feed', 1, 'body'], - ['feed', 1, 'author'], - ['feed', 0, 'author', 'id'], - ['feed', 0, 'author', 'name'], - ['feed', 0, 'author', 'nameAlias'], - ['feed', 1, 'author', 'id'], - ['feed', 1, 'author', 'name'], - ['feed', 1, 'author', 'nameAlias'], + ["feed"], + ["feed", 0, "id"], + ["feed", 0, "title"], + ["feed", 0, "body"], + ["feed", 0, "author"], + ["feed", 1, "id"], + ["feed", 1, "title"], + ["feed", 1, "body"], + ["feed", 1, "author"], + ["feed", 0, "author", "id"], + ["feed", 0, "author", "name"], + ["feed", 0, "author", "nameAlias"], + ["feed", 1, "author", "id"], + ["feed", 1, "author", "name"], + ["feed", 1, "author", "nameAlias"], ] diff --git a/graphql/execution/tests/test_lists.py b/graphql/execution/tests/test_lists.py index 20bb33f1..3534a137 100644 --- a/graphql/execution/tests/test_lists.py +++ b/graphql/execution/tests/test_lists.py @@ -387,4 +387,3 @@ class TestNotNullListOfNotNullT_Array_Promise_T: # [T!]! Array> ], }, ) - diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py index c764c6ca..f880886f 100644 --- a/graphql/execution/tests/test_nonnull.py +++ b/graphql/execution/tests/test_nonnull.py @@ -896,4 +896,3 @@ def test_nulls_the_top_level_if_async_non_nullable_field_resolves_null(): ], }, ) - diff --git a/graphql/execution/tests/test_variables.py b/graphql/execution/tests/test_variables.py index 19b86283..63d64904 100644 --- a/graphql/execution/tests/test_variables.py +++ b/graphql/execution/tests/test_variables.py @@ -782,4 +782,3 @@ def test_when_argument_provided_cannot_be_parsed(self): """, {"data": {"fieldWithDefaultArgumentValue": '"Hello World"'}}, ) - diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py index d282d180..6229eb1b 100644 --- a/graphql/execution/utils.py +++ b/graphql/execution/utils.py @@ -28,6 +28,7 @@ Field, ) from .base import ResolveInfo + from types import TracebackType from typing import Any, List, Dict, Optional, Union, Callable, Set logger = logging.getLogger(__name__) @@ -142,10 +143,8 @@ def get_argument_values(self, field_def, field_ast): return result - def report_error( - self, error, traceback=None # type: GraphQLError # type: Optional[traceback] - ): - # type: (...) -> None + def report_error(self, error, traceback=None): + # type: (GraphQLError, Optional[TracebackType]) -> None exception = format_exception( type(error), error, getattr(error, "stack", None) or traceback ) diff --git a/graphql/language/ast.py b/graphql/language/ast.py index 7a8deb48..e9cb307c 100644 --- a/graphql/language/ast.py +++ b/graphql/language/ast.py @@ -1497,4 +1497,3 @@ def __copy__(self): def __hash__(self): # type: () -> int return id(self) - diff --git a/graphql/language/base.py b/graphql/language/base.py index f6d9d91b..fca28dc6 100644 --- a/graphql/language/base.py +++ b/graphql/language/base.py @@ -6,14 +6,14 @@ from .visitor import BREAK, ParallelVisitor, TypeInfoVisitor, visit __all__ = [ - 'Lexer', - 'get_location', - 'parse', - 'parse_value', - 'print_ast', - 'Source', - 'BREAK', - 'ParallelVisitor', - 'TypeInfoVisitor', - 'visit', + "Lexer", + "get_location", + "parse", + "parse_value", + "print_ast", + "Source", + "BREAK", + "ParallelVisitor", + "TypeInfoVisitor", + "visit", ] diff --git a/graphql/language/parser.py b/graphql/language/parser.py index d44e9313..fd7e5494 100644 --- a/graphql/language/parser.py +++ b/graphql/language/parser.py @@ -729,7 +729,7 @@ def parse_field_definition(parser): # type: (Parser) -> FieldDefinition start = parser.token.start - return ast.FieldDefinition( # type: ignore + return ast.FieldDefinition( # type: ignore name=parse_name(parser), arguments=parse_argument_defs(parser), type=expect(parser, TokenKind.COLON) and parse_type(parser), @@ -750,7 +750,7 @@ def parse_input_value_def(parser): # type: (Parser) -> InputValueDefinition start = parser.token.start - return ast.InputValueDefinition( # type: ignore + return ast.InputValueDefinition( # type: ignore name=parse_name(parser), type=expect(parser, TokenKind.COLON) and parse_type(parser), default_value=parse_const_value(parser) @@ -781,7 +781,7 @@ def parse_union_type_definition(parser): start = parser.token.start expect_keyword(parser, "union") - return ast.UnionTypeDefinition( # type: ignore + return ast.UnionTypeDefinition( # type: ignore name=parse_name(parser), directives=parse_directives(parser), types=expect(parser, TokenKind.EQUALS) and parse_union_members(parser), diff --git a/graphql/language/printer.py b/graphql/language/printer.py index 11e086eb..3c6c1f7d 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -316,4 +316,3 @@ def indent(maybe_str): if maybe_str: return maybe_str.replace("\n", "\n ") return "" - diff --git a/graphql/language/source.py b/graphql/language/source.py index 7af63eeb..0f737774 100644 --- a/graphql/language/source.py +++ b/graphql/language/source.py @@ -1,19 +1,17 @@ -__all__ = ['Source'] +__all__ = ["Source"] class Source(object): - __slots__ = 'body', 'name' + __slots__ = "body", "name" - def __init__(self, body, name='GraphQL'): + def __init__(self, body, name="GraphQL"): # type: (str, str) -> None self.body = body self.name = name def __eq__(self, other): - return ( - self is other or ( - isinstance(other, Source) and - self.body == other.body and - self.name == other.name - ) + return self is other or ( + isinstance(other, Source) + and self.body == other.body + and self.name == other.name ) diff --git a/graphql/language/tests/test_lexer.py b/graphql/language/tests/test_lexer.py index 36bf9c9b..dda777d9 100644 --- a/graphql/language/tests/test_lexer.py +++ b/graphql/language/tests/test_lexer.py @@ -12,223 +12,307 @@ def lex_one(s): def test_repr_token(): # type: () -> None - token = lex_one('500') + token = lex_one("500") assert repr(token) == "" def test_disallows_uncommon_control_characters(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'\u0007') + lex_one(u"\u0007") - assert u'Syntax Error GraphQL (1:1) Invalid character "\\u0007"' in excinfo.value.message + assert ( + u'Syntax Error GraphQL (1:1) Invalid character "\\u0007"' + in excinfo.value.message + ) def test_accepts_bom_header(): # type: () -> None - assert lex_one(u'\uFEFF foo') == Token(TokenKind.NAME, 2, 5, u'foo') + assert lex_one(u"\uFEFF foo") == Token(TokenKind.NAME, 2, 5, u"foo") def test_skips_whitespace(): # type: () -> None - assert lex_one(u""" + assert ( + lex_one( + u""" foo -""") == Token(TokenKind.NAME, 6, 9, 'foo') +""" + ) + == Token(TokenKind.NAME, 6, 9, "foo") + ) - assert lex_one(u""" + assert ( + lex_one( + u""" #comment foo#comment -""") == Token(TokenKind.NAME, 18, 21, 'foo') +""" + ) + == Token(TokenKind.NAME, 18, 21, "foo") + ) - assert lex_one(u""",,,foo,,,""") == Token(TokenKind.NAME, 3, 6, 'foo') + assert lex_one(u""",,,foo,,,""") == Token(TokenKind.NAME, 3, 6, "foo") def test_errors_respect_whitespace(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - lex_one(u""" + lex_one( + u""" ? -""") +""" + ) assert excinfo.value.message == ( u'Syntax Error GraphQL (3:5) Unexpected character "?".\n' - u'\n' - u'2: \n' - u'3: ?\n' - u' ^\n' - u'4: \n' + u"\n" + u"2: \n" + u"3: ?\n" + u" ^\n" + u"4: \n" ) def test_lexes_strings(): # type: () -> None - assert lex_one(u'"simple"') == Token(TokenKind.STRING, 0, 8, 'simple') - assert lex_one(u'" white space "') == Token(TokenKind.STRING, 0, 15, ' white space ') + assert lex_one(u'"simple"') == Token(TokenKind.STRING, 0, 8, "simple") + assert lex_one(u'" white space "') == Token( + TokenKind.STRING, 0, 15, " white space " + ) assert lex_one(u'"quote \\""') == Token(TokenKind.STRING, 0, 10, 'quote "') - assert lex_one(u'"escaped \\n\\r\\b\\t\\f"') == Token(TokenKind.STRING, 0, 20, 'escaped \n\r\b\t\f') - assert lex_one(u'"slashes \\\\ \\/"') == Token(TokenKind.STRING, 0, 15, 'slashes \\ /') - assert lex_one(u'"unicode \\u1234\\u5678\\u90AB\\uCDEF"') == Token(TokenKind.STRING, 0, 34, - u'unicode \u1234\u5678\u90AB\uCDEF') + assert lex_one(u'"escaped \\n\\r\\b\\t\\f"') == Token( + TokenKind.STRING, 0, 20, "escaped \n\r\b\t\f" + ) + assert lex_one(u'"slashes \\\\ \\/"') == Token( + TokenKind.STRING, 0, 15, "slashes \\ /" + ) + assert lex_one(u'"unicode \\u1234\\u5678\\u90AB\\uCDEF"') == Token( + TokenKind.STRING, 0, 34, u"unicode \u1234\u5678\u90AB\uCDEF" + ) def test_lex_reports_useful_string_errors(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"') - assert u'Syntax Error GraphQL (1:2) Unterminated string' in excinfo.value.message + assert u"Syntax Error GraphQL (1:2) Unterminated string" in excinfo.value.message with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"no end quote') - assert u'Syntax Error GraphQL (1:14) Unterminated string' in excinfo.value.message + assert u"Syntax Error GraphQL (1:14) Unterminated string" in excinfo.value.message with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"contains unescaped \u0007 control char"') - assert u'Syntax Error GraphQL (1:21) Invalid character within String: "\\u0007".' in excinfo.value.message + assert ( + u'Syntax Error GraphQL (1:21) Invalid character within String: "\\u0007".' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"null-byte is not \u0000 end of file"') - assert u'Syntax Error GraphQL (1:19) Invalid character within String: "\\u0000".' in excinfo.value.message + assert ( + u'Syntax Error GraphQL (1:19) Invalid character within String: "\\u0000".' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"multi\nline"') - assert u'Syntax Error GraphQL (1:7) Unterminated string' in excinfo.value.message + assert u"Syntax Error GraphQL (1:7) Unterminated string" in excinfo.value.message with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"multi\rline"') - assert u'Syntax Error GraphQL (1:7) Unterminated string' in excinfo.value.message + assert u"Syntax Error GraphQL (1:7) Unterminated string" in excinfo.value.message with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\z esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\z.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\z." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\x esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\x.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\x." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\u1 esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u1 es.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u1 es." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\u0XX1 esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u0XX1.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u0XX1." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\uXXXX esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXX' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXX" + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\uFXXX esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uFXXX.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uFXXX." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: lex_one(u'"bad \\uXXXF esc"') - assert u'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXF.' in excinfo.value.message + assert ( + u"Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXF." + in excinfo.value.message + ) def test_lexes_numbers(): # type: () -> None - assert lex_one(u'4') == Token(TokenKind.INT, 0, 1, '4') - assert lex_one(u'4.123') == Token(TokenKind.FLOAT, 0, 5, '4.123') - assert lex_one(u'-4') == Token(TokenKind.INT, 0, 2, '-4') - assert lex_one(u'9') == Token(TokenKind.INT, 0, 1, '9') - assert lex_one(u'0') == Token(TokenKind.INT, 0, 1, '0') - assert lex_one(u'-4.123') == Token(TokenKind.FLOAT, 0, 6, '-4.123') - assert lex_one(u'0.123') == Token(TokenKind.FLOAT, 0, 5, '0.123') - assert lex_one(u'123e4') == Token(TokenKind.FLOAT, 0, 5, '123e4') - assert lex_one(u'123E4') == Token(TokenKind.FLOAT, 0, 5, '123E4') - assert lex_one(u'123e-4') == Token(TokenKind.FLOAT, 0, 6, '123e-4') - assert lex_one(u'123e+4') == Token(TokenKind.FLOAT, 0, 6, '123e+4') - assert lex_one(u'-1.123e4') == Token(TokenKind.FLOAT, 0, 8, '-1.123e4') - assert lex_one(u'-1.123E4') == Token(TokenKind.FLOAT, 0, 8, '-1.123E4') - assert lex_one(u'-1.123e-4') == Token(TokenKind.FLOAT, 0, 9, '-1.123e-4') - assert lex_one(u'-1.123e+4') == Token(TokenKind.FLOAT, 0, 9, '-1.123e+4') - assert lex_one(u'-1.123e4567') == Token(TokenKind.FLOAT, 0, 11, '-1.123e4567') + assert lex_one(u"4") == Token(TokenKind.INT, 0, 1, "4") + assert lex_one(u"4.123") == Token(TokenKind.FLOAT, 0, 5, "4.123") + assert lex_one(u"-4") == Token(TokenKind.INT, 0, 2, "-4") + assert lex_one(u"9") == Token(TokenKind.INT, 0, 1, "9") + assert lex_one(u"0") == Token(TokenKind.INT, 0, 1, "0") + assert lex_one(u"-4.123") == Token(TokenKind.FLOAT, 0, 6, "-4.123") + assert lex_one(u"0.123") == Token(TokenKind.FLOAT, 0, 5, "0.123") + assert lex_one(u"123e4") == Token(TokenKind.FLOAT, 0, 5, "123e4") + assert lex_one(u"123E4") == Token(TokenKind.FLOAT, 0, 5, "123E4") + assert lex_one(u"123e-4") == Token(TokenKind.FLOAT, 0, 6, "123e-4") + assert lex_one(u"123e+4") == Token(TokenKind.FLOAT, 0, 6, "123e+4") + assert lex_one(u"-1.123e4") == Token(TokenKind.FLOAT, 0, 8, "-1.123e4") + assert lex_one(u"-1.123E4") == Token(TokenKind.FLOAT, 0, 8, "-1.123E4") + assert lex_one(u"-1.123e-4") == Token(TokenKind.FLOAT, 0, 9, "-1.123e-4") + assert lex_one(u"-1.123e+4") == Token(TokenKind.FLOAT, 0, 9, "-1.123e+4") + assert lex_one(u"-1.123e4567") == Token(TokenKind.FLOAT, 0, 11, "-1.123e4567") def test_lex_reports_useful_number_errors(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'00') - assert u'Syntax Error GraphQL (1:2) Invalid number, unexpected digit after 0: "0".' in excinfo.value.message + lex_one(u"00") + assert ( + u'Syntax Error GraphQL (1:2) Invalid number, unexpected digit after 0: "0".' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'+1') - assert u'Syntax Error GraphQL (1:1) Unexpected character "+"' in excinfo.value.message + lex_one(u"+1") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character "+"' in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'1.') - assert u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: .' in excinfo.value.message + lex_one(u"1.") + assert ( + u"Syntax Error GraphQL (1:3) Invalid number, expected digit but got: ." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'.123') - assert u'Syntax Error GraphQL (1:1) Unexpected character ".".' in excinfo.value.message + lex_one(u".123") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character ".".' in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'1.A') - assert u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "A".' in excinfo.value.message + lex_one(u"1.A") + assert ( + u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "A".' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'-A') - assert u'Syntax Error GraphQL (1:2) Invalid number, expected digit but got: "A".' in excinfo.value.message + lex_one(u"-A") + assert ( + u'Syntax Error GraphQL (1:2) Invalid number, expected digit but got: "A".' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'1.0e') - assert u'Syntax Error GraphQL (1:5) Invalid number, expected digit but got: .' in excinfo.value.message + lex_one(u"1.0e") + assert ( + u"Syntax Error GraphQL (1:5) Invalid number, expected digit but got: ." + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'1.0eA') - assert u'Syntax Error GraphQL (1:5) Invalid number, expected digit but got: "A".' in excinfo.value.message + lex_one(u"1.0eA") + assert ( + u'Syntax Error GraphQL (1:5) Invalid number, expected digit but got: "A".' + in excinfo.value.message + ) def test_lexes_punctuation(): # type: () -> None - assert lex_one(u'!') == Token(TokenKind.BANG, 0, 1) - assert lex_one(u'$') == Token(TokenKind.DOLLAR, 0, 1) - assert lex_one(u'(') == Token(TokenKind.PAREN_L, 0, 1) - assert lex_one(u')') == Token(TokenKind.PAREN_R, 0, 1) - assert lex_one(u'...') == Token(TokenKind.SPREAD, 0, 3) - assert lex_one(u':') == Token(TokenKind.COLON, 0, 1) - assert lex_one(u'=') == Token(TokenKind.EQUALS, 0, 1) - assert lex_one(u'@') == Token(TokenKind.AT, 0, 1) - assert lex_one(u'[') == Token(TokenKind.BRACKET_L, 0, 1) - assert lex_one(u']') == Token(TokenKind.BRACKET_R, 0, 1) - assert lex_one(u'{') == Token(TokenKind.BRACE_L, 0, 1) - assert lex_one(u'|') == Token(TokenKind.PIPE, 0, 1) - assert lex_one(u'}') == Token(TokenKind.BRACE_R, 0, 1) + assert lex_one(u"!") == Token(TokenKind.BANG, 0, 1) + assert lex_one(u"$") == Token(TokenKind.DOLLAR, 0, 1) + assert lex_one(u"(") == Token(TokenKind.PAREN_L, 0, 1) + assert lex_one(u")") == Token(TokenKind.PAREN_R, 0, 1) + assert lex_one(u"...") == Token(TokenKind.SPREAD, 0, 3) + assert lex_one(u":") == Token(TokenKind.COLON, 0, 1) + assert lex_one(u"=") == Token(TokenKind.EQUALS, 0, 1) + assert lex_one(u"@") == Token(TokenKind.AT, 0, 1) + assert lex_one(u"[") == Token(TokenKind.BRACKET_L, 0, 1) + assert lex_one(u"]") == Token(TokenKind.BRACKET_R, 0, 1) + assert lex_one(u"{") == Token(TokenKind.BRACE_L, 0, 1) + assert lex_one(u"|") == Token(TokenKind.PIPE, 0, 1) + assert lex_one(u"}") == Token(TokenKind.BRACE_R, 0, 1) def test_lex_reports_useful_unknown_character_error(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'..') - assert u'Syntax Error GraphQL (1:1) Unexpected character "."' in excinfo.value.message + lex_one(u"..") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character "."' in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'?') - assert u'Syntax Error GraphQL (1:1) Unexpected character "?"' in excinfo.value.message + lex_one(u"?") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character "?"' in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'\u203B') - assert u'Syntax Error GraphQL (1:1) Unexpected character "\\u203B"' in excinfo.value.message + lex_one(u"\u203B") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character "\\u203B"' + in excinfo.value.message + ) with raises(GraphQLSyntaxError) as excinfo: - lex_one(u'\u200b') - assert u'Syntax Error GraphQL (1:1) Unexpected character "\\u200B"' in excinfo.value.message + lex_one(u"\u200b") + assert ( + u'Syntax Error GraphQL (1:1) Unexpected character "\\u200B"' + in excinfo.value.message + ) def test_lex_reports_useful_information_for_dashes_in_names(): # type: () -> None - q = u'a-b' + q = u"a-b" lexer = Lexer(Source(q)) first_token = lexer.next_token() - assert first_token == Token(TokenKind.NAME, 0, 1, 'a') + assert first_token == Token(TokenKind.NAME, 0, 1, "a") with raises(GraphQLSyntaxError) as excinfo: lexer.next_token() - assert u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "b".' in excinfo.value.message + assert ( + u'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "b".' + in excinfo.value.message + ) diff --git a/graphql/language/tests/test_location.py b/graphql/language/tests/test_location.py index 48884893..3562d53a 100644 --- a/graphql/language/tests/test_location.py +++ b/graphql/language/tests/test_location.py @@ -4,4 +4,4 @@ def test_repr_source_location(): # type: () -> None loc = SourceLocation(10, 25) - assert repr(loc) == 'SourceLocation(line=10, column=25)' + assert repr(loc) == "SourceLocation(line=10, column=25)" diff --git a/graphql/language/tests/test_parser.py b/graphql/language/tests/test_parser.py index 3bf8d611..6c9d5f47 100644 --- a/graphql/language/tests/test_parser.py +++ b/graphql/language/tests/test_parser.py @@ -11,8 +11,8 @@ def test_repr_loc(): # type: () -> None - loc = Loc(start=10, end=25, source='foo') - assert repr(loc) == '' + loc = Loc(start=10, end=25, source="foo") + assert repr(loc) == "" def test_empty_parse(): @@ -20,8 +20,7 @@ def test_empty_parse(): with raises(GraphQLSyntaxError) as excinfo: parse("") assert ( - u'Syntax Error GraphQL (1:1) Unexpected EOF\n' - u'\n' + u"Syntax Error GraphQL (1:1) Unexpected EOF\n" u"\n" ) == excinfo.value.message @@ -30,62 +29,66 @@ def test_parse_provides_useful_errors(): with raises(GraphQLSyntaxError) as excinfo: parse("""{""") assert ( - u'Syntax Error GraphQL (1:2) Expected Name, found EOF\n' - u'\n' - u'1: {\n' - u' ^\n' - u'' + u"Syntax Error GraphQL (1:2) Expected Name, found EOF\n" + u"\n" + u"1: {\n" + u" ^\n" + u"" ) == excinfo.value.message assert excinfo.value.positions == [1] assert excinfo.value.locations == [SourceLocation(line=1, column=2)] with raises(GraphQLSyntaxError) as excinfo: - parse("""{ ...MissingOn } + parse( + """{ ...MissingOn } fragment MissingOn Type -""") +""" + ) assert 'Syntax Error GraphQL (2:20) Expected "on", found Name "Type"' in str( - excinfo.value) + excinfo.value + ) with raises(GraphQLSyntaxError) as excinfo: - parse('{ field: {} }') - assert 'Syntax Error GraphQL (1:10) Expected Name, found {' in str( - excinfo.value) + parse("{ field: {} }") + assert "Syntax Error GraphQL (1:10) Expected Name, found {" in str(excinfo.value) with raises(GraphQLSyntaxError) as excinfo: - parse('notanoperation Foo { field }') + parse("notanoperation Foo { field }") assert 'Syntax Error GraphQL (1:1) Unexpected Name "notanoperation"' in str( - excinfo.value) + excinfo.value + ) with raises(GraphQLSyntaxError) as excinfo: - parse('...') - assert 'Syntax Error GraphQL (1:1) Unexpected ...' in str(excinfo.value) + parse("...") + assert "Syntax Error GraphQL (1:1) Unexpected ..." in str(excinfo.value) def test_parse_provides_useful_error_when_using_source(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - parse(Source('query', 'MyQuery.graphql')) - assert 'Syntax Error MyQuery.graphql (1:6) Expected {, found EOF' in str( - excinfo.value) + parse(Source("query", "MyQuery.graphql")) + assert "Syntax Error MyQuery.graphql (1:6) Expected {, found EOF" in str( + excinfo.value + ) def test_parses_variable_inline_values(): # type: () -> None - parse('{ field(complex: { a: { b: [ $var ] } }) }') + parse("{ field(complex: { a: { b: [ $var ] } }) }") def test_parses_constant_default_values(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - parse('query Foo($x: Complex = { a: { b: [ $var ] } }) { field }') - assert 'Syntax Error GraphQL (1:37) Unexpected $' in str(excinfo.value) + parse("query Foo($x: Complex = { a: { b: [ $var ] } }) { field }") + assert "Syntax Error GraphQL (1:37) Unexpected $" in str(excinfo.value) def test_does_not_accept_fragments_named_on(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - parse('fragment on on on { on }') + parse("fragment on on on { on }") assert 'Syntax Error GraphQL (1:10) Unexpected Name "on"' in excinfo.value.message @@ -93,40 +96,54 @@ def test_does_not_accept_fragments_named_on(): def test_does_not_accept_fragments_spread_of_on(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - parse('{ ...on }') + parse("{ ...on }") - assert 'Syntax Error GraphQL (1:9) Expected Name, found }' in excinfo.value.message + assert "Syntax Error GraphQL (1:9) Expected Name, found }" in excinfo.value.message def test_does_not_allow_null_value(): # type: () -> None with raises(GraphQLSyntaxError) as excinfo: - parse('{ fieldWithNullableStringInput(input: null) }') + parse("{ fieldWithNullableStringInput(input: null) }") assert 'Syntax Error GraphQL (1:39) Unexpected Name "null"' in excinfo.value.message def test_parses_multi_byte_characters(): # type: () -> None - result = parse(u''' + result = parse( + u""" # This comment has a \u0A0A multi-byte character. { field(arg: "Has a \u0A0A multi-byte character.") } - ''', no_location=True, no_source=True) + """, + no_location=True, + no_source=True, + ) assert result == ast.Document( definitions=[ ast.OperationDefinition( - operation='query', name=None, variable_definitions=None, directives=[], + operation="query", + name=None, + variable_definitions=None, + directives=[], selection_set=ast.SelectionSet( selections=[ ast.Field( - alias=None, name=ast.Name(value=u'field'), + alias=None, + name=ast.Name(value=u"field"), arguments=[ ast.Argument( - name=ast.Name(value=u'arg'), - value=ast.StringValue(value=u'Has a \u0a0a multi-byte character.'))], - directives=[], selection_set=None) + name=ast.Name(value=u"arg"), + value=ast.StringValue( + value=u"Has a \u0a0a multi-byte character." + ), + ) + ], + directives=[], + selection_set=None, + ) ] - ) + ), ) ] ) @@ -134,16 +151,16 @@ def test_parses_multi_byte_characters(): def tesst_allows_non_keywords_anywhere_a_name_is_allowed(): non_keywords = [ - 'on', - 'fragment', - 'query', - 'mutation', - 'subscription', - 'true', - 'false' + "on", + "fragment", + "query", + "mutation", + "subscription", + "true", + "false", ] - query_template = ''' + query_template = """ query {keyword} { ... {fragment_name} ... on {keyword} { field } @@ -151,12 +168,12 @@ def tesst_allows_non_keywords_anywhere_a_name_is_allowed(): fragment {fragment_name} on Type { {keyword}({keyword}: ${keyword}) @{keyword}({keyword}: {keyword}) } - ''' + """ for keyword in non_keywords: fragment_name = keyword - if keyword == 'on': - fragment_name = 'a' + if keyword == "on": + fragment_name = "a" parse(query_template.format(fragment_name=fragment_name, keyword=keyword)) @@ -168,93 +185,123 @@ def test_parses_kitchen_sink(): def test_parses_anonymous_mutation_operations(): # type: () -> None - parse(''' + parse( + """ mutation { mutationField } - ''') + """ + ) def test_parses_anonymous_subscription_operations(): # type: () -> None - parse(''' + parse( + """ subscription { mutationField } - ''') + """ + ) def test_parses_named_mutation_operations(): # type: () -> None - parse(''' + parse( + """ mutation Foo { mutationField } - ''') + """ + ) def test_parses_named_subscription_operations(): # type: () -> None - parse(''' + parse( + """ subscription Foo { subscriptionField } - ''') + """ + ) def test_parse_creates_ast(): # type: () -> None - source = Source("""{ + source = Source( + """{ node(id: 4) { id, name } } -""") +""" + ) result = parse(source) - assert result == \ - ast.Document( - loc=Loc(start=0, end=41, source=source), - definitions=[ast.OperationDefinition( + assert result == ast.Document( + loc=Loc(start=0, end=41, source=source), + definitions=[ + ast.OperationDefinition( loc=Loc(start=0, end=40, source=source), - operation='query', + operation="query", name=None, variable_definitions=None, directives=[], selection_set=ast.SelectionSet( loc=Loc(start=0, end=40, source=source), - selections=[ast.Field( - loc=Loc(start=4, end=38, source=source), - alias=None, - name=ast.Name( - loc=Loc(start=4, end=8, source=source), - value='node'), - arguments=[ast.Argument( - name=ast.Name(loc=Loc(start=9, end=11, source=source), - value='id'), - value=ast.IntValue( - loc=Loc(start=13, end=14, source=source), - value='4'), - loc=Loc(start=9, end=14, source=source))], - directives=[], - selection_set=ast.SelectionSet( - loc=Loc(start=16, end=38, source=source), - selections=[ast.Field( - loc=Loc(start=22, end=24, source=source), - alias=None, - name=ast.Name( - loc=Loc(start=22, end=24, source=source), - value='id'), - arguments=[], - directives=[], - selection_set=None), - ast.Field( - loc=Loc(start=30, end=34, source=source), - alias=None, - name=ast.Name( - loc=Loc(start=30, end=34, source=source), - value='name'), - arguments=[], - directives=[], - selection_set=None)]))]))]) + selections=[ + ast.Field( + loc=Loc(start=4, end=38, source=source), + alias=None, + name=ast.Name( + loc=Loc(start=4, end=8, source=source), value="node" + ), + arguments=[ + ast.Argument( + name=ast.Name( + loc=Loc(start=9, end=11, source=source), + value="id", + ), + value=ast.IntValue( + loc=Loc(start=13, end=14, source=source), + value="4", + ), + loc=Loc(start=9, end=14, source=source), + ) + ], + directives=[], + selection_set=ast.SelectionSet( + loc=Loc(start=16, end=38, source=source), + selections=[ + ast.Field( + loc=Loc(start=22, end=24, source=source), + alias=None, + name=ast.Name( + loc=Loc(start=22, end=24, source=source), + value="id", + ), + arguments=[], + directives=[], + selection_set=None, + ), + ast.Field( + loc=Loc(start=30, end=34, source=source), + alias=None, + name=ast.Name( + loc=Loc(start=30, end=34, source=source), + value="name", + ), + arguments=[], + directives=[], + selection_set=None, + ), + ], + ), + ) + ], + ), + ) + ], + ) diff --git a/graphql/language/tests/test_printer.py b/graphql/language/tests/test_printer.py index f1188898..470991df 100644 --- a/graphql/language/tests/test_printer.py +++ b/graphql/language/tests/test_printer.py @@ -19,67 +19,79 @@ def test_does_not_alter_ast(): def test_prints_minimal_ast(): # type: () -> None - ast = Field(name=Name(loc=None, value='foo')) - assert print_ast(ast) == 'foo' + ast = Field(name=Name(loc=None, value="foo")) + assert print_ast(ast) == "foo" def test_produces_helpful_error_messages(): # type: () -> None - bad_ast = {'random': 'Data'} + bad_ast = {"random": "Data"} with raises(Exception) as excinfo: print_ast(bad_ast) - assert 'Invalid AST Node' in str(excinfo.value) + assert "Invalid AST Node" in str(excinfo.value) def test_correctly_prints_query_operation_without_name(): # type: () -> None - query_ast_shorthanded = parse('query { id, name }') - assert print_ast(query_ast_shorthanded) == '''{ + query_ast_shorthanded = parse("query { id, name }") + assert ( + print_ast(query_ast_shorthanded) + == """{ id name } -''' +""" + ) def test_correctly_prints_mutation_operation_without_name(): # type: () -> None - mutation_ast = parse('mutation { id, name }') - assert print_ast(mutation_ast) == '''mutation { + mutation_ast = parse("mutation { id, name }") + assert ( + print_ast(mutation_ast) + == """mutation { id name } -''' +""" + ) def test_correctly_prints_query_with_artifacts(): # type: () -> None - query_ast_shorthanded = parse( - 'query ($foo: TestType) @testDirective { id, name }' - ) - assert print_ast(query_ast_shorthanded) == '''query ($foo: TestType) @testDirective { + query_ast_shorthanded = parse("query ($foo: TestType) @testDirective { id, name }") + assert ( + print_ast(query_ast_shorthanded) + == """query ($foo: TestType) @testDirective { id name } -''' +""" + ) def test_correctly_prints_mutation_with_artifacts(): # type: () -> None query_ast_shorthanded = parse( - 'mutation ($foo: TestType) @testDirective { id, name }' + "mutation ($foo: TestType) @testDirective { id, name }" ) - assert print_ast(query_ast_shorthanded) == '''mutation ($foo: TestType) @testDirective { + assert ( + print_ast(query_ast_shorthanded) + == """mutation ($foo: TestType) @testDirective { id name } -''' +""" + ) def test_prints_kitchen_sink(): # type: () -> None ast = parse(KITCHEN_SINK) printed = print_ast(ast) - assert printed == '''query queryName($foo: ComplexType, $site: Site = MOBILE) { + assert ( + printed + == """query queryName($foo: ComplexType, $site: Site = MOBILE) { whoever123is: node(id: [123, 456]) { id ... on User @defer { @@ -129,4 +141,5 @@ def test_prints_kitchen_sink(): unnamed(truthy: true, falsey: false) query } -''' +""" + ) diff --git a/graphql/language/tests/test_schema_parser.py b/graphql/language/tests/test_schema_parser.py index cfb7b33d..6ec58d4d 100644 --- a/graphql/language/tests/test_schema_parser.py +++ b/graphql/language/tests/test_schema_parser.py @@ -15,10 +15,10 @@ def create_loc_fn(body): def test_parses_simple_type(): # type: () -> None - body = ''' + body = """ type Hello { world: String -}''' +}""" doc = parse(body) loc = create_loc_fn(body) @@ -26,44 +26,35 @@ def test_parses_simple_type(): expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(23, 29) - ), - loc=loc(23, 29) + name=ast.Name(value="String", loc=loc(23, 29)), + loc=loc(23, 29), ), directives=[], - loc=loc(16, 29) + loc=loc(16, 29), ) ], - loc=loc(1, 31) + loc=loc(1, 31), ) ], - loc=loc(1, 31) + loc=loc(1, 31), ) assert doc == expected def test_parses_simple_extension(): # type: () -> None - body = ''' + body = """ extend type Hello { world: String -}''' +}""" doc = parse(body) loc = create_loc_fn(body) @@ -71,36 +62,27 @@ def test_parses_simple_extension(): definitions=[ ast.TypeExtensionDefinition( definition=ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(13, 18) - ), + name=ast.Name(value="Hello", loc=loc(13, 18)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(23, 28) - ), + name=ast.Name(value="world", loc=loc(23, 28)), arguments=[], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(30, 36) - ), - loc=loc(30, 36) + name=ast.Name(value="String", loc=loc(30, 36)), + loc=loc(30, 36), ), directives=[], - loc=loc(23, 36) + loc=loc(23, 36), ) ], - loc=loc(8, 38) + loc=loc(8, 38), ), - loc=loc(1, 38) + loc=loc(1, 38), ) ], - loc=loc(1, 38) + loc=loc(1, 38), ) assert doc == expected @@ -108,78 +90,62 @@ def test_parses_simple_extension(): def test_simple_non_null_type(): # type: () -> None - body = ''' + body = """ type Hello { world: String! -}''' +}""" doc = parse(body) loc = create_loc_fn(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[], type=ast.NonNullType( type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(23, 29) - ), - loc=loc(23, 29) + name=ast.Name(value="String", loc=loc(23, 29)), + loc=loc(23, 29), ), - loc=loc(23, 30) + loc=loc(23, 30), ), directives=[], - loc=loc(16, 30) + loc=loc(16, 30), ) ], - loc=loc(1, 32) + loc=loc(1, 32), ) ], - loc=loc(1, 32) + loc=loc(1, 32), ) assert doc == expected def test_parses_simple_type_inheriting_interface(): # type: () -> None - body = 'type Hello implements World { }' + body = "type Hello implements World { }" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(5, 10) - ), + name=ast.Name(value="Hello", loc=loc(5, 10)), interfaces=[ ast.NamedType( - name=ast.Name( - value='World', - loc=loc(22, 27) - ), - loc=loc(22, 27) + name=ast.Name(value="World", loc=loc(22, 27)), loc=loc(22, 27) ) ], directives=[], fields=[], - loc=loc(0, 31) + loc=loc(0, 31), ) ], - loc=loc(0, 31) + loc=loc(0, 31), ) assert doc == expected @@ -187,69 +153,52 @@ def test_parses_simple_type_inheriting_interface(): def test_parses_simple_type_inheriting_multiple_interfaces(): # type: () -> None - body = 'type Hello implements Wo, rld { }' + body = "type Hello implements Wo, rld { }" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(5, 10) - ), + name=ast.Name(value="Hello", loc=loc(5, 10)), interfaces=[ ast.NamedType( - name=ast.Name( - value='Wo', - loc=loc(22, 24) - ), - loc=loc(22, 24) + name=ast.Name(value="Wo", loc=loc(22, 24)), loc=loc(22, 24) ), ast.NamedType( - name=ast.Name( - value='rld', - loc=loc(26, 29) - ), - loc=loc(26, 29) - ) + name=ast.Name(value="rld", loc=loc(26, 29)), loc=loc(26, 29) + ), ], directives=[], fields=[], - loc=loc(0, 33) + loc=loc(0, 33), ) ], - loc=loc(0, 33) + loc=loc(0, 33), ) assert doc == expected def test_parses_single_value_enum(): # type: () -> None - body = 'enum Hello { WORLD }' + body = "enum Hello { WORLD }" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.EnumTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(5, 10) - ), + name=ast.Name(value="Hello", loc=loc(5, 10)), directives=[], values=[ ast.EnumValueDefinition( - name=ast.Name( - value='WORLD', - loc=loc(13, 18) - ), + name=ast.Name(value="WORLD", loc=loc(13, 18)), directives=[], - loc=loc(13, 18) + loc=loc(13, 18), ) ], - loc=loc(0, 20) + loc=loc(0, 20), ) ], - loc=loc(0, 20) + loc=loc(0, 20), ) assert doc == expected @@ -257,39 +206,30 @@ def test_parses_single_value_enum(): def test_parses_double_value_enum(): # type: () -> None - body = 'enum Hello { WO, RLD }' + body = "enum Hello { WO, RLD }" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.EnumTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(5, 10) - ), + name=ast.Name(value="Hello", loc=loc(5, 10)), directives=[], values=[ ast.EnumValueDefinition( - name=ast.Name( - value='WO', - loc=loc(13, 15) - ), + name=ast.Name(value="WO", loc=loc(13, 15)), directives=[], - loc=loc(13, 15) + loc=loc(13, 15), ), ast.EnumValueDefinition( - name=ast.Name( - value='RLD', - loc=loc(17, 20) - ), + name=ast.Name(value="RLD", loc=loc(17, 20)), directives=[], - loc=loc(17, 20) - ) + loc=loc(17, 20), + ), ], - loc=loc(0, 22) + loc=loc(0, 22), ) ], - loc=loc(0, 22) + loc=loc(0, 22), ) assert doc == expected @@ -297,43 +237,34 @@ def test_parses_double_value_enum(): def test_parses_simple_interface(): # type: () -> None - body = ''' + body = """ interface Hello { world: String } -''' +""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.InterfaceTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(11, 16) - ), + name=ast.Name(value="Hello", loc=loc(11, 16)), directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(21, 26) - ), + name=ast.Name(value="world", loc=loc(21, 26)), arguments=[], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(28, 34) - ), - loc=loc(28, 34) + name=ast.Name(value="String", loc=loc(28, 34)), + loc=loc(28, 34), ), directives=[], - loc=loc(21, 34) + loc=loc(21, 34), ) ], - loc=loc(1, 36) + loc=loc(1, 36), ) ], - loc=loc(1, 37) + loc=loc(1, 37), ) assert doc == expected @@ -341,60 +272,45 @@ def test_parses_simple_interface(): def test_parses_simple_field_with_arg(): # type: () -> None - body = ''' + body = """ type Hello { world(flag: Boolean): String -}''' +}""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( - name=ast.Name( - value='flag', - loc=loc(22, 26) - ), + name=ast.Name(value="flag", loc=loc(22, 26)), type=ast.NamedType( - name=ast.Name( - value='Boolean', - loc=loc(28, 35) - ), - loc=loc(28, 35) + name=ast.Name(value="Boolean", loc=loc(28, 35)), + loc=loc(28, 35), ), default_value=None, directives=[], - loc=loc(22, 35) + loc=loc(22, 35), ) ], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(38, 44) - ), - loc=loc(38, 44) + name=ast.Name(value="String", loc=loc(38, 44)), + loc=loc(38, 44), ), directives=[], - loc=loc(16, 44) + loc=loc(16, 44), ) ], - loc=loc(1, 46) + loc=loc(1, 46), ) ], - loc=loc(1, 46) + loc=loc(1, 46), ) assert doc == expected @@ -402,63 +318,47 @@ def test_parses_simple_field_with_arg(): def test_parses_simple_field_with_arg_with_default_value(): # type: () -> None - body = ''' + body = """ type Hello { world(flag: Boolean = true): String -}''' +}""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( - name=ast.Name( - value='flag', - loc=loc(22, 26) - ), + name=ast.Name(value="flag", loc=loc(22, 26)), type=ast.NamedType( - name=ast.Name( - value='Boolean', - loc=loc(28, 35) - ), - loc=loc(28, 35) + name=ast.Name(value="Boolean", loc=loc(28, 35)), + loc=loc(28, 35), ), default_value=ast.BooleanValue( - value=True, - loc=loc(38, 42) + value=True, loc=loc(38, 42) ), directives=[], - loc=loc(22, 42) + loc=loc(22, 42), ) ], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(45, 51) - ), - loc=loc(45, 51) + name=ast.Name(value="String", loc=loc(45, 51)), + loc=loc(45, 51), ), directives=[], - loc=loc(16, 51) + loc=loc(16, 51), ) ], - loc=loc(1, 53) + loc=loc(1, 53), ) ], - loc=loc(1, 53) + loc=loc(1, 53), ) assert doc == expected @@ -466,281 +366,215 @@ def test_parses_simple_field_with_arg_with_default_value(): def test_parses_simple_field_with_list_arg(): # type: () -> None - body = ''' + body = """ type Hello { world(things: [String]): String -}''' +}""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( - name=ast.Name( - value='things', - loc=loc(22, 28) - ), + name=ast.Name(value="things", loc=loc(22, 28)), type=ast.ListType( type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(31, 37) - ), - loc=loc(31, 37) + name=ast.Name(value="String", loc=loc(31, 37)), + loc=loc(31, 37), ), - loc=loc(30, 38) + loc=loc(30, 38), ), default_value=None, directives=[], - loc=loc(22, 38) + loc=loc(22, 38), ) ], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(41, 47) - ), - loc=loc(41, 47) + name=ast.Name(value="String", loc=loc(41, 47)), + loc=loc(41, 47), ), directives=[], - loc=loc(16, 47) + loc=loc(16, 47), ) ], - loc=loc(1, 49) + loc=loc(1, 49), ) ], - loc=loc(1, 49) + loc=loc(1, 49), ) assert doc == expected def test_parses_simple_field_with_two_args(): # type: () -> None - body = ''' + body = """ type Hello { world(argOne: Boolean, argTwo: Int): String -}''' +}""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), interfaces=[], directives=[], fields=[ ast.FieldDefinition( - name=ast.Name( - value='world', - loc=loc(16, 21) - ), + name=ast.Name(value="world", loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( - name=ast.Name( - value='argOne', - loc=loc(22, 28) - ), + name=ast.Name(value="argOne", loc=loc(22, 28)), type=ast.NamedType( - name=ast.Name( - value='Boolean', - loc=loc(30, 37) - ), - loc=loc(30, 37) + name=ast.Name(value="Boolean", loc=loc(30, 37)), + loc=loc(30, 37), ), default_value=None, directives=[], - loc=loc(22, 37) + loc=loc(22, 37), ), ast.InputValueDefinition( - name=ast.Name( - value='argTwo', - loc=loc(39, 45) - ), + name=ast.Name(value="argTwo", loc=loc(39, 45)), type=ast.NamedType( - name=ast.Name( - value='Int', - loc=loc(47, 50) - ), - loc=loc(47, 50) + name=ast.Name(value="Int", loc=loc(47, 50)), + loc=loc(47, 50), ), default_value=None, directives=[], - loc=loc(39, 50) - ) + loc=loc(39, 50), + ), ], type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(53, 59) - ), - loc=loc(53, 59) + name=ast.Name(value="String", loc=loc(53, 59)), + loc=loc(53, 59), ), directives=[], - loc=loc(16, 59) + loc=loc(16, 59), ) ], - loc=loc(1, 61) + loc=loc(1, 61), ) ], - loc=loc(1, 61) + loc=loc(1, 61), ) assert doc == expected def test_parses_simple_union(): # type: () -> None - body = 'union Hello = World' + body = "union Hello = World" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.UnionTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), directives=[], types=[ ast.NamedType( - name=ast.Name( - value='World', - loc=loc(14, 19) - ), - loc=loc(14, 19) + name=ast.Name(value="World", loc=loc(14, 19)), loc=loc(14, 19) ) ], - loc=loc(0, 19) + loc=loc(0, 19), ) ], - loc=loc(0, 19) + loc=loc(0, 19), ) assert doc == expected def test_parses_union_with_two_types(): # type: () -> None - body = 'union Hello = Wo | Rld' + body = "union Hello = Wo | Rld" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.UnionTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(6, 11) - ), + name=ast.Name(value="Hello", loc=loc(6, 11)), directives=[], types=[ ast.NamedType( - name=ast.Name( - value='Wo', - loc=loc(14, 16) - ), - loc=loc(14, 16) + name=ast.Name(value="Wo", loc=loc(14, 16)), loc=loc(14, 16) ), ast.NamedType( - name=ast.Name( - value='Rld', - loc=loc(19, 22) - ), - loc=loc(19, 22) - ) + name=ast.Name(value="Rld", loc=loc(19, 22)), loc=loc(19, 22) + ), ], - loc=loc(0, 22) + loc=loc(0, 22), ) ], - loc=loc(0, 22) + loc=loc(0, 22), ) assert doc == expected def test_parses_scalar(): # type: () -> None - body = 'scalar Hello' + body = "scalar Hello" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ScalarTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(7, 12) - ), + name=ast.Name(value="Hello", loc=loc(7, 12)), directives=[], - loc=loc(0, 12) + loc=loc(0, 12), ) ], - loc=loc(0, 12) + loc=loc(0, 12), ) assert doc == expected def test_parses_simple_input_object(): # type: () -> None - body = ''' + body = """ input Hello { world: String -}''' +}""" loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.InputObjectTypeDefinition( - name=ast.Name( - value='Hello', - loc=loc(7, 12) - ), + name=ast.Name(value="Hello", loc=loc(7, 12)), directives=[], fields=[ ast.InputValueDefinition( - name=ast.Name( - value='world', - loc=loc(17, 22) - ), + name=ast.Name(value="world", loc=loc(17, 22)), type=ast.NamedType( - name=ast.Name( - value='String', - loc=loc(24, 30) - ), - loc=loc(24, 30) + name=ast.Name(value="String", loc=loc(24, 30)), + loc=loc(24, 30), ), default_value=None, directives=[], - loc=loc(17, 30) + loc=loc(17, 30), ) ], - loc=loc(1, 32) + loc=loc(1, 32), ) ], - loc=loc(1, 32) + loc=loc(1, 32), ) assert doc == expected def test_parsing_simple_input_object_with_args_should_fail(): # type: () -> None - body = ''' + body = """ input Hello { world(foo: Int): String } -''' +""" with raises(GraphQLSyntaxError) as excinfo: parse(body) - assert 'Syntax Error GraphQL (3:8) Expected :, found (' in excinfo.value.message + assert "Syntax Error GraphQL (3:8) Expected :, found (" in excinfo.value.message diff --git a/graphql/language/tests/test_schema_printer.py b/graphql/language/tests/test_schema_printer.py index dd812c01..afa979cb 100644 --- a/graphql/language/tests/test_schema_printer.py +++ b/graphql/language/tests/test_schema_printer.py @@ -11,16 +11,14 @@ def test_prints_minimal_ast(): # type: () -> None - node = ast.ScalarTypeDefinition( - name=ast.Name('foo') - ) + node = ast.ScalarTypeDefinition(name=ast.Name("foo")) - assert print_ast(node) == 'scalar foo' + assert print_ast(node) == "scalar foo" def test_print_produces_helpful_error_messages(): # type: () -> None - bad_ast = {'random': 'Data'} + bad_ast = {"random": "Data"} with raises(AssertionError) as excinfo: print_ast(bad_ast) @@ -40,7 +38,7 @@ def test_prints_kitchen_sink(): ast = parse(SCHEMA_KITCHEN_SINK) printed = print_ast(ast) - expected = '''schema { + expected = """schema { query: QueryType mutation: MutationType } @@ -105,6 +103,6 @@ def test_prints_kitchen_sink(): directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT -''' +""" assert printed == expected diff --git a/graphql/language/tests/test_visitor.py b/graphql/language/tests/test_visitor.py index 4113f397..e37a333a 100644 --- a/graphql/language/tests/test_visitor.py +++ b/graphql/language/tests/test_visitor.py @@ -1,9 +1,20 @@ -from graphql.language.ast import (Document, Field, Name, OperationDefinition, - SelectionSet) +from graphql.language.ast import ( + Document, + Field, + Name, + OperationDefinition, + SelectionSet, +) from graphql.language.parser import parse from graphql.language.printer import print_ast -from graphql.language.visitor import (BREAK, REMOVE, ParallelVisitor, - TypeInfoVisitor, Visitor, visit) +from graphql.language.visitor import ( + BREAK, + REMOVE, + ParallelVisitor, + TypeInfoVisitor, + Visitor, + visit, +) from graphql.type import get_named_type, is_composite_type from graphql.utils.type_info import TypeInfo @@ -25,19 +36,19 @@ def test_allows_editing_a_node_both_on_enter_and_on_leave(): # type: () -> None - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor(Visitor): - def __init__(self): # type: () -> None self.did_enter = False self.did_leave = False - def enter(self, - node, # type: Union[Document, OperationDefinition, SelectionSet] - *args # type: Any - ): + def enter( + self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + *args # type: Any + ): # type: (...) -> Optional[OperationDefinition] if isinstance(node, OperationDefinition): self.did_enter = True @@ -45,38 +56,39 @@ def enter(self, self.selections = None if selection_set: self.selections = selection_set.selections - new_selection_set = SelectionSet( - selections=[]) + new_selection_set = SelectionSet(selections=[]) return OperationDefinition( name=node.name, variable_definitions=node.variable_definitions, directives=node.directives, loc=node.loc, operation=node.operation, - selection_set=new_selection_set) + selection_set=new_selection_set, + ) - def leave(self, - node, # type: Union[Document, OperationDefinition, SelectionSet] - *args # type: Any - ): + def leave( + self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + *args # type: Any + ): # type: (...) -> Optional[OperationDefinition] if isinstance(node, OperationDefinition): self.did_leave = True new_selection_set = None if self.selections: - new_selection_set = SelectionSet( - selections=self.selections) + new_selection_set = SelectionSet(selections=self.selections) return OperationDefinition( name=node.name, variable_definitions=node.variable_definitions, directives=node.directives, loc=node.loc, operation=node.operation, - selection_set=new_selection_set) + selection_set=new_selection_set, + ) visitor = TestVisitor() edited_ast = visit(ast, visitor) - assert ast == parse('{ a, b, c { a, b, c } }', no_location=True) + assert ast == parse("{ a, b, c { a, b, c } }", no_location=True) assert edited_ast == ast assert visitor.did_enter assert visitor.did_leave @@ -84,12 +96,11 @@ def leave(self, def test_allows_editing_the_root_node_on_enter_and_on_leave(): # type: () -> None - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) definitions = ast.definitions class TestVisitor(Visitor): - def __init__(self): # type: () -> None self.did_enter = False @@ -99,17 +110,13 @@ def enter(self, node, *args): # type: (Document, *Any) -> Document if isinstance(node, Document): self.did_enter = True - return Document( - loc=node.loc, - definitions=[]) + return Document(loc=node.loc, definitions=[]) def leave(self, node, *args): # type: (Document, *Any) -> Document if isinstance(node, Document): self.did_leave = True - return Document( - loc=node.loc, - definitions=definitions) + return Document(loc=node.loc, definitions=definitions) visitor = TestVisitor() edited_ast = visit(ast, visitor) @@ -120,58 +127,54 @@ def leave(self, node, *args): def test_allows_for_editing_on_enter(): # type: () -> None - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor(Visitor): - def enter(self, node, *args): # type: (Any, *Any) -> Optional[Any] - if isinstance(node, Field) and node.name.value == 'b': + if isinstance(node, Field) and node.name.value == "b": return REMOVE edited_ast = visit(ast, TestVisitor()) - assert ast == parse('{ a, b, c { a, b, c } }', no_location=True) - assert edited_ast == parse('{ a, c { a, c } }', no_location=True) + assert ast == parse("{ a, b, c { a, b, c } }", no_location=True) + assert edited_ast == parse("{ a, c { a, c } }", no_location=True) def test_allows_for_editing_on_leave(): # type: () -> None - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor(Visitor): - def leave(self, node, *args): # type: (Union[Field, Name], *Any) -> Optional[Falsey] - if isinstance(node, Field) and node.name.value == 'b': + if isinstance(node, Field) and node.name.value == "b": return REMOVE edited_ast = visit(ast, TestVisitor()) - assert ast == parse('{ a, b, c { a, b, c } }', no_location=True) - assert edited_ast == parse('{ a, c { a, c } }', no_location=True) + assert ast == parse("{ a, b, c { a, b, c } }", no_location=True) + assert edited_ast == parse("{ a, c { a, c } }", no_location=True) def test_visits_edited_node(): # type: () -> None - added_field = Field(name=Name(value='__typename')) - ast = parse('{ a { x } }') + added_field = Field(name=Name(value="__typename")) + ast = parse("{ a { x } }") class TestVisitor(Visitor): - def __init__(self): # type: () -> None self.did_visit_added_field = False def enter(self, node, *args): # type: (Any, *Any) -> Optional[Field] - if isinstance(node, Field) and node.name.value == 'a': + if isinstance(node, Field) and node.name.value == "a": selection_set = node.selection_set selections = [] if selection_set: selections = selection_set.selections - new_selection_set = SelectionSet( - selections=[added_field] + selections) + new_selection_set = SelectionSet(selections=[added_field] + selections) return Field(name=None, selection_set=new_selection_set) if node is added_field: self.did_visit_added_field = True @@ -184,114 +187,104 @@ def enter(self, node, *args): def test_allows_skipping_a_subtree(): # type: () -> None visited = [] - ast = parse('{ a, b { x }, c }') + ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): - def enter(self, node, *args): # type: (Any, *Any) -> Optional[Any] - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - if isinstance(node, Field) and node.name.value == 'b': + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + if isinstance(node, Field) and node.name.value == "b": return False def leave(self, node, *args): # type: (Union[Field, Name, SelectionSet], *Any) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) visit(ast, TestVisitor()) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'OperationDefinition', None], - ['leave', 'Document', None], + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "OperationDefinition", None], + ["leave", "Document", None], ] def test_allows_early_exit_while_visiting(): # type: () -> None visited = [] - ast = parse('{ a, b { x }, c }') + ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): - def enter(self, node, *args): # type: (Any, *Any) -> Optional[Any] - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - if isinstance(node, Name) and node.value == 'x': + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + if isinstance(node, Name) and node.value == "x": return BREAK def leave(self, node, *args): # type: (Union[Field, Name], *Any) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) visit(ast, TestVisitor()) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'b'], - ['leave', 'Name', 'b'], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'x'], + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "x"], ] def test_allows_a_named_functions_visitor_api(): # type: () -> None visited = [] - ast = parse('{ a, b { x }, c }') + ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): - def enter_Name(self, node, *args): # type: (Name, *Any) -> None - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) def enter_SelectionSet(self, node, *args): # type: (SelectionSet, *Any) -> None - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) def leave_SelectionSet(self, node, *args): # type: (SelectionSet, *Any) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) visit(ast, TestVisitor()) assert visited == [ - ['enter', 'SelectionSet', None], - ['enter', 'Name', 'a'], - ['enter', 'Name', 'b'], - ['enter', 'SelectionSet', None], - ['enter', 'Name', 'x'], - ['leave', 'SelectionSet', None], - ['enter', 'Name', 'c'], - ['leave', 'SelectionSet', None], + ["enter", "SelectionSet", None], + ["enter", "Name", "a"], + ["enter", "Name", "b"], + ["enter", "SelectionSet", None], + ["enter", "Name", "x"], + ["leave", "SelectionSet", None], + ["enter", "Name", "c"], + ["leave", "SelectionSet", None], ] @@ -301,878 +294,904 @@ def test_visits_kitchen_sink(): ast = parse(KITCHEN_SINK) class TestVisitor(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None kind = parent and type(parent).__name__ - if kind == 'list': + if kind == "list": kind = None - visited.append(['enter', type(node).__name__, key, kind]) + visited.append(["enter", type(node).__name__, key, kind]) def leave(self, node, key, parent, *args): # type: (Any, Union[int, str], Any, *List[Any]) -> None kind = parent and type(parent).__name__ - if kind == 'list': + if kind == "list": kind = None - visited.append(['leave', type(node).__name__, key, kind]) + visited.append(["leave", type(node).__name__, key, kind]) visit(ast, TestVisitor()) assert visited == [ - ['enter', 'Document', None, None], - ['enter', 'OperationDefinition', 0, None], - ['enter', 'Name', 'name', 'OperationDefinition'], - ['leave', 'Name', 'name', 'OperationDefinition'], - ['enter', 'VariableDefinition', 0, None], - ['enter', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'NamedType', 'type', 'VariableDefinition'], - ['enter', 'Name', 'name', 'NamedType'], - ['leave', 'Name', 'name', 'NamedType'], - ['leave', 'NamedType', 'type', 'VariableDefinition'], - ['leave', 'VariableDefinition', 0, None], - ['enter', 'VariableDefinition', 1, None], - ['enter', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'NamedType', 'type', 'VariableDefinition'], - ['enter', 'Name', 'name', 'NamedType'], - ['leave', 'Name', 'name', 'NamedType'], - ['leave', 'NamedType', 'type', 'VariableDefinition'], - ['enter', 'EnumValue', 'default_value', 'VariableDefinition'], - ['leave', 'EnumValue', 'default_value', 'VariableDefinition'], - ['leave', 'VariableDefinition', 1, None], - ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'ListValue', 'value', 'Argument'], - ['enter', 'IntValue', 0, None], - ['leave', 'IntValue', 0, None], - ['enter', 'IntValue', 1, None], - ['leave', 'IntValue', 1, None], - ['leave', 'ListValue', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['enter', 'InlineFragment', 1, None], - ['enter', 'NamedType', 'type_condition', 'InlineFragment'], - ['enter', 'Name', 'name', 'NamedType'], - ['leave', 'Name', 'name', 'NamedType'], - ['leave', 'NamedType', 'type_condition', 'InlineFragment'], - ['enter', 'Directive', 0, None], - ['enter', 'Name', 'name', 'Directive'], - ['leave', 'Name', 'name', 'Directive'], - ['leave', 'Directive', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['enter', 'Field', 1, None], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'IntValue', 'value', 'Argument'], - ['leave', 'IntValue', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'Argument', 1, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 1, None], - ['enter', 'Directive', 0, None], - ['enter', 'Name', 'name', 'Directive'], - ['leave', 'Name', 'name', 'Directive'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['leave', 'Directive', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['enter', 'FragmentSpread', 1, None], - ['enter', 'Name', 'name', 'FragmentSpread'], - ['leave', 'Name', 'name', 'FragmentSpread'], - ['leave', 'FragmentSpread', 1, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 1, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['leave', 'InlineFragment', 1, None], - ['enter', 'InlineFragment', 2, None], - ['enter', 'Directive', 0, None], - ['enter', 'Name', 'name', 'Directive'], - ['leave', 'Name', 'name', 'Directive'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['leave', 'Directive', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['leave', 'InlineFragment', 2, None], - ['enter', 'InlineFragment', 3, None], - ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'], - ['leave', 'InlineFragment', 3, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['leave', 'OperationDefinition', 0, None], - ['enter', 'OperationDefinition', 1, None], - ['enter', 'Name', 'name', 'OperationDefinition'], - ['leave', 'Name', 'name', 'OperationDefinition'], - ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'IntValue', 'value', 'Argument'], - ['leave', 'IntValue', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'Directive', 0, None], - ['enter', 'Name', 'name', 'Directive'], - ['leave', 'Name', 'name', 'Directive'], - ['leave', 'Directive', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['leave', 'OperationDefinition', 1, None], - ['enter', 'OperationDefinition', 2, None], - ['enter', 'Name', 'name', 'OperationDefinition'], - ['leave', 'Name', 'name', 'OperationDefinition'], - ['enter', 'VariableDefinition', 0, None], - ['enter', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'variable', 'VariableDefinition'], - ['enter', 'NamedType', 'type', 'VariableDefinition'], - ['enter', 'Name', 'name', 'NamedType'], - ['leave', 'Name', 'name', 'NamedType'], - ['leave', 'NamedType', 'type', 'VariableDefinition'], - ['leave', 'VariableDefinition', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['enter', 'Field', 1, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'SelectionSet', 'selection_set', 'Field'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 1, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'Field'], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['leave', 'OperationDefinition', 2, None], - ['enter', 'FragmentDefinition', 3, None], - ['enter', 'Name', 'name', 'FragmentDefinition'], - ['leave', 'Name', 'name', 'FragmentDefinition'], - ['enter', 'NamedType', 'type_condition', 'FragmentDefinition'], - ['enter', 'Name', 'name', 'NamedType'], - ['leave', 'Name', 'name', 'NamedType'], - ['leave', 'NamedType', 'type_condition', 'FragmentDefinition'], - ['enter', 'SelectionSet', 'selection_set', 'FragmentDefinition'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'Argument', 1, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'Variable', 'value', 'Argument'], - ['enter', 'Name', 'name', 'Variable'], - ['leave', 'Name', 'name', 'Variable'], - ['leave', 'Variable', 'value', 'Argument'], - ['leave', 'Argument', 1, None], - ['enter', 'Argument', 2, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'ObjectValue', 'value', 'Argument'], - ['enter', 'ObjectField', 0, None], - ['enter', 'Name', 'name', 'ObjectField'], - ['leave', 'Name', 'name', 'ObjectField'], - ['enter', 'StringValue', 'value', 'ObjectField'], - ['leave', 'StringValue', 'value', 'ObjectField'], - ['leave', 'ObjectField', 0, None], - ['leave', 'ObjectValue', 'value', 'Argument'], - ['leave', 'Argument', 2, None], - ['leave', 'Field', 0, None], - ['leave', 'SelectionSet', 'selection_set', 'FragmentDefinition'], - ['leave', 'FragmentDefinition', 3, None], - ['enter', 'OperationDefinition', 4, None], - ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['enter', 'Field', 0, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'BooleanValue', 'value', 'Argument'], - ['leave', 'BooleanValue', 'value', 'Argument'], - ['leave', 'Argument', 0, None], - ['enter', 'Argument', 1, None], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'BooleanValue', 'value', 'Argument'], - ['leave', 'BooleanValue', 'value', 'Argument'], - ['leave', 'Argument', 1, None], - ['leave', 'Field', 0, None], - ['enter', 'Field', 1, None], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 1, None], - ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'], - ['leave', 'OperationDefinition', 4, None], - ['leave', 'Document', None, None] + ["enter", "Document", None, None], + ["enter", "OperationDefinition", 0, None], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "VariableDefinition", 0, None], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["leave", "VariableDefinition", 0, None], + ["enter", "VariableDefinition", 1, None], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["enter", "EnumValue", "default_value", "VariableDefinition"], + ["leave", "EnumValue", "default_value", "VariableDefinition"], + ["leave", "VariableDefinition", 1, None], + ["enter", "SelectionSet", "selection_set", "OperationDefinition"], + ["enter", "Field", 0, None], + ["enter", "Name", "alias", "Field"], + ["leave", "Name", "alias", "Field"], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "ListValue", "value", "Argument"], + ["enter", "IntValue", 0, None], + ["leave", "IntValue", 0, None], + ["enter", "IntValue", 1, None], + ["leave", "IntValue", 1, None], + ["leave", "ListValue", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["enter", "InlineFragment", 1, None], + ["enter", "NamedType", "type_condition", "InlineFragment"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type_condition", "InlineFragment"], + ["enter", "Directive", 0, None], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["leave", "Directive", 0, None], + ["enter", "SelectionSet", "selection_set", "InlineFragment"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["enter", "Field", 1, None], + ["enter", "Name", "alias", "Field"], + ["leave", "Name", "alias", "Field"], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "IntValue", "value", "Argument"], + ["leave", "IntValue", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "Argument", 1, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 1, None], + ["enter", "Directive", 0, None], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, None], + ["leave", "Directive", 0, None], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["enter", "FragmentSpread", 1, None], + ["enter", "Name", "name", "FragmentSpread"], + ["leave", "Name", "name", "FragmentSpread"], + ["leave", "FragmentSpread", 1, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 1, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "InlineFragment"], + ["leave", "InlineFragment", 1, None], + ["enter", "InlineFragment", 2, None], + ["enter", "Directive", 0, None], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, None], + ["leave", "Directive", 0, None], + ["enter", "SelectionSet", "selection_set", "InlineFragment"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "InlineFragment"], + ["leave", "InlineFragment", 2, None], + ["enter", "InlineFragment", 3, None], + ["enter", "SelectionSet", "selection_set", "InlineFragment"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "InlineFragment"], + ["leave", "InlineFragment", 3, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "OperationDefinition"], + ["leave", "OperationDefinition", 0, None], + ["enter", "OperationDefinition", 1, None], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "SelectionSet", "selection_set", "OperationDefinition"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "IntValue", "value", "Argument"], + ["leave", "IntValue", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "Directive", 0, None], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["leave", "Directive", 0, None], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "OperationDefinition"], + ["leave", "OperationDefinition", 1, None], + ["enter", "OperationDefinition", 2, None], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "VariableDefinition", 0, None], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["leave", "VariableDefinition", 0, None], + ["enter", "SelectionSet", "selection_set", "OperationDefinition"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["enter", "Field", 1, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selection_set", "Field"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 1, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "Field"], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "OperationDefinition"], + ["leave", "OperationDefinition", 2, None], + ["enter", "FragmentDefinition", 3, None], + ["enter", "Name", "name", "FragmentDefinition"], + ["leave", "Name", "name", "FragmentDefinition"], + ["enter", "NamedType", "type_condition", "FragmentDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type_condition", "FragmentDefinition"], + ["enter", "SelectionSet", "selection_set", "FragmentDefinition"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "Argument", 1, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 1, None], + ["enter", "Argument", 2, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "ObjectValue", "value", "Argument"], + ["enter", "ObjectField", 0, None], + ["enter", "Name", "name", "ObjectField"], + ["leave", "Name", "name", "ObjectField"], + ["enter", "StringValue", "value", "ObjectField"], + ["leave", "StringValue", "value", "ObjectField"], + ["leave", "ObjectField", 0, None], + ["leave", "ObjectValue", "value", "Argument"], + ["leave", "Argument", 2, None], + ["leave", "Field", 0, None], + ["leave", "SelectionSet", "selection_set", "FragmentDefinition"], + ["leave", "FragmentDefinition", 3, None], + ["enter", "OperationDefinition", 4, None], + ["enter", "SelectionSet", "selection_set", "OperationDefinition"], + ["enter", "Field", 0, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "BooleanValue", "value", "Argument"], + ["leave", "BooleanValue", "value", "Argument"], + ["leave", "Argument", 0, None], + ["enter", "Argument", 1, None], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "BooleanValue", "value", "Argument"], + ["leave", "BooleanValue", "value", "Argument"], + ["leave", "Argument", 1, None], + ["leave", "Field", 0, None], + ["enter", "Field", 1, None], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 1, None], + ["leave", "SelectionSet", "selection_set", "OperationDefinition"], + ["leave", "OperationDefinition", 4, None], + ["leave", "Document", None, None], ] def test_visits_in_pararell_allows_skipping_a_subtree(): # type: () -> None visited = [] - ast = parse('{ a, b { x }, c }') + ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - if type(node).__name__ == 'Field' and node.name.value == 'b': + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + if type(node).__name__ == "Field" and node.name.value == "b": return False - def leave(self, - node, # type: Union[Field, Name, SelectionSet] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field, OperationDefinition] - *args # type: List[Any] - ): + def leave( + self, + node, # type: Union[Field, Name, SelectionSet] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field, OperationDefinition] + *args # type: List[Any] + ): # type: (...) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) visit(ast, ParallelVisitor([TestVisitor()])) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'OperationDefinition', None], - ['leave', 'Document', None], + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "OperationDefinition", None], + ["leave", "Document", None], ] def test_visits_in_pararell_allows_skipping_different_subtrees(): # type: () -> None visited = [] - ast = parse('{ a { x }, b { y} }') + ast = parse("{ a { x }, b { y} }") class TestVisitor(Visitor): - def __init__(self, name): # type: (str) -> None self.name = name - def enter(self, - node, # type: Union[Document, OperationDefinition, SelectionSet] - key, # type: Union[None, int, str] - parent, # type: Union[List[OperationDefinition], None, OperationDefinition] - *args # type: Any - ): + def enter( + self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + key, # type: Union[None, int, str] + parent, # type: Union[List[OperationDefinition], None, OperationDefinition] + *args # type: Any + ): # type: (...) -> Optional[Any] - visited.append(["no-{}".format(self.name), 'enter', - type(node).__name__, getattr(node, 'value', None)]) - if type(node).__name__ == 'Field' and node.name.value == self.name: + visited.append( + [ + "no-{}".format(self.name), + "enter", + type(node).__name__, + getattr(node, "value", None), + ] + ) + if type(node).__name__ == "Field" and node.name.value == self.name: return False - def leave(self, - node, # type: Union[Field, Name, SelectionSet] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + def leave( + self, + node, # type: Union[Field, Name, SelectionSet] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> None - visited.append(["no-{}".format(self.name), 'leave', - type(node).__name__, getattr(node, 'value', None)]) - - visit(ast, ParallelVisitor([TestVisitor('a'), TestVisitor('b')])) + visited.append( + [ + "no-{}".format(self.name), + "leave", + type(node).__name__, + getattr(node, "value", None), + ] + ) + + visit(ast, ParallelVisitor([TestVisitor("a"), TestVisitor("b")])) assert visited == [ - ['no-a', 'enter', 'Document', None], - ['no-b', 'enter', 'Document', None], - ['no-a', 'enter', 'OperationDefinition', None], - ['no-b', 'enter', 'OperationDefinition', None], - ['no-a', 'enter', 'SelectionSet', None], - ['no-b', 'enter', 'SelectionSet', None], - ['no-a', 'enter', 'Field', None], - ['no-b', 'enter', 'Field', None], - ['no-b', 'enter', 'Name', 'a'], - ['no-b', 'leave', 'Name', 'a'], - ['no-b', 'enter', 'SelectionSet', None], - ['no-b', 'enter', 'Field', None], - ['no-b', 'enter', 'Name', 'x'], - ['no-b', 'leave', 'Name', 'x'], - ['no-b', 'leave', 'Field', None], - ['no-b', 'leave', 'SelectionSet', None], - ['no-b', 'leave', 'Field', None], - ['no-a', 'enter', 'Field', None], - ['no-b', 'enter', 'Field', None], - ['no-a', 'enter', 'Name', 'b'], - ['no-a', 'leave', 'Name', 'b'], - ['no-a', 'enter', 'SelectionSet', None], - ['no-a', 'enter', 'Field', None], - ['no-a', 'enter', 'Name', 'y'], - ['no-a', 'leave', 'Name', 'y'], - ['no-a', 'leave', 'Field', None], - ['no-a', 'leave', 'SelectionSet', None], - ['no-a', 'leave', 'Field', None], - ['no-a', 'leave', 'SelectionSet', None], - ['no-b', 'leave', 'SelectionSet', None], - ['no-a', 'leave', 'OperationDefinition', None], - ['no-b', 'leave', 'OperationDefinition', None], - ['no-a', 'leave', 'Document', None], - ['no-b', 'leave', 'Document', None], + ["no-a", "enter", "Document", None], + ["no-b", "enter", "Document", None], + ["no-a", "enter", "OperationDefinition", None], + ["no-b", "enter", "OperationDefinition", None], + ["no-a", "enter", "SelectionSet", None], + ["no-b", "enter", "SelectionSet", None], + ["no-a", "enter", "Field", None], + ["no-b", "enter", "Field", None], + ["no-b", "enter", "Name", "a"], + ["no-b", "leave", "Name", "a"], + ["no-b", "enter", "SelectionSet", None], + ["no-b", "enter", "Field", None], + ["no-b", "enter", "Name", "x"], + ["no-b", "leave", "Name", "x"], + ["no-b", "leave", "Field", None], + ["no-b", "leave", "SelectionSet", None], + ["no-b", "leave", "Field", None], + ["no-a", "enter", "Field", None], + ["no-b", "enter", "Field", None], + ["no-a", "enter", "Name", "b"], + ["no-a", "leave", "Name", "b"], + ["no-a", "enter", "SelectionSet", None], + ["no-a", "enter", "Field", None], + ["no-a", "enter", "Name", "y"], + ["no-a", "leave", "Name", "y"], + ["no-a", "leave", "Field", None], + ["no-a", "leave", "SelectionSet", None], + ["no-a", "leave", "Field", None], + ["no-a", "leave", "SelectionSet", None], + ["no-b", "leave", "SelectionSet", None], + ["no-a", "leave", "OperationDefinition", None], + ["no-b", "leave", "OperationDefinition", None], + ["no-a", "leave", "Document", None], + ["no-b", "leave", "Document", None], ] def test_visits_in_pararell_allows_early_exit_while_visiting(): # type: () -> None visited = [] - ast = parse('{ a, b { x }, c }') + ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - - def leave(self, - node, # type: Union[Field, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + + def leave( + self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> Optional[object] - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) - if type(node).__name__ == 'Name' and node.value == 'x': + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) + if type(node).__name__ == "Name" and node.value == "x": return BREAK visit(ast, ParallelVisitor([TestVisitor()])) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'b'], - ['leave', 'Name', 'b'], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'x'], - ['leave', 'Name', 'x'] + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "x"], + ["leave", "Name", "x"], ] def test_visits_in_pararell_allows_early_exit_from_different_points(): # type: () -> None visited = [] - ast = parse('{ a { y }, b { x } }') + ast = parse("{ a { y }, b { x } }") class TestVisitor(Visitor): - def __init__(self, name): # type: (str) -> None self.name = name - def enter(self, - node, # type: Union[Document, OperationDefinition, SelectionSet] - key, # type: Union[None, int, str] - parent, # type: Union[List[OperationDefinition], None, OperationDefinition] - *args # type: Any - ): + def enter( + self, + node, # type: Union[Document, OperationDefinition, SelectionSet] + key, # type: Union[None, int, str] + parent, # type: Union[List[OperationDefinition], None, OperationDefinition] + *args # type: Any + ): # type: (...) -> None - visited.append(["break-{}".format(self.name), 'enter', - type(node).__name__, getattr(node, 'value', None)]) - - def leave(self, - node, # type: Union[Field, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + visited.append( + [ + "break-{}".format(self.name), + "enter", + type(node).__name__, + getattr(node, "value", None), + ] + ) + + def leave( + self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> Optional[Any] - visited.append(["break-{}".format(self.name), 'leave', - type(node).__name__, getattr(node, 'value', None)]) - if type(node).__name__ == 'Field' and node.name.value == self.name: + visited.append( + [ + "break-{}".format(self.name), + "leave", + type(node).__name__, + getattr(node, "value", None), + ] + ) + if type(node).__name__ == "Field" and node.name.value == self.name: return BREAK - visit(ast, ParallelVisitor([TestVisitor('a'), TestVisitor('b')])) + visit(ast, ParallelVisitor([TestVisitor("a"), TestVisitor("b")])) assert visited == [ - ['break-a', 'enter', 'Document', None], - ['break-b', 'enter', 'Document', None], - ['break-a', 'enter', 'OperationDefinition', None], - ['break-b', 'enter', 'OperationDefinition', None], - ['break-a', 'enter', 'SelectionSet', None], - ['break-b', 'enter', 'SelectionSet', None], - ['break-a', 'enter', 'Field', None], - ['break-b', 'enter', 'Field', None], - ['break-a', 'enter', 'Name', 'a'], - ['break-b', 'enter', 'Name', 'a'], - ['break-a', 'leave', 'Name', 'a'], - ['break-b', 'leave', 'Name', 'a'], - ['break-a', 'enter', 'SelectionSet', None], - ['break-b', 'enter', 'SelectionSet', None], - ['break-a', 'enter', 'Field', None], - ['break-b', 'enter', 'Field', None], - ['break-a', 'enter', 'Name', 'y'], - ['break-b', 'enter', 'Name', 'y'], - ['break-a', 'leave', 'Name', 'y'], - ['break-b', 'leave', 'Name', 'y'], - ['break-a', 'leave', 'Field', None], - ['break-b', 'leave', 'Field', None], - ['break-a', 'leave', 'SelectionSet', None], - ['break-b', 'leave', 'SelectionSet', None], - ['break-a', 'leave', 'Field', None], - ['break-b', 'leave', 'Field', None], - ['break-b', 'enter', 'Field', None], - ['break-b', 'enter', 'Name', 'b'], - ['break-b', 'leave', 'Name', 'b'], - ['break-b', 'enter', 'SelectionSet', None], - ['break-b', 'enter', 'Field', None], - ['break-b', 'enter', 'Name', 'x'], - ['break-b', 'leave', 'Name', 'x'], - ['break-b', 'leave', 'Field', None], - ['break-b', 'leave', 'SelectionSet', None], - ['break-b', 'leave', 'Field', None] + ["break-a", "enter", "Document", None], + ["break-b", "enter", "Document", None], + ["break-a", "enter", "OperationDefinition", None], + ["break-b", "enter", "OperationDefinition", None], + ["break-a", "enter", "SelectionSet", None], + ["break-b", "enter", "SelectionSet", None], + ["break-a", "enter", "Field", None], + ["break-b", "enter", "Field", None], + ["break-a", "enter", "Name", "a"], + ["break-b", "enter", "Name", "a"], + ["break-a", "leave", "Name", "a"], + ["break-b", "leave", "Name", "a"], + ["break-a", "enter", "SelectionSet", None], + ["break-b", "enter", "SelectionSet", None], + ["break-a", "enter", "Field", None], + ["break-b", "enter", "Field", None], + ["break-a", "enter", "Name", "y"], + ["break-b", "enter", "Name", "y"], + ["break-a", "leave", "Name", "y"], + ["break-b", "leave", "Name", "y"], + ["break-a", "leave", "Field", None], + ["break-b", "leave", "Field", None], + ["break-a", "leave", "SelectionSet", None], + ["break-b", "leave", "SelectionSet", None], + ["break-a", "leave", "Field", None], + ["break-b", "leave", "Field", None], + ["break-b", "enter", "Field", None], + ["break-b", "enter", "Name", "b"], + ["break-b", "leave", "Name", "b"], + ["break-b", "enter", "SelectionSet", None], + ["break-b", "enter", "Field", None], + ["break-b", "enter", "Name", "x"], + ["break-b", "leave", "Name", "x"], + ["break-b", "leave", "Field", None], + ["break-b", "leave", "SelectionSet", None], + ["break-b", "leave", "Field", None], ] def test_visits_in_pararell_allows_for_editing_on_enter(): # type: () -> None visited = [] - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor1(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] - if type(node).__name__ == 'Field' and node.name.value == 'b': + if type(node).__name__ == "Field" and node.name.value == "b": return REMOVE class TestVisitor2(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - - def leave(self, - node, # type: Union[Field, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + + def leave( + self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) edited_ast = visit(ast, ParallelVisitor([TestVisitor1(), TestVisitor2()])) - assert ast == parse('{ a, b, c { a, b, c } }', no_location=True) - assert edited_ast == parse('{ a, c { a, c } }', no_location=True) + assert ast == parse("{ a, b, c { a, b, c } }", no_location=True) + assert edited_ast == parse("{ a, c { a, c } }", no_location=True) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'OperationDefinition', None], - ['leave', 'Document', None] + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "OperationDefinition", None], + ["leave", "Document", None], ] def test_visits_in_pararell_allows_for_editing_on_leave(): # type: () -> None visited = [] - ast = parse('{ a, b, c { a, b, c } }', no_location=True) + ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor1(Visitor): - - def leave(self, - node, # type: Union[Field, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + def leave( + self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> Optional[Falsey] - if type(node).__name__ == 'Field' and node.name.value == 'b': + if type(node).__name__ == "Field" and node.name.value == "b": return REMOVE class TestVisitor2(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None - visited.append( - ['enter', type(node).__name__, getattr(node, 'value', None)]) - - def leave(self, - node, # type: Union[Field, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Field], Field] - *args # type: List[Any] - ): + visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) + + def leave( + self, + node, # type: Union[Field, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Field], Field] + *args # type: List[Any] + ): # type: (...) -> None - visited.append( - ['leave', type(node).__name__, getattr(node, 'value', None)]) + visited.append(["leave", type(node).__name__, getattr(node, "value", None)]) edited_ast = visit(ast, ParallelVisitor([TestVisitor1(), TestVisitor2()])) - assert ast == parse('{ a, b, c { a, b, c } }', no_location=True) - assert edited_ast == parse('{ a, c { a, c } }', no_location=True) + assert ast == parse("{ a, b, c { a, b, c } }", no_location=True) + assert edited_ast == parse("{ a, c { a, c } }", no_location=True) assert visited == [ - ['enter', 'Document', None], - ['enter', 'OperationDefinition', None], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'b'], - ['leave', 'Name', 'b'], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['enter', 'SelectionSet', None], - ['enter', 'Field', None], - ['enter', 'Name', 'a'], - ['leave', 'Name', 'a'], - ['leave', 'Field', None], - ['enter', 'Field', None], - ['enter', 'Name', 'b'], - ['leave', 'Name', 'b'], - ['enter', 'Field', None], - ['enter', 'Name', 'c'], - ['leave', 'Name', 'c'], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'Field', None], - ['leave', 'SelectionSet', None], - ['leave', 'OperationDefinition', None], - ['leave', 'Document', None] + ["enter", "Document", None], + ["enter", "OperationDefinition", None], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["enter", "SelectionSet", None], + ["enter", "Field", None], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", None], + ["enter", "Field", None], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "Field", None], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "Field", None], + ["leave", "SelectionSet", None], + ["leave", "OperationDefinition", None], + ["leave", "Document", None], ] def test_visits_with_typeinfo_maintains_type_info_during_visit(): # type: () -> None visited = [] - ast = parse('{ human(id: 4) { name, pets { name }, unknown } }') + ast = parse("{ human(id: 4) { name, pets { name }, unknown } }") type_info = TypeInfo(test_schema) class TestVisitor(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() - visited.append([ - 'enter', - type(node).__name__, - node.value if type(node).__name__ == "Name" else None, - str(parent_type) if parent_type else None, - str(_type) if _type else None, - str(input_type) if input_type else None - ]) - - def leave(self, - node, # type: Union[Argument, IntValue, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Argument], Argument, Field] - *args # type: List[Any] - ): + visited.append( + [ + "enter", + type(node).__name__, + node.value if type(node).__name__ == "Name" else None, + str(parent_type) if parent_type else None, + str(_type) if _type else None, + str(input_type) if input_type else None, + ] + ) + + def leave( + self, + node, # type: Union[Argument, IntValue, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Argument], Argument, Field] + *args # type: List[Any] + ): # type: (...) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() - visited.append([ - 'leave', - type(node).__name__, - node.value if type(node).__name__ == "Name" else None, - str(parent_type) if parent_type else None, - str(_type) if _type else None, - str(input_type) if input_type else None - ]) + visited.append( + [ + "leave", + type(node).__name__, + node.value if type(node).__name__ == "Name" else None, + str(parent_type) if parent_type else None, + str(_type) if _type else None, + str(input_type) if input_type else None, + ] + ) visit(ast, TypeInfoVisitor(type_info, TestVisitor())) assert visited == [ - ['enter', 'Document', None, None, None, None], - ['enter', 'OperationDefinition', None, None, 'QueryRoot', None], - ['enter', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None], - ['enter', 'Field', None, 'QueryRoot', 'Human', None], - ['enter', 'Name', 'human', 'QueryRoot', 'Human', None], - ['leave', 'Name', 'human', 'QueryRoot', 'Human', None], - ['enter', 'Argument', None, 'QueryRoot', 'Human', 'ID'], - ['enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID'], - ['leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID'], - ['enter', 'IntValue', None, 'QueryRoot', 'Human', 'ID'], - ['leave', 'IntValue', None, 'QueryRoot', 'Human', 'ID'], - ['leave', 'Argument', None, 'QueryRoot', 'Human', 'ID'], - ['enter', 'SelectionSet', None, 'Human', 'Human', None], - ['enter', 'Field', None, 'Human', 'String', None], - ['enter', 'Name', 'name', 'Human', 'String', None], - ['leave', 'Name', 'name', 'Human', 'String', None], - ['leave', 'Field', None, 'Human', 'String', None], - ['enter', 'Field', None, 'Human', '[Pet]', None], - ['enter', 'Name', 'pets', 'Human', '[Pet]', None], - ['leave', 'Name', 'pets', 'Human', '[Pet]', None], - ['enter', 'SelectionSet', None, 'Pet', '[Pet]', None], - ['enter', 'Field', None, 'Pet', 'String', None], - ['enter', 'Name', 'name', 'Pet', 'String', None], - ['leave', 'Name', 'name', 'Pet', 'String', None], - ['leave', 'Field', None, 'Pet', 'String', None], - ['leave', 'SelectionSet', None, 'Pet', '[Pet]', None], - ['leave', 'Field', None, 'Human', '[Pet]', None], - ['enter', 'Field', None, 'Human', None, None], - ['enter', 'Name', 'unknown', 'Human', None, None], - ['leave', 'Name', 'unknown', 'Human', None, None], - ['leave', 'Field', None, 'Human', None, None], - ['leave', 'SelectionSet', None, 'Human', 'Human', None], - ['leave', 'Field', None, 'QueryRoot', 'Human', None], - ['leave', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None], - ['leave', 'OperationDefinition', None, None, 'QueryRoot', None], - ['leave', 'Document', None, None, None, None] + ["enter", "Document", None, None, None, None], + ["enter", "OperationDefinition", None, None, "QueryRoot", None], + ["enter", "SelectionSet", None, "QueryRoot", "QueryRoot", None], + ["enter", "Field", None, "QueryRoot", "Human", None], + ["enter", "Name", "human", "QueryRoot", "Human", None], + ["leave", "Name", "human", "QueryRoot", "Human", None], + ["enter", "Argument", None, "QueryRoot", "Human", "ID"], + ["enter", "Name", "id", "QueryRoot", "Human", "ID"], + ["leave", "Name", "id", "QueryRoot", "Human", "ID"], + ["enter", "IntValue", None, "QueryRoot", "Human", "ID"], + ["leave", "IntValue", None, "QueryRoot", "Human", "ID"], + ["leave", "Argument", None, "QueryRoot", "Human", "ID"], + ["enter", "SelectionSet", None, "Human", "Human", None], + ["enter", "Field", None, "Human", "String", None], + ["enter", "Name", "name", "Human", "String", None], + ["leave", "Name", "name", "Human", "String", None], + ["leave", "Field", None, "Human", "String", None], + ["enter", "Field", None, "Human", "[Pet]", None], + ["enter", "Name", "pets", "Human", "[Pet]", None], + ["leave", "Name", "pets", "Human", "[Pet]", None], + ["enter", "SelectionSet", None, "Pet", "[Pet]", None], + ["enter", "Field", None, "Pet", "String", None], + ["enter", "Name", "name", "Pet", "String", None], + ["leave", "Name", "name", "Pet", "String", None], + ["leave", "Field", None, "Pet", "String", None], + ["leave", "SelectionSet", None, "Pet", "[Pet]", None], + ["leave", "Field", None, "Human", "[Pet]", None], + ["enter", "Field", None, "Human", None, None], + ["enter", "Name", "unknown", "Human", None, None], + ["leave", "Name", "unknown", "Human", None, None], + ["leave", "Field", None, "Human", None, None], + ["leave", "SelectionSet", None, "Human", "Human", None], + ["leave", "Field", None, "QueryRoot", "Human", None], + ["leave", "SelectionSet", None, "QueryRoot", "QueryRoot", None], + ["leave", "OperationDefinition", None, None, "QueryRoot", None], + ["leave", "Document", None, None, None, None], ] def test_visits_with_typeinfo_maintains_type_info_during_edit(): # type: () -> None visited = [] - ast = parse('{ human(id: 4) { name, pets }, alien }') + ast = parse("{ human(id: 4) { name, pets }, alien }") type_info = TypeInfo(test_schema) class TestVisitor(Visitor): - def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() - visited.append([ - 'enter', - type(node).__name__, - node.value if type(node).__name__ == "Name" else None, - str(parent_type) if parent_type else None, - str(_type) if _type else None, - str(input_type) if input_type else None - ]) + visited.append( + [ + "enter", + type(node).__name__, + node.value if type(node).__name__ == "Name" else None, + str(parent_type) if parent_type else None, + str(_type) if _type else None, + str(input_type) if input_type else None, + ] + ) # Make a query valid by adding missing selection sets. - if type(node).__name__ == "Field" and not node.selection_set and is_composite_type(get_named_type(_type)): + if ( + type(node).__name__ == "Field" + and not node.selection_set + and is_composite_type(get_named_type(_type)) + ): return Field( alias=node.alias, name=node.name, arguments=node.arguments, directives=node.directives, - selection_set=SelectionSet( - [Field(name=Name(value='__typename'))] - ) + selection_set=SelectionSet([Field(name=Name(value="__typename"))]), ) - def leave(self, - node, # type: Union[Argument, IntValue, Name] - key, # type: Union[int, str] - parent, # type: Union[List[Argument], Argument, Field] - *args # type: List[Any] - ): + def leave( + self, + node, # type: Union[Argument, IntValue, Name] + key, # type: Union[int, str] + parent, # type: Union[List[Argument], Argument, Field] + *args # type: List[Any] + ): # type: (...) -> None parent_type = type_info.get_parent_type() _type = type_info.get_type() input_type = type_info.get_input_type() - visited.append([ - 'leave', - type(node).__name__, - node.value if type(node).__name__ == "Name" else None, - str(parent_type) if parent_type else None, - str(_type) if _type else None, - str(input_type) if input_type else None - ]) + visited.append( + [ + "leave", + type(node).__name__, + node.value if type(node).__name__ == "Name" else None, + str(parent_type) if parent_type else None, + str(_type) if _type else None, + str(input_type) if input_type else None, + ] + ) edited_ast = visit(ast, TypeInfoVisitor(type_info, TestVisitor())) # assert print_ast(ast) == print_ast(parse( # '{ human(id: 4) { name, pets }, alien }' # )) - assert print_ast(edited_ast) == print_ast(parse( - '{ human(id: 4) { name, pets { __typename } }, alien { __typename } }' - )) + assert print_ast(edited_ast) == print_ast( + parse("{ human(id: 4) { name, pets { __typename } }, alien { __typename } }") + ) assert visited == [ - ['enter', 'Document', None, None, None, None], - ['enter', 'OperationDefinition', None, None, 'QueryRoot', None], - ['enter', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None], - ['enter', 'Field', None, 'QueryRoot', 'Human', None], - ['enter', 'Name', 'human', 'QueryRoot', 'Human', None], - ['leave', 'Name', 'human', 'QueryRoot', 'Human', None], - ['enter', 'Argument', None, 'QueryRoot', 'Human', 'ID'], - ['enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID'], - ['leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID'], - ['enter', 'IntValue', None, 'QueryRoot', 'Human', 'ID'], - ['leave', 'IntValue', None, 'QueryRoot', 'Human', 'ID'], - ['leave', 'Argument', None, 'QueryRoot', 'Human', 'ID'], - ['enter', 'SelectionSet', None, 'Human', 'Human', None], - ['enter', 'Field', None, 'Human', 'String', None], - ['enter', 'Name', 'name', 'Human', 'String', None], - ['leave', 'Name', 'name', 'Human', 'String', None], - ['leave', 'Field', None, 'Human', 'String', None], - ['enter', 'Field', None, 'Human', '[Pet]', None], - ['enter', 'Name', 'pets', 'Human', '[Pet]', None], - ['leave', 'Name', 'pets', 'Human', '[Pet]', None], - ['enter', 'SelectionSet', None, 'Pet', '[Pet]', None], - ['enter', 'Field', None, 'Pet', 'String!', None], - ['enter', 'Name', '__typename', 'Pet', 'String!', None], - ['leave', 'Name', '__typename', 'Pet', 'String!', None], - ['leave', 'Field', None, 'Pet', 'String!', None], - ['leave', 'SelectionSet', None, 'Pet', '[Pet]', None], - ['leave', 'Field', None, 'Human', '[Pet]', None], - ['leave', 'SelectionSet', None, 'Human', 'Human', None], - ['leave', 'Field', None, 'QueryRoot', 'Human', None], - ['enter', 'Field', None, 'QueryRoot', 'Alien', None], - ['enter', 'Name', 'alien', 'QueryRoot', 'Alien', None], - ['leave', 'Name', 'alien', 'QueryRoot', 'Alien', None], - ['enter', 'SelectionSet', None, 'Alien', 'Alien', None], - ['enter', 'Field', None, 'Alien', 'String!', None], - ['enter', 'Name', '__typename', 'Alien', 'String!', None], - ['leave', 'Name', '__typename', 'Alien', 'String!', None], - ['leave', 'Field', None, 'Alien', 'String!', None], - ['leave', 'SelectionSet', None, 'Alien', 'Alien', None], - ['leave', 'Field', None, 'QueryRoot', 'Alien', None], - ['leave', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None], - ['leave', 'OperationDefinition', None, None, 'QueryRoot', None], - ['leave', 'Document', None, None, None, None] + ["enter", "Document", None, None, None, None], + ["enter", "OperationDefinition", None, None, "QueryRoot", None], + ["enter", "SelectionSet", None, "QueryRoot", "QueryRoot", None], + ["enter", "Field", None, "QueryRoot", "Human", None], + ["enter", "Name", "human", "QueryRoot", "Human", None], + ["leave", "Name", "human", "QueryRoot", "Human", None], + ["enter", "Argument", None, "QueryRoot", "Human", "ID"], + ["enter", "Name", "id", "QueryRoot", "Human", "ID"], + ["leave", "Name", "id", "QueryRoot", "Human", "ID"], + ["enter", "IntValue", None, "QueryRoot", "Human", "ID"], + ["leave", "IntValue", None, "QueryRoot", "Human", "ID"], + ["leave", "Argument", None, "QueryRoot", "Human", "ID"], + ["enter", "SelectionSet", None, "Human", "Human", None], + ["enter", "Field", None, "Human", "String", None], + ["enter", "Name", "name", "Human", "String", None], + ["leave", "Name", "name", "Human", "String", None], + ["leave", "Field", None, "Human", "String", None], + ["enter", "Field", None, "Human", "[Pet]", None], + ["enter", "Name", "pets", "Human", "[Pet]", None], + ["leave", "Name", "pets", "Human", "[Pet]", None], + ["enter", "SelectionSet", None, "Pet", "[Pet]", None], + ["enter", "Field", None, "Pet", "String!", None], + ["enter", "Name", "__typename", "Pet", "String!", None], + ["leave", "Name", "__typename", "Pet", "String!", None], + ["leave", "Field", None, "Pet", "String!", None], + ["leave", "SelectionSet", None, "Pet", "[Pet]", None], + ["leave", "Field", None, "Human", "[Pet]", None], + ["leave", "SelectionSet", None, "Human", "Human", None], + ["leave", "Field", None, "QueryRoot", "Human", None], + ["enter", "Field", None, "QueryRoot", "Alien", None], + ["enter", "Name", "alien", "QueryRoot", "Alien", None], + ["leave", "Name", "alien", "QueryRoot", "Alien", None], + ["enter", "SelectionSet", None, "Alien", "Alien", None], + ["enter", "Field", None, "Alien", "String!", None], + ["enter", "Name", "__typename", "Alien", "String!", None], + ["leave", "Name", "__typename", "Alien", "String!", None], + ["leave", "Field", None, "Alien", "String!", None], + ["leave", "SelectionSet", None, "Alien", "Alien", None], + ["leave", "Field", None, "QueryRoot", "Alien", None], + ["leave", "SelectionSet", None, "QueryRoot", "QueryRoot", None], + ["leave", "OperationDefinition", None, None, "QueryRoot", None], + ["leave", "Document", None, None, None, None], ] diff --git a/graphql/language/tests/test_visitor_meta.py b/graphql/language/tests/test_visitor_meta.py index 19890ad3..d40bb47a 100644 --- a/graphql/language/tests/test_visitor_meta.py +++ b/graphql/language/tests/test_visitor_meta.py @@ -5,7 +5,6 @@ def test_visitor_meta_creates_enter_and_leave_handlers(): # type: () -> None class MyVisitor(Visitor): - def enter_OperationDefinition(self): pass @@ -19,7 +18,6 @@ def leave_OperationDefinition(self): def test_visitor_inherits_parent_definitions(): # type: () -> None class MyVisitor(Visitor): - def enter_OperationDefinition(self): pass @@ -30,7 +28,6 @@ def leave_OperationDefinition(self): assert MyVisitor._get_leave_handler(ast.OperationDefinition) class MyVisitorSubclassed(MyVisitor): - def enter_FragmentDefinition(self): pass diff --git a/graphql/language/visitor_meta.py b/graphql/language/visitor_meta.py index db2e6409..37372c48 100644 --- a/graphql/language/visitor_meta.py +++ b/graphql/language/visitor_meta.py @@ -2,81 +2,76 @@ QUERY_DOCUMENT_KEYS = { ast.Name: (), - - ast.Document: ('definitions',), - ast.OperationDefinition: ('name', 'variable_definitions', 'directives', 'selection_set'), - ast.VariableDefinition: ('variable', 'type', 'default_value'), - ast.Variable: ('name',), - ast.SelectionSet: ('selections',), - ast.Field: ('alias', 'name', 'arguments', 'directives', 'selection_set'), - ast.Argument: ('name', 'value'), - - ast.FragmentSpread: ('name', 'directives'), - ast.InlineFragment: ('type_condition', 'directives', 'selection_set'), - ast.FragmentDefinition: ('name', 'type_condition', 'directives', 'selection_set'), - + ast.Document: ("definitions",), + ast.OperationDefinition: ( + "name", + "variable_definitions", + "directives", + "selection_set", + ), + ast.VariableDefinition: ("variable", "type", "default_value"), + ast.Variable: ("name",), + ast.SelectionSet: ("selections",), + ast.Field: ("alias", "name", "arguments", "directives", "selection_set"), + ast.Argument: ("name", "value"), + ast.FragmentSpread: ("name", "directives"), + ast.InlineFragment: ("type_condition", "directives", "selection_set"), + ast.FragmentDefinition: ("name", "type_condition", "directives", "selection_set"), ast.IntValue: (), ast.FloatValue: (), ast.StringValue: (), ast.BooleanValue: (), ast.EnumValue: (), - ast.ListValue: ('values',), - ast.ObjectValue: ('fields',), - ast.ObjectField: ('name', 'value'), - - ast.Directive: ('name', 'arguments'), - - ast.NamedType: ('name',), - ast.ListType: ('type',), - ast.NonNullType: ('type',), - - ast.SchemaDefinition: ('directives', 'operation_types',), - ast.OperationTypeDefinition: ('type',), - - ast.ScalarTypeDefinition: ('name', 'directives',), - ast.ObjectTypeDefinition: ('name', 'interfaces', 'directives', 'fields'), - ast.FieldDefinition: ('name', 'arguments', 'directives', 'type'), - ast.InputValueDefinition: ('name', 'type', 'directives', 'default_value'), - ast.InterfaceTypeDefinition: ('name', 'directives', 'fields'), - ast.UnionTypeDefinition: ('name', 'directives', 'types'), - ast.EnumTypeDefinition: ('name', 'directives', 'values'), - ast.EnumValueDefinition: ('name', 'directives',), - ast.InputObjectTypeDefinition: ('name', 'directives', 'fields'), - - ast.TypeExtensionDefinition: ('definition',), - - ast.DirectiveDefinition: ('name', 'arguments', 'locations'), + ast.ListValue: ("values",), + ast.ObjectValue: ("fields",), + ast.ObjectField: ("name", "value"), + ast.Directive: ("name", "arguments"), + ast.NamedType: ("name",), + ast.ListType: ("type",), + ast.NonNullType: ("type",), + ast.SchemaDefinition: ("directives", "operation_types"), + ast.OperationTypeDefinition: ("type",), + ast.ScalarTypeDefinition: ("name", "directives"), + ast.ObjectTypeDefinition: ("name", "interfaces", "directives", "fields"), + ast.FieldDefinition: ("name", "arguments", "directives", "type"), + ast.InputValueDefinition: ("name", "type", "directives", "default_value"), + ast.InterfaceTypeDefinition: ("name", "directives", "fields"), + ast.UnionTypeDefinition: ("name", "directives", "types"), + ast.EnumTypeDefinition: ("name", "directives", "values"), + ast.EnumValueDefinition: ("name", "directives"), + ast.InputObjectTypeDefinition: ("name", "directives", "fields"), + ast.TypeExtensionDefinition: ("definition",), + ast.DirectiveDefinition: ("name", "arguments", "locations"), } AST_KIND_TO_TYPE = {c.__name__: c for c in QUERY_DOCUMENT_KEYS.keys()} class VisitorMeta(type): - def __new__(cls, name, bases, attrs): enter_handlers = {} leave_handlers = {} for base in bases: - if hasattr(base, '_enter_handlers'): + if hasattr(base, "_enter_handlers"): enter_handlers.update(base._enter_handlers) - if hasattr(base, '_leave_handlers'): + if hasattr(base, "_leave_handlers"): leave_handlers.update(base._leave_handlers) for attr, val in attrs.items(): - if attr.startswith('enter_'): + if attr.startswith("enter_"): ast_kind = attr[6:] ast_type = AST_KIND_TO_TYPE.get(ast_kind) enter_handlers[ast_type] = val - elif attr.startswith('leave_'): + elif attr.startswith("leave_"): ast_kind = attr[6:] ast_type = AST_KIND_TO_TYPE.get(ast_kind) leave_handlers[ast_type] = val - attrs['_enter_handlers'] = enter_handlers - attrs['_leave_handlers'] = leave_handlers - attrs['_get_enter_handler'] = enter_handlers.get - attrs['_get_leave_handler'] = leave_handlers.get + attrs["_enter_handlers"] = enter_handlers + attrs["_leave_handlers"] = leave_handlers + attrs["_get_enter_handler"] = enter_handlers.get + attrs["_get_leave_handler"] = leave_handlers.get return super(VisitorMeta, cls).__new__(cls, name, bases, attrs) diff --git a/graphql/pyutils/ordereddict.py b/graphql/pyutils/ordereddict.py index 29633537..5a6b2b69 100644 --- a/graphql/pyutils/ordereddict.py +++ b/graphql/pyutils/ordereddict.py @@ -5,4 +5,4 @@ except ImportError: from collections import OrderedDict -__all__ = ['OrderedDict'] +__all__ = ["OrderedDict"] diff --git a/graphql/pyutils/tests/test_default_ordered_dict.py b/graphql/pyutils/tests/test_default_ordered_dict.py index f1069137..0a87a8dd 100644 --- a/graphql/pyutils/tests/test_default_ordered_dict.py +++ b/graphql/pyutils/tests/test_default_ordered_dict.py @@ -8,19 +8,19 @@ def test_will_missing_will_set_value_from_factory(): d = DefaultOrderedDict(list) - f = d['foo'] + f = d["foo"] assert isinstance(f, list) - assert d['foo'] is f + assert d["foo"] is f def test_preserves_input_order(): d = DefaultOrderedDict(list) - d['a'].append(1) - d['b'].append(2) - d['c'].append(3) - d['a'].append(4) + d["a"].append(1) + d["b"].append(2) + d["c"].append(3) + d["a"].append(4) - assert list(d.keys()) == ['a', 'b', 'c'] + assert list(d.keys()) == ["a", "b", "c"] assert list(d.values()) == [[1, 4], [2], [3]] @@ -28,31 +28,31 @@ def test_will_act_list_default_dict_if_no_factory_defined(): d = DefaultOrderedDict() with raises(KeyError) as excinfo: - assert d['test'] + assert d["test"] assert str(excinfo.value) == "'test'" def test_will_repr_properly(): - d = DefaultOrderedDict(list, [('a', 1), ('b', 2)]) + d = DefaultOrderedDict(list, [("a", 1), ("b", 2)]) assert repr(d) == "DefaultOrderedDict({}, [('a', 1), ('b', 2)])".format(list) def test_requires_callable_default_factory(): with raises(TypeError) as excinfo: - DefaultOrderedDict('not callable') + DefaultOrderedDict("not callable") - assert str(excinfo.value) == 'first argument must be callable' + assert str(excinfo.value) == "first argument must be callable" def test_picklable(): - d = DefaultOrderedDict(list, [('a', 1), ('b', 2)]) + d = DefaultOrderedDict(list, [("a", 1), ("b", 2)]) d_copied = pickle.loads(pickle.dumps(d)) assert d_copied == d assert d.default_factory == d_copied.default_factory - d = DefaultOrderedDict(None, [('a', 1), ('b', 2)]) + d = DefaultOrderedDict(None, [("a", 1), ("b", 2)]) d_copied = pickle.loads(pickle.dumps(d)) assert d_copied == d @@ -60,29 +60,29 @@ def test_picklable(): def test_copy(): - d = DefaultOrderedDict(list, [('a', [1, 2]), ('b', [3, 4])]) + d = DefaultOrderedDict(list, [("a", [1, 2]), ("b", [3, 4])]) d_copied = copy.copy(d) assert d_copied == d assert d.default_factory == d_copied.default_factory - assert d_copied['a'] is d['a'] - assert d_copied['b'] is d['b'] + assert d_copied["a"] is d["a"] + assert d_copied["b"] is d["b"] d_copied = d.copy() assert d_copied == d assert d.default_factory == d_copied.default_factory - assert d_copied['a'] is d['a'] - assert d_copied['b'] is d['b'] + assert d_copied["a"] is d["a"] + assert d_copied["b"] is d["b"] def test_deep_copy(): - d = DefaultOrderedDict(list, [('a', [1, 2]), ('b', [3, 4])]) + d = DefaultOrderedDict(list, [("a", [1, 2]), ("b", [3, 4])]) d_copied = copy.deepcopy(d) assert d_copied == d assert d.default_factory == d_copied.default_factory - assert d_copied['a'] == d['a'] - assert d_copied['a'] is not d['a'] - assert d_copied['b'] == d['b'] - assert d_copied['b'] is not d['b'] + assert d_copied["a"] == d["a"] + assert d_copied["a"] is not d["a"] + assert d_copied["b"] == d["b"] + assert d_copied["b"] is not d["b"] diff --git a/graphql/pyutils/version.py b/graphql/pyutils/version.py index a8dd7354..dc971265 100644 --- a/graphql/pyutils/version.py +++ b/graphql/pyutils/version.py @@ -16,15 +16,15 @@ def get_version(version=None): main = get_main_version(version) - sub = '' - if version[3] == 'alpha' and version[4] == 0: + sub = "" + if version[3] == "alpha" and version[4] == 0: git_changeset = get_git_changeset() if git_changeset: - sub = '.dev%s' % git_changeset + sub = ".dev%s" % git_changeset else: - sub = '.dev' - elif version[3] != 'final': - mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'rc'} + sub = ".dev" + elif version[3] != "final": + mapping = {"alpha": "a", "beta": "b", "rc": "rc"} sub = mapping[version[3]] + str(version[4]) return str(main + sub) @@ -34,7 +34,7 @@ def get_main_version(version=None): "Returns main version (X.Y[.Z]) from VERSION." version = get_complete_version(version) parts = 2 if version[2] == 0 else 3 - return '.'.join(str(x) for x in version[:parts]) + return ".".join(str(x) for x in version[:parts]) def get_complete_version(version=None): @@ -45,17 +45,17 @@ def get_complete_version(version=None): from graphql import VERSION as version else: assert len(version) == 5 - assert version[3] in ('alpha', 'beta', 'rc', 'final') + assert version[3] in ("alpha", "beta", "rc", "final") return version def get_docs_version(version=None): version = get_complete_version(version) - if version[3] != 'final': - return 'dev' + if version[3] != "final": + return "dev" else: - return '%d.%d' % version[:2] + return "%d.%d" % version[:2] def get_git_changeset(): @@ -67,12 +67,15 @@ def get_git_changeset(): repo_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) try: git_log = subprocess.Popen( - 'git log --pretty=format:%ct --quiet -1 HEAD', - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=True, cwd=repo_dir, universal_newlines=True, + "git log --pretty=format:%ct --quiet -1 HEAD", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True, + cwd=repo_dir, + universal_newlines=True, ) timestamp = git_log.communicate()[0] timestamp = datetime.datetime.utcfromtimestamp(int(timestamp)) except Exception: return None - return timestamp.strftime('%Y%m%d%H%M%S') + return timestamp.strftime("%Y%m%d%H%M%S") diff --git a/graphql/type/__init__.py b/graphql/type/__init__.py index 153c1b5e..41a11115 100644 --- a/graphql/type/__init__.py +++ b/graphql/type/__init__.py @@ -19,21 +19,18 @@ is_leaf_type, is_type, get_nullable_type, - is_output_type + is_output_type, ) from .directives import ( # "Enum" of Directive locations DirectiveLocation, - # Directive definition GraphQLDirective, - # Built-in directives defined by the Spec specified_directives, GraphQLSkipDirective, GraphQLIncludeDirective, GraphQLDeprecatedDirective, - # Constant Deprecation Reason DEFAULT_DEPRECATION_REASON, ) @@ -49,7 +46,6 @@ from .introspection import ( # "Enum" of Type Kinds TypeKind, - # GraphQL Types for introspection. __Schema, __Directive, @@ -59,9 +55,8 @@ __InputValue, __EnumValue, __TypeKind, - # Meta-field definitions. SchemaMetaFieldDef, TypeMetaFieldDef, - TypeNameMetaFieldDef + TypeNameMetaFieldDef, ) diff --git a/graphql/type/definition.py b/graphql/type/definition.py index ecb4f4ed..ec23d3dc 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -763,4 +763,3 @@ def is_same_type(self, other): return isinstance(other, GraphQLNonNull) and self.of_type.is_same_type( other.of_type ) - diff --git a/graphql/type/directives.py b/graphql/type/directives.py index 06c920de..ef7417c4 100644 --- a/graphql/type/directives.py +++ b/graphql/type/directives.py @@ -8,125 +8,117 @@ class DirectiveLocation(object): # Operations - QUERY = 'QUERY' - MUTATION = 'MUTATION' - SUBSCRIPTION = 'SUBSCRIPTION' - FIELD = 'FIELD' - FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION' - FRAGMENT_SPREAD = 'FRAGMENT_SPREAD' - INLINE_FRAGMENT = 'INLINE_FRAGMENT' + QUERY = "QUERY" + MUTATION = "MUTATION" + SUBSCRIPTION = "SUBSCRIPTION" + FIELD = "FIELD" + FRAGMENT_DEFINITION = "FRAGMENT_DEFINITION" + FRAGMENT_SPREAD = "FRAGMENT_SPREAD" + INLINE_FRAGMENT = "INLINE_FRAGMENT" # Schema Definitions - SCHEMA = 'SCHEMA' - SCALAR = 'SCALAR' - OBJECT = 'OBJECT' - FIELD_DEFINITION = 'FIELD_DEFINITION' - ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION' - INTERFACE = 'INTERFACE' - UNION = 'UNION' - ENUM = 'ENUM' - ENUM_VALUE = 'ENUM_VALUE' - INPUT_OBJECT = 'INPUT_OBJECT' - INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION' - - OPERATION_LOCATIONS = [ - QUERY, - MUTATION, - SUBSCRIPTION - ] - - FRAGMENT_LOCATIONS = [ - FRAGMENT_DEFINITION, - FRAGMENT_SPREAD, - INLINE_FRAGMENT - ] - - FIELD_LOCATIONS = [ - FIELD - ] + SCHEMA = "SCHEMA" + SCALAR = "SCALAR" + OBJECT = "OBJECT" + FIELD_DEFINITION = "FIELD_DEFINITION" + ARGUMENT_DEFINITION = "ARGUMENT_DEFINITION" + INTERFACE = "INTERFACE" + UNION = "UNION" + ENUM = "ENUM" + ENUM_VALUE = "ENUM_VALUE" + INPUT_OBJECT = "INPUT_OBJECT" + INPUT_FIELD_DEFINITION = "INPUT_FIELD_DEFINITION" + + OPERATION_LOCATIONS = [QUERY, MUTATION, SUBSCRIPTION] + + FRAGMENT_LOCATIONS = [FRAGMENT_DEFINITION, FRAGMENT_SPREAD, INLINE_FRAGMENT] + + FIELD_LOCATIONS = [FIELD] class GraphQLDirective(object): - __slots__ = 'name', 'args', 'description', 'locations' + __slots__ = "name", "args", "description", "locations" def __init__(self, name, description=None, args=None, locations=None): - assert name, 'Directive must be named.' + assert name, "Directive must be named." assert_valid_name(name) - assert isinstance(locations, collections.Iterable), 'Must provide locations for directive.' + assert isinstance( + locations, collections.Iterable + ), "Must provide locations for directive." self.name = name self.description = description self.locations = locations if args: - assert isinstance(args, collections.Mapping), '{} args must be a dict with argument names as keys.'.format(name) + assert isinstance( + args, collections.Mapping + ), "{} args must be a dict with argument names as keys.".format(name) for arg_name, _arg in args.items(): assert_valid_name(arg_name) - assert is_input_type(_arg.type), '{}({}) argument type must be Input Type but got {}.'.format( - name, - arg_name, - _arg.type) + assert is_input_type( + _arg.type + ), "{}({}) argument type must be Input Type but got {}.".format( + name, arg_name, _arg.type + ) self.args = args or OrderedDict() """Used to conditionally include fields or fragments.""" GraphQLIncludeDirective = GraphQLDirective( - name='include', - description='Directs the executor to include this field or fragment only when the `if` argument is true.', + name="include", + description="Directs the executor to include this field or fragment only when the `if` argument is true.", args={ - 'if': GraphQLArgument( - type=GraphQLNonNull(GraphQLBoolean), - description='Included when true.', - ), + "if": GraphQLArgument( + type=GraphQLNonNull(GraphQLBoolean), description="Included when true." + ) }, locations=[ DirectiveLocation.FIELD, DirectiveLocation.FRAGMENT_SPREAD, DirectiveLocation.INLINE_FRAGMENT, - ] + ], ) """Used to conditionally skip (exclude) fields or fragments.""" GraphQLSkipDirective = GraphQLDirective( - name='skip', - description='Directs the executor to skip this field or fragment when the `if` argument is true.', + name="skip", + description="Directs the executor to skip this field or fragment when the `if` argument is true.", args={ - 'if': GraphQLArgument( - type=GraphQLNonNull(GraphQLBoolean), - description='Skipped when true.', - ), + "if": GraphQLArgument( + type=GraphQLNonNull(GraphQLBoolean), description="Skipped when true." + ) }, locations=[ DirectiveLocation.FIELD, DirectiveLocation.FRAGMENT_SPREAD, DirectiveLocation.INLINE_FRAGMENT, - ] + ], ) """Constant string used for default reason for a deprecation.""" -DEFAULT_DEPRECATION_REASON = 'No longer supported' +DEFAULT_DEPRECATION_REASON = "No longer supported" """Used to declare element of a GraphQL schema as deprecated.""" GraphQLDeprecatedDirective = GraphQLDirective( - name='deprecated', - description='Marks an element of a GraphQL schema as no longer supported.', + name="deprecated", + description="Marks an element of a GraphQL schema as no longer supported.", args={ - 'reason': GraphQLArgument( + "reason": GraphQLArgument( type=GraphQLString, - description=('Explains why this element was deprecated, usually also including a suggestion for how to' - 'access supported similar data. Formatted in [Markdown]' - '(https://daringfireball.net/projects/markdown/).'), - default_value=DEFAULT_DEPRECATION_REASON - ), + description=( + "Explains why this element was deprecated, usually also including a suggestion for how to" + "access supported similar data. Formatted in [Markdown]" + "(https://daringfireball.net/projects/markdown/)." + ), + default_value=DEFAULT_DEPRECATION_REASON, + ) }, - locations=[ - DirectiveLocation.FIELD_DEFINITION, - DirectiveLocation.ENUM_VALUE, - ] + locations=[DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.ENUM_VALUE], ) specified_directives = [ GraphQLIncludeDirective, GraphQLSkipDirective, - GraphQLDeprecatedDirective + GraphQLDeprecatedDirective, ] diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index 4a18d785..c80170e1 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -657,4 +657,3 @@ def input_fields( resolver=lambda source, info, **args: info.parent_type.name, args={}, ) - diff --git a/graphql/type/scalars.py b/graphql/type/scalars.py index ce07ee3a..4578023c 100644 --- a/graphql/type/scalars.py +++ b/graphql/type/scalars.py @@ -2,6 +2,7 @@ from ..language.ast import BooleanValue, FloatValue, IntValue, StringValue from .definition import GraphQLScalarType + if False: from typing import Any, Optional, Union @@ -26,9 +27,9 @@ def coerce_int(value): if MIN_INT <= num <= MAX_INT: return num - raise Exception(( - "Int cannot represent non 32-bit signed integer value: {}" - ).format(value)) + raise Exception( + ("Int cannot represent non 32-bit signed integer value: {}").format(value) + ) def parse_int_literal(ast): @@ -41,14 +42,15 @@ def parse_int_literal(ast): GraphQLInt = GraphQLScalarType( - name='Int', - description='The `Int` scalar type represents non-fractional signed whole numeric ' - 'values. Int can represent values between -(2^31 - 1) and 2^31 - 1 since ' - 'represented in JSON as double-precision floating point numbers specified' - 'by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).', + name="Int", + description="The `Int` scalar type represents non-fractional signed whole numeric " + "values. Int can represent values between -(2^31 - 1) and 2^31 - 1 since " + "represented in JSON as double-precision floating point numbers specified" + "by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).", serialize=coerce_int, parse_value=coerce_int, - parse_literal=parse_int_literal) + parse_literal=parse_int_literal, +) def coerce_float(value): @@ -66,13 +68,14 @@ def parse_float_literal(ast): GraphQLFloat = GraphQLScalarType( - name='Float', - description='The `Float` scalar type represents signed double-precision fractional ' - 'values as specified by ' - '[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ', + name="Float", + description="The `Float` scalar type represents signed double-precision fractional " + "values as specified by " + "[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", serialize=coerce_float, parse_value=coerce_float, - parse_literal=parse_float_literal) + parse_literal=parse_float_literal, +) def coerce_string(value): @@ -81,7 +84,7 @@ def coerce_string(value): return value if isinstance(value, bool): - return u'true' if value else u'false' + return u"true" if value else u"false" return text_type(value) @@ -103,13 +106,14 @@ def parse_string_literal(ast): GraphQLString = GraphQLScalarType( - name='String', - description='The `String` scalar type represents textual data, represented as UTF-8 ' - 'character sequences. The String type is most often used by GraphQL to ' - 'represent free-form human-readable text.', + name="String", + description="The `String` scalar type represents textual data, represented as UTF-8 " + "character sequences. The String type is most often used by GraphQL to " + "represent free-form human-readable text.", serialize=coerce_string, parse_value=coerce_string, - parse_literal=parse_string_literal) + parse_literal=parse_string_literal, +) def parse_boolean_literal(ast): @@ -120,11 +124,12 @@ def parse_boolean_literal(ast): GraphQLBoolean = GraphQLScalarType( - name='Boolean', - description='The `Boolean` scalar type represents `true` or `false`.', + name="Boolean", + description="The `Boolean` scalar type represents `true` or `false`.", serialize=bool, parse_value=bool, - parse_literal=parse_boolean_literal) + parse_literal=parse_boolean_literal, +) def parse_id_literal(ast): @@ -135,12 +140,13 @@ def parse_id_literal(ast): GraphQLID = GraphQLScalarType( - name='ID', - description='The `ID` scalar type represents a unique identifier, often used to ' - 'refetch an object or as key for a cache. The ID type appears in a JSON ' - 'response as a String; however, it is not intended to be human-readable. ' - 'When expected as an input type, any string (such as `"4"`) or integer ' - '(such as `4`) input value will be accepted as an ID.', + name="ID", + description="The `ID` scalar type represents a unique identifier, often used to " + "refetch an object or as key for a cache. The ID type appears in a JSON " + "response as a String; however, it is not intended to be human-readable. " + 'When expected as an input type, any string (such as `"4"`) or integer ' + "(such as `4`) input value will be accepted as an ID.", serialize=coerce_str, parse_value=coerce_str, - parse_literal=parse_id_literal) + parse_literal=parse_id_literal, +) diff --git a/graphql/type/tests/test_definition.py b/graphql/type/tests/test_definition.py index 659ecfd4..0281a83f 100644 --- a/graphql/type/tests/test_definition.py +++ b/graphql/type/tests/test_definition.py @@ -2,65 +2,89 @@ from py.test import raises -from graphql.type import (GraphQLArgument, GraphQLBoolean, GraphQLEnumType, - GraphQLEnumValue, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInt, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLSchema, - GraphQLString, GraphQLUnionType) +from graphql.type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) from graphql.type.definition import is_input_type, is_output_type -BlogImage = GraphQLObjectType('Image', { - 'url': GraphQLField(GraphQLString), - 'width': GraphQLField(GraphQLInt), - 'height': GraphQLField(GraphQLInt), -}) - -BlogAuthor = GraphQLObjectType('Author', lambda: { - 'id': GraphQLField(GraphQLString), - 'name': GraphQLField(GraphQLString), - 'pic': GraphQLField( - BlogImage, - args={ - 'width': GraphQLArgument(GraphQLInt), - 'height': GraphQLArgument(GraphQLInt), - }), - 'recentArticle': GraphQLField(BlogArticle) -}) - -BlogArticle = GraphQLObjectType('Article', lambda: { - 'id': GraphQLField(GraphQLString), - 'isPublished': GraphQLField(GraphQLBoolean), - 'author': GraphQLField(BlogAuthor), - 'title': GraphQLField(GraphQLString), - 'body': GraphQLField(GraphQLString), -}) - -BlogQuery = GraphQLObjectType('Query', { - 'article': GraphQLField( - BlogArticle, - args={ - 'id': GraphQLArgument(GraphQLString), - }), - 'feed': GraphQLField(GraphQLList(BlogArticle)) -}) - -BlogMutation = GraphQLObjectType('Mutation', { - 'writeArticle': GraphQLField(BlogArticle) -}) - -BlogSubscription = GraphQLObjectType('Subscription', { - 'articleSubscribe': GraphQLField( - args={'id': GraphQLArgument(GraphQLString)}, - type=BlogArticle - ) -}) - -ObjectType = GraphQLObjectType('Object', {}) -InterfaceType = GraphQLInterfaceType('Interface') -UnionType = GraphQLUnionType('Union', [ObjectType], resolve_type=lambda: None) -EnumType = GraphQLEnumType('Enum', {'foo': GraphQLEnumValue()}) -InputObjectType = GraphQLInputObjectType('InputObject', {}) +BlogImage = GraphQLObjectType( + "Image", + { + "url": GraphQLField(GraphQLString), + "width": GraphQLField(GraphQLInt), + "height": GraphQLField(GraphQLInt), + }, +) + +BlogAuthor = GraphQLObjectType( + "Author", + lambda: { + "id": GraphQLField(GraphQLString), + "name": GraphQLField(GraphQLString), + "pic": GraphQLField( + BlogImage, + args={ + "width": GraphQLArgument(GraphQLInt), + "height": GraphQLArgument(GraphQLInt), + }, + ), + "recentArticle": GraphQLField(BlogArticle), + }, +) + +BlogArticle = GraphQLObjectType( + "Article", + lambda: { + "id": GraphQLField(GraphQLString), + "isPublished": GraphQLField(GraphQLBoolean), + "author": GraphQLField(BlogAuthor), + "title": GraphQLField(GraphQLString), + "body": GraphQLField(GraphQLString), + }, +) + +BlogQuery = GraphQLObjectType( + "Query", + { + "article": GraphQLField( + BlogArticle, args={"id": GraphQLArgument(GraphQLString)} + ), + "feed": GraphQLField(GraphQLList(BlogArticle)), + }, +) + +BlogMutation = GraphQLObjectType( + "Mutation", {"writeArticle": GraphQLField(BlogArticle)} +) + +BlogSubscription = GraphQLObjectType( + "Subscription", + { + "articleSubscribe": GraphQLField( + args={"id": GraphQLArgument(GraphQLString)}, type=BlogArticle + ) + }, +) + +ObjectType = GraphQLObjectType("Object", {}) +InterfaceType = GraphQLInterfaceType("Interface") +UnionType = GraphQLUnionType("Union", [ObjectType], resolve_type=lambda: None) +EnumType = GraphQLEnumType("Enum", {"foo": GraphQLEnumValue()}) +InputObjectType = GraphQLInputObjectType("InputObject", {}) def test_defines_a_query_only_schema(): @@ -68,27 +92,27 @@ def test_defines_a_query_only_schema(): assert BlogSchema.get_query_type() == BlogQuery - article_field = BlogQuery.fields['article'] + article_field = BlogQuery.fields["article"] assert article_field.type == BlogArticle - assert article_field.type.name == 'Article' + assert article_field.type.name == "Article" # assert article_field.name == 'article' article_field_type = article_field.type assert isinstance(article_field_type, GraphQLObjectType) - title_field = article_field_type.fields['title'] + title_field = article_field_type.fields["title"] # assert title_field.name == 'title' assert title_field.type == GraphQLString - assert title_field.type.name == 'String' + assert title_field.type.name == "String" - author_field = article_field_type.fields['author'] + author_field = article_field_type.fields["author"] author_field_type = author_field.type assert isinstance(author_field_type, GraphQLObjectType) - recent_article_field = author_field_type.fields['recentArticle'] + recent_article_field = author_field_type.fields["recentArticle"] assert recent_article_field.type == BlogArticle - feed_field = BlogQuery.fields['feed'] + feed_field = BlogQuery.fields["feed"] assert feed_field.type.of_type == BlogArticle # assert feed_field.name == 'feed' @@ -98,63 +122,63 @@ def test_defines_a_mutation_schema(): assert BlogSchema.get_mutation_type() == BlogMutation - write_mutation = BlogMutation.fields['writeArticle'] + write_mutation = BlogMutation.fields["writeArticle"] assert write_mutation.type == BlogArticle - assert write_mutation.type.name == 'Article' + assert write_mutation.type.name == "Article" # assert write_mutation.name == 'writeArticle' def test_defines_a_subscription_schema(): - BlogSchema = GraphQLSchema( - query=BlogQuery, - subscription=BlogSubscription - ) + BlogSchema = GraphQLSchema(query=BlogQuery, subscription=BlogSubscription) assert BlogSchema.get_subscription_type() == BlogSubscription - subscription = BlogSubscription.fields['articleSubscribe'] + subscription = BlogSubscription.fields["articleSubscribe"] assert subscription.type == BlogArticle - assert subscription.type.name == 'Article' + assert subscription.type.name == "Article" # assert subscription.name == 'articleSubscribe' def test_defines_an_enum_type_with_deprecated_value(): - EnumTypeWithDeprecatedValue = GraphQLEnumType('EnumWithDeprecatedValue', { - 'foo': GraphQLEnumValue(deprecation_reason='Just because'), - }) + EnumTypeWithDeprecatedValue = GraphQLEnumType( + "EnumWithDeprecatedValue", + {"foo": GraphQLEnumValue(deprecation_reason="Just because")}, + ) value = EnumTypeWithDeprecatedValue.get_values()[0] - assert value.name == 'foo' + assert value.name == "foo" assert value.description is None assert value.is_deprecated is True - assert value.deprecation_reason == 'Just because' - assert value.value == 'foo' + assert value.deprecation_reason == "Just because" + assert value.value == "foo" def test_defines_an_enum_type_with_a_value_of_none(): - EnumTypeWithNoneValue = GraphQLEnumType('EnumWithNullishValue', { - 'NULL': GraphQLEnumValue(None), - }) + EnumTypeWithNoneValue = GraphQLEnumType( + "EnumWithNullishValue", {"NULL": GraphQLEnumValue(None)} + ) value = EnumTypeWithNoneValue.get_values()[0] - assert value.name == 'NULL' + assert value.name == "NULL" assert value.description is None assert value.is_deprecated is False assert value.deprecation_reason is None assert value.value is None - + def test_defines_an_object_type_with_deprecated_field(): - TypeWithDeprecatedField = GraphQLObjectType('foo', fields={ - 'bar': GraphQLField( - type=GraphQLString, - deprecation_reason='A terrible reason' - ), - }) + TypeWithDeprecatedField = GraphQLObjectType( + "foo", + fields={ + "bar": GraphQLField( + type=GraphQLString, deprecation_reason="A terrible reason" + ) + }, + ) - field = TypeWithDeprecatedField.fields['bar'] + field = TypeWithDeprecatedField.fields["bar"] assert field.type == GraphQLString assert field.description is None - assert field.deprecation_reason == 'A terrible reason' + assert field.deprecation_reason == "A terrible reason" assert field.is_deprecated is True # assert field.name == 'bar' assert field.args == OrderedDict() @@ -162,103 +186,92 @@ def test_defines_an_object_type_with_deprecated_field(): def test_includes_nested_input_objects_in_the_map(): NestedInputObject = GraphQLInputObjectType( - name='NestedInputObject', - fields={'value': GraphQLInputObjectField(GraphQLString)} + name="NestedInputObject", + fields={"value": GraphQLInputObjectField(GraphQLString)}, ) SomeInputObject = GraphQLInputObjectType( - name='SomeInputObject', - fields={'nested': GraphQLInputObjectField(NestedInputObject)} + name="SomeInputObject", + fields={"nested": GraphQLInputObjectField(NestedInputObject)}, ) SomeMutation = GraphQLObjectType( - name='SomeMutation', + name="SomeMutation", fields={ - 'mutateSomething': GraphQLField( - type=BlogArticle, - args={ - 'input': GraphQLArgument(SomeInputObject) - } + "mutateSomething": GraphQLField( + type=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} ) - } + }, ) SomeSubscription = GraphQLObjectType( - name='SomeSubscription', + name="SomeSubscription", fields={ - 'subscribeToSomething': GraphQLField( - type=BlogArticle, - args={ - 'input': GraphQLArgument(SomeInputObject) - } + "subscribeToSomething": GraphQLField( + type=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} ) - } + }, ) schema = GraphQLSchema( - query=BlogQuery, - mutation=SomeMutation, - subscription=SomeSubscription + query=BlogQuery, mutation=SomeMutation, subscription=SomeSubscription ) - assert schema.get_type_map()['NestedInputObject'] is NestedInputObject + assert schema.get_type_map()["NestedInputObject"] is NestedInputObject def test_includes_interface_possible_types_in_the_type_map(): - SomeInterface = GraphQLInterfaceType('SomeInterface', fields={'f': GraphQLField(GraphQLInt)}) + SomeInterface = GraphQLInterfaceType( + "SomeInterface", fields={"f": GraphQLField(GraphQLInt)} + ) SomeSubtype = GraphQLObjectType( - name='SomeSubtype', - fields={'f': GraphQLField(GraphQLInt)}, + name="SomeSubtype", + fields={"f": GraphQLField(GraphQLInt)}, interfaces=[SomeInterface], - is_type_of=lambda: None + is_type_of=lambda: None, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', - fields={ - 'iface': GraphQLField(SomeInterface)}), - types=[SomeSubtype]) - assert schema.get_type_map()['SomeSubtype'] == SomeSubtype + name="Query", fields={"iface": GraphQLField(SomeInterface)} + ), + types=[SomeSubtype], + ) + assert schema.get_type_map()["SomeSubtype"] == SomeSubtype def test_includes_interfaces_thunk_subtypes_in_the_type_map(): SomeInterface = GraphQLInterfaceType( - name='SomeInterface', - fields={ - 'f': GraphQLField(GraphQLInt) - } + name="SomeInterface", fields={"f": GraphQLField(GraphQLInt)} ) SomeSubtype = GraphQLObjectType( - name='SomeSubtype', - fields={ - 'f': GraphQLField(GraphQLInt) - }, + name="SomeSubtype", + fields={"f": GraphQLField(GraphQLInt)}, interfaces=lambda: [SomeInterface], - is_type_of=lambda: True + is_type_of=lambda: True, ) - schema = GraphQLSchema(query=GraphQLObjectType( - name='Query', - fields={ - 'iface': GraphQLField(SomeInterface) - } - ), types=[SomeSubtype]) + schema = GraphQLSchema( + query=GraphQLObjectType( + name="Query", fields={"iface": GraphQLField(SomeInterface)} + ), + types=[SomeSubtype], + ) - assert schema.get_type_map()['SomeSubtype'] is SomeSubtype + assert schema.get_type_map()["SomeSubtype"] is SomeSubtype def test_stringifies_simple_types(): - assert str(GraphQLInt) == 'Int' - assert str(BlogArticle) == 'Article' - assert str(InterfaceType) == 'Interface' - assert str(UnionType) == 'Union' - assert str(EnumType) == 'Enum' - assert str(InputObjectType) == 'InputObject' - assert str(GraphQLNonNull(GraphQLInt)) == 'Int!' - assert str(GraphQLList(GraphQLInt)) == '[Int]' - assert str(GraphQLNonNull(GraphQLList(GraphQLInt))) == '[Int]!' - assert str(GraphQLList(GraphQLNonNull(GraphQLInt))) == '[Int!]' - assert str(GraphQLList(GraphQLList(GraphQLInt))) == '[[Int]]' + assert str(GraphQLInt) == "Int" + assert str(BlogArticle) == "Article" + assert str(InterfaceType) == "Interface" + assert str(UnionType) == "Union" + assert str(EnumType) == "Enum" + assert str(InputObjectType) == "InputObject" + assert str(GraphQLNonNull(GraphQLInt)) == "Int!" + assert str(GraphQLList(GraphQLInt)) == "[Int]" + assert str(GraphQLNonNull(GraphQLList(GraphQLInt))) == "[Int]!" + assert str(GraphQLList(GraphQLNonNull(GraphQLInt))) == "[Int!]" + assert str(GraphQLList(GraphQLList(GraphQLInt))) == "[[Int]]" def test_identifies_input_types(): @@ -268,7 +281,7 @@ def test_identifies_input_types(): (InterfaceType, False), (UnionType, False), (EnumType, True), - (InputObjectType, True) + (InputObjectType, True), ) for type, answer in expected: @@ -284,7 +297,7 @@ def test_identifies_output_types(): (InterfaceType, True), (UnionType, True), (EnumType, True), - (InputObjectType, False) + (InputObjectType, False), ) for type, answer in expected: @@ -297,7 +310,9 @@ def test_prohibits_nesting_nonnull_inside_nonnull(): with raises(Exception) as excinfo: GraphQLNonNull(GraphQLNonNull(GraphQLInt)) - assert 'Can only create NonNull of a Nullable GraphQLType but got: Int!.' in str(excinfo.value) + assert "Can only create NonNull of a Nullable GraphQLType but got: Int!." in str( + excinfo.value + ) def test_prohibits_putting_non_object_types_in_unions(): @@ -308,44 +323,54 @@ def test_prohibits_putting_non_object_types_in_unions(): InterfaceType, UnionType, EnumType, - InputObjectType + InputObjectType, ] for x in bad_union_types: with raises(Exception) as excinfo: - GraphQLSchema(GraphQLObjectType('Root', fields={'union': GraphQLField(GraphQLUnionType('BadUnion', [x]))})) + GraphQLSchema( + GraphQLObjectType( + "Root", + fields={"union": GraphQLField(GraphQLUnionType("BadUnion", [x]))}, + ) + ) - assert 'BadUnion may only contain Object types, it cannot contain: ' + str(x) + '.' \ - == str(excinfo.value) + assert "BadUnion may only contain Object types, it cannot contain: " + str( + x + ) + "." == str(excinfo.value) def test_does_not_mutate_passed_field_definitions(): fields = { - 'field1': GraphQLField(GraphQLString), - 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), + "field1": GraphQLField(GraphQLString), + "field2": GraphQLField( + GraphQLString, args={"id": GraphQLArgument(GraphQLString)} + ), } - TestObject1 = GraphQLObjectType(name='Test1', fields=fields) - TestObject2 = GraphQLObjectType(name='Test1', fields=fields) + TestObject1 = GraphQLObjectType(name="Test1", fields=fields) + TestObject2 = GraphQLObjectType(name="Test1", fields=fields) assert TestObject1.fields == TestObject2.fields assert fields == { - 'field1': GraphQLField(GraphQLString), - 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), + "field1": GraphQLField(GraphQLString), + "field2": GraphQLField( + GraphQLString, args={"id": GraphQLArgument(GraphQLString)} + ), } input_fields = { - 'field1': GraphQLInputObjectField(GraphQLString), - 'field2': GraphQLInputObjectField(GraphQLString), + "field1": GraphQLInputObjectField(GraphQLString), + "field2": GraphQLInputObjectField(GraphQLString), } - TestInputObject1 = GraphQLInputObjectType(name='Test1', fields=input_fields) - TestInputObject2 = GraphQLInputObjectType(name='Test2', fields=input_fields) + TestInputObject1 = GraphQLInputObjectType(name="Test1", fields=input_fields) + TestInputObject2 = GraphQLInputObjectType(name="Test2", fields=input_fields) assert TestInputObject1.fields == TestInputObject2.fields assert input_fields == { - 'field1': GraphQLInputObjectField(GraphQLString), - 'field2': GraphQLInputObjectField(GraphQLString), + "field1": GraphQLInputObjectField(GraphQLString), + "field2": GraphQLInputObjectField(GraphQLString), } @@ -371,21 +396,31 @@ def test_does_not_mutate_passed_field_definitions(): def test_does_not_sort_fields_and_argument_keys_when_using_ordered_dict(): - fields = OrderedDict([ - ('b', GraphQLField(GraphQLString)), - ('c', GraphQLField(GraphQLString)), - ('a', GraphQLField(GraphQLString)), - ('d', GraphQLField(GraphQLString, args=OrderedDict([ - ('q', GraphQLArgument(GraphQLString)), - ('x', GraphQLArgument(GraphQLString)), - ('v', GraphQLArgument(GraphQLString)), - ('a', GraphQLArgument(GraphQLString)), - ('n', GraphQLArgument(GraphQLString)) - ]))) - ]) - - test_object = GraphQLObjectType(name='Test', fields=fields) + fields = OrderedDict( + [ + ("b", GraphQLField(GraphQLString)), + ("c", GraphQLField(GraphQLString)), + ("a", GraphQLField(GraphQLString)), + ( + "d", + GraphQLField( + GraphQLString, + args=OrderedDict( + [ + ("q", GraphQLArgument(GraphQLString)), + ("x", GraphQLArgument(GraphQLString)), + ("v", GraphQLArgument(GraphQLString)), + ("a", GraphQLArgument(GraphQLString)), + ("n", GraphQLArgument(GraphQLString)), + ] + ), + ), + ), + ] + ) + + test_object = GraphQLObjectType(name="Test", fields=fields) ordered_fields = test_object.fields - assert list(ordered_fields.keys()) == ['b', 'c', 'a', 'd'] - field_with_args = test_object.fields.get('d') - assert list(field_with_args.args.keys()) == ['q', 'x', 'v', 'a', 'n'] + assert list(ordered_fields.keys()) == ["b", "c", "a", "d"] + field_with_args = test_object.fields.get("d") + assert list(field_with_args.args.keys()) == ["q", "x", "v", "a", "n"] diff --git a/graphql/type/tests/test_enum_type.py b/graphql/type/tests/test_enum_type.py index 65c9ae18..9ac33ebd 100644 --- a/graphql/type/tests/test_enum_type.py +++ b/graphql/type/tests/test_enum_type.py @@ -3,17 +3,26 @@ from rx import Observable from graphql import graphql -from graphql.type import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue, - GraphQLField, GraphQLInt, GraphQLObjectType, - GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInt, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) ColorType = GraphQLEnumType( - name='Color', - values=OrderedDict([ - ('RED', GraphQLEnumValue(0)), - ('GREEN', GraphQLEnumValue(1)), - ('BLUE', GraphQLEnumValue(2)) - ]) + name="Color", + values=OrderedDict( + [ + ("RED", GraphQLEnumValue(0)), + ("GREEN", GraphQLEnumValue(1)), + ("BLUE", GraphQLEnumValue(2)), + ] + ), ) @@ -26,206 +35,230 @@ def get_first(args, *keys): QueryType = GraphQLObjectType( - name='Query', + name="Query", fields={ - 'colorEnum': GraphQLField( + "colorEnum": GraphQLField( type=ColorType, args={ - 'fromEnum': GraphQLArgument(ColorType), - 'fromInt': GraphQLArgument(GraphQLInt), - 'fromString': GraphQLArgument(GraphQLString) + "fromEnum": GraphQLArgument(ColorType), + "fromInt": GraphQLArgument(GraphQLInt), + "fromString": GraphQLArgument(GraphQLString), }, resolver=lambda value, info, **args: get_first( - args, 'fromInt', 'fromString', 'fromEnum') + args, "fromInt", "fromString", "fromEnum" + ), ), - 'colorInt': GraphQLField( + "colorInt": GraphQLField( type=GraphQLInt, args={ - 'fromEnum': GraphQLArgument(ColorType), - 'fromInt': GraphQLArgument(GraphQLInt), + "fromEnum": GraphQLArgument(ColorType), + "fromInt": GraphQLArgument(GraphQLInt), }, - resolver=lambda value, info, **args: get_first( - args, 'fromInt', 'fromEnum') - ) - } + resolver=lambda value, info, **args: get_first(args, "fromInt", "fromEnum"), + ), + }, ) MutationType = GraphQLObjectType( - name='Mutation', + name="Mutation", fields={ - 'favoriteEnum': GraphQLField( + "favoriteEnum": GraphQLField( type=ColorType, - args={ - 'color': GraphQLArgument(ColorType) - }, - resolver=lambda value, info, **args: args.get('color') + args={"color": GraphQLArgument(ColorType)}, + resolver=lambda value, info, **args: args.get("color"), ) - } + }, ) SubscriptionType = GraphQLObjectType( - name='Subscription', + name="Subscription", fields={ - 'subscribeToEnum': GraphQLField( + "subscribeToEnum": GraphQLField( type=ColorType, - args={ - 'color': GraphQLArgument(ColorType) - }, - resolver=lambda value, info, **args: Observable.from_( - [args.get('color')]) + args={"color": GraphQLArgument(ColorType)}, + resolver=lambda value, info, **args: Observable.from_([args.get("color")]), ) - } + }, ) Schema = GraphQLSchema( - query=QueryType, mutation=MutationType, subscription=SubscriptionType) + query=QueryType, mutation=MutationType, subscription=SubscriptionType +) def test_accepts_enum_literals_as_input(): - result = graphql(Schema, '{ colorInt(fromEnum: GREEN) }') + result = graphql(Schema, "{ colorInt(fromEnum: GREEN) }") assert not result.errors - assert result.data == { - 'colorInt': 1 - } + assert result.data == {"colorInt": 1} def test_enum_may_be_output_type(): - result = graphql(Schema, '{ colorEnum(fromInt: 1) }') + result = graphql(Schema, "{ colorEnum(fromInt: 1) }") assert not result.errors - assert result.data == { - 'colorEnum': 'GREEN' - } + assert result.data == {"colorEnum": "GREEN"} def test_enum_may_be_both_input_and_output_type(): - result = graphql(Schema, '{ colorEnum(fromEnum: GREEN) }') + result = graphql(Schema, "{ colorEnum(fromEnum: GREEN) }") assert not result.errors - assert result.data == { - 'colorEnum': 'GREEN' - } + assert result.data == {"colorEnum": "GREEN"} def test_does_not_accept_string_literals(): result = graphql(Schema, '{ colorEnum(fromEnum: "GREEN") }') assert not result.data - assert result.errors[0].message == 'Argument "fromEnum" has invalid value "GREEN".\n' \ - 'Expected type "Color", found "GREEN".' + assert ( + result.errors[0].message == 'Argument "fromEnum" has invalid value "GREEN".\n' + 'Expected type "Color", found "GREEN".' + ) def test_does_not_accept_values_not_in_the_enum(): - result = graphql(Schema, '{ colorEnum(fromEnum: GREENISH) }') + result = graphql(Schema, "{ colorEnum(fromEnum: GREENISH) }") assert not result.data - assert result.errors[0].message == 'Argument "fromEnum" has invalid value GREENISH.\n' \ - 'Expected type "Color", found GREENISH.' + assert ( + result.errors[0].message == 'Argument "fromEnum" has invalid value GREENISH.\n' + 'Expected type "Color", found GREENISH.' + ) def test_does_not_accept_values_with_incorrect_casing(): - result = graphql(Schema, '{ colorEnum(fromEnum: green) }') + result = graphql(Schema, "{ colorEnum(fromEnum: green) }") assert not result.data - assert result.errors[0].message == 'Argument "fromEnum" has invalid value green.\n' \ - 'Expected type "Color", found green.' + assert ( + result.errors[0].message == 'Argument "fromEnum" has invalid value green.\n' + 'Expected type "Color", found green.' + ) def test_does_not_accept_incorrect_internal_value(): result = graphql(Schema, '{ colorEnum(fromString: "GREEN") }') - assert result.data == {'colorEnum': None} - assert result.errors[0].message == 'Expected a value of type "Color" ' \ - 'but received: GREEN' + assert result.data == {"colorEnum": None} + assert ( + result.errors[0].message == 'Expected a value of type "Color" ' + "but received: GREEN" + ) def test_does_not_accept_internal_value_in_place_of_enum_literal(): - result = graphql(Schema, '{ colorEnum(fromEnum: 1) }') + result = graphql(Schema, "{ colorEnum(fromEnum: 1) }") assert not result.data - assert result.errors[0].message == 'Argument "fromEnum" has invalid value 1.\n' \ - 'Expected type "Color", found 1.' + assert ( + result.errors[0].message == 'Argument "fromEnum" has invalid value 1.\n' + 'Expected type "Color", found 1.' + ) def test_does_not_accept_enum_literal_in_place_of_int(): - result = graphql(Schema, '{ colorEnum(fromInt: GREEN) }') + result = graphql(Schema, "{ colorEnum(fromInt: GREEN) }") assert not result.data - assert result.errors[0].message == 'Argument "fromInt" has invalid value GREEN.\n' \ - 'Expected type "Int", found GREEN.' + assert ( + result.errors[0].message == 'Argument "fromInt" has invalid value GREEN.\n' + 'Expected type "Int", found GREEN.' + ) def test_accepts_json_string_as_enum_variable(): result = graphql( Schema, - 'query test($color: Color!) { colorEnum(fromEnum: $color) }', - variable_values={'color': 'BLUE'} + "query test($color: Color!) { colorEnum(fromEnum: $color) }", + variable_values={"color": "BLUE"}, ) assert not result.errors - assert result.data == {'colorEnum': 'BLUE'} + assert result.data == {"colorEnum": "BLUE"} def test_accepts_enum_literals_as_input_arguments_to_mutations(): - result = graphql(Schema, 'mutation x($color: Color!) { favoriteEnum(color: $color) }', variable_values={ - 'color': 'GREEN'}) + result = graphql( + Schema, + "mutation x($color: Color!) { favoriteEnum(color: $color) }", + variable_values={"color": "GREEN"}, + ) assert not result.errors - assert result.data == {'favoriteEnum': 'GREEN'} + assert result.data == {"favoriteEnum": "GREEN"} def test_accepts_enum_literals_as_input_arguments_to_subscriptions(): result = graphql( - Schema, 'subscription x($color: Color!) { subscribeToEnum(color: $color) }', variable_values={ - 'color': 'GREEN'}, allow_subscriptions=True) + Schema, + "subscription x($color: Color!) { subscribeToEnum(color: $color) }", + variable_values={"color": "GREEN"}, + allow_subscriptions=True, + ) assert isinstance(result, Observable) l = [] result.subscribe(l.append) result = l[0] assert not result.errors - assert result.data == {'subscribeToEnum': 'GREEN'} + assert result.data == {"subscribeToEnum": "GREEN"} def test_does_not_accept_internal_value_as_enum_variable(): result = graphql( - Schema, 'query test($color: Color!) { colorEnum(fromEnum: $color) }', variable_values={'color': 2}) + Schema, + "query test($color: Color!) { colorEnum(fromEnum: $color) }", + variable_values={"color": 2}, + ) assert not result.data - assert result.errors[0].message == 'Variable "$color" got invalid value 2.\n' \ - 'Expected type "Color", found 2.' + assert ( + result.errors[0].message == 'Variable "$color" got invalid value 2.\n' + 'Expected type "Color", found 2.' + ) def test_does_not_accept_string_variables_as_enum_input(): - result = graphql(Schema, 'query test($color: String!) { colorEnum(fromEnum: $color) }', variable_values={ - 'color': 'BLUE'}) + result = graphql( + Schema, + "query test($color: String!) { colorEnum(fromEnum: $color) }", + variable_values={"color": "BLUE"}, + ) assert not result.data - assert result.errors[0].message == 'Variable "color" of type "String!" used in position expecting type "Color".' + assert ( + result.errors[0].message + == 'Variable "color" of type "String!" used in position expecting type "Color".' + ) def test_does_not_accept_internal_value_as_enum_input(): result = graphql( - Schema, 'query test($color: Int!) { colorEnum(fromEnum: $color) }', variable_values={'color': 2}) + Schema, + "query test($color: Int!) { colorEnum(fromEnum: $color) }", + variable_values={"color": 2}, + ) assert not result.data - assert result.errors[0].message == 'Variable "color" of type "Int!" used in position expecting type "Color".' + assert ( + result.errors[0].message + == 'Variable "color" of type "Int!" used in position expecting type "Color".' + ) def test_enum_value_may_have_an_internal_value_of_0(): - result = graphql( - Schema, '{ colorEnum(fromEnum: RED) colorInt(fromEnum: RED) }') + result = graphql(Schema, "{ colorEnum(fromEnum: RED) colorInt(fromEnum: RED) }") assert not result.errors - assert result.data == {'colorEnum': 'RED', 'colorInt': 0} + assert result.data == {"colorEnum": "RED", "colorInt": 0} def test_enum_inputs_may_be_nullable(): - result = graphql(Schema, '{ colorEnum colorInt }') + result = graphql(Schema, "{ colorEnum colorInt }") assert not result.errors - assert result.data == {'colorEnum': None, 'colorInt': None} + assert result.data == {"colorEnum": None, "colorInt": None} def test_presents_a_get_values_api(): values = ColorType.get_values() assert len(values) == 3 - assert values[0].name == 'RED' + assert values[0].name == "RED" assert values[0].value == 0 - assert values[1].name == 'GREEN' + assert values[1].name == "GREEN" assert values[1].value == 1 - assert values[2].name == 'BLUE' + assert values[2].name == "BLUE" assert values[2].value == 2 def test_presents_a_get_value_api(): - oneValue = ColorType.get_value('RED') - assert oneValue.name == 'RED' + oneValue = ColorType.get_value("RED") + assert oneValue.name == "RED" assert oneValue.value == 0 badUsage = ColorType.get_value(0) @@ -233,22 +266,30 @@ def test_presents_a_get_value_api(): def test_sorts_values_if_not_using_ordered_dict(): - enum = GraphQLEnumType(name='Test', values={ - 'c': GraphQLEnumValue(), - 'b': GraphQLEnumValue(), - 'a': GraphQLEnumValue(), - 'd': GraphQLEnumValue() - }) + enum = GraphQLEnumType( + name="Test", + values={ + "c": GraphQLEnumValue(), + "b": GraphQLEnumValue(), + "a": GraphQLEnumValue(), + "d": GraphQLEnumValue(), + }, + ) - assert [v.name for v in enum.values] == ['a', 'b', 'c', 'd'] + assert [v.name for v in enum.values] == ["a", "b", "c", "d"] def test_does_not_sort_values_when_using_ordered_dict(): - enum = GraphQLEnumType(name='Test', values=OrderedDict([ - ('c', GraphQLEnumValue()), - ('b', GraphQLEnumValue()), - ('a', GraphQLEnumValue()), - ('d', GraphQLEnumValue()), - ])) - - assert [v.name for v in enum.values] == ['c', 'b', 'a', 'd'] + enum = GraphQLEnumType( + name="Test", + values=OrderedDict( + [ + ("c", GraphQLEnumValue()), + ("b", GraphQLEnumValue()), + ("a", GraphQLEnumValue()), + ("d", GraphQLEnumValue()), + ] + ), + ) + + assert [v.name for v in enum.values] == ["c", "b", "a", "d"] diff --git a/graphql/type/tests/test_introspection.py b/graphql/type/tests/test_introspection.py index 378e0bf6..35df33be 100644 --- a/graphql/type/tests/test_introspection.py +++ b/graphql/type/tests/test_introspection.py @@ -5,10 +5,18 @@ from graphql.error import format_error from graphql.execution import execute from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue, - GraphQLField, GraphQLInputObjectField, - GraphQLInputObjectType, GraphQLList, - GraphQLObjectType, GraphQLSchema, GraphQLString) +from graphql.type import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLList, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) from graphql.utils.introspection_query import introspection_query from graphql.validation.rules import ProvidedNonNullArguments @@ -16,7 +24,9 @@ def test_executes_an_introspection_query(): - EmptySchema = GraphQLSchema(GraphQLObjectType('QueryRoot', {'f': GraphQLField(GraphQLString)})) + EmptySchema = GraphQLSchema( + GraphQLObjectType("QueryRoot", {"f": GraphQLField(GraphQLString)}) + ) result = graphql(EmptySchema, introspection_query) assert not result.errors @@ -24,715 +34,778 @@ def test_executes_an_introspection_query(): "__schema": { "mutationType": None, "subscriptionType": None, - "queryType": { - "name": "QueryRoot" - }, - "types": [{ - "kind": "OBJECT", - "name": "QueryRoot", - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__Schema", - "fields": [{ - "name": "types", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "LIST", - "name": None, - "ofType": { + "queryType": {"name": "QueryRoot"}, + "types": [ + { + "kind": "OBJECT", + "name": "QueryRoot", + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__Schema", + "fields": [ + { + "name": "types", + "args": [], + "type": { "kind": "NON_NULL", "name": None, "ofType": { - "kind": "OBJECT", - "name": "__Type" - } - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "queryType", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "mutationType", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "subscriptionType", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "directives", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "LIST", - "name": None, - "ofType": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": {"kind": "OBJECT", "name": "__Type"}, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "queryType", + "args": [], + "type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "OBJECT", - "name": "__Directive" - } - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__Type", - "fields": [{ - "name": "kind", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "name", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "description", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "fields", - "args": [{ - "name": "includeDeprecated", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None + "name": "__Type", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, }, - "defaultValue": "false" - }], - "type": { - "kind": "LIST", - "name": None, - "ofType": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": None - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "interfaces", - "args": [], - "type": { - "kind": "LIST", - "name": None, - "ofType": { - "kind": "NON_NULL", - "name": None, - "ofType": { + { + "name": "mutationType", + "args": [], + "type": { "kind": "OBJECT", "name": "__Type", - "ofType": None - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "possibleTypes", - "args": [], - "type": { - "kind": "LIST", - "name": None, - "ofType": { - "kind": "NON_NULL", - "name": None, - "ofType": { + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "subscriptionType", + "args": [], + "type": { "kind": "OBJECT", "name": "__Type", - "ofType": None - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "enumValues", - "args": [{ - "name": "includeDeprecated", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, }, - "defaultValue": "false" - }], - "type": { - "kind": "LIST", - "name": None, - "ofType": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": None - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "inputFields", - "args": [], - "type": { - "kind": "LIST", - "name": None, - "ofType": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": None - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "ofType", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "ENUM", - "name": "__TypeKind", - "fields": None, - "inputFields": None, - "interfaces": None, - "enumValues": [{ - "name": "SCALAR", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "OBJECT", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "INTERFACE", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "UNION", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "ENUM", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "INPUT_OBJECT", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "LIST", - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "NON_NULL", - "isDeprecated": False, - "deprecationReason": None - }], - "possibleTypes": None - }, { - "kind": "SCALAR", - "name": "String", - "fields": None, - "inputFields": None, - "interfaces": None, - "enumValues": None, - "possibleTypes": None - }, { - "kind": "SCALAR", - "name": "Boolean", - "fields": None, - "inputFields": None, - "interfaces": None, - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__Field", - "fields": [{ - "name": "name", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "description", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "args", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "LIST", - "name": None, - "ofType": { + { + "name": "directives", + "args": [], + "type": { "kind": "NON_NULL", "name": None, "ofType": { - "kind": "OBJECT", - "name": "__InputValue" - } - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "type", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "isDeprecated", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "deprecationReason", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__InputValue", - "fields": [{ - "name": "name", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "description", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "type", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "defaultValue", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__EnumValue", - "fields": [{ - "name": "name", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "description", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "isDeprecated", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "deprecationReason", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "OBJECT", - "name": "__Directive", - "fields": [{ - "name": "name", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": None - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "description", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": None - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "locations", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "LIST", - "name": None, - "ofType": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__Directive", + }, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__Type", + "fields": [ + { + "name": "kind", + "args": [], + "type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "ENUM", - "name": "__DirectiveLocation" + "name": "__TypeKind", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "name", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "description", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "fields", + "args": [ + { + "name": "includeDeprecated", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + "defaultValue": "false", } - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "args", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "LIST", - "name": None, - "ofType": { + ], + "type": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__Field", + "ofType": None, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "interfaces", + "args": [], + "type": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__Type", + "ofType": None, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "possibleTypes", + "args": [], + "type": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__Type", + "ofType": None, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "enumValues", + "args": [ + { + "name": "includeDeprecated", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + "defaultValue": "false", + } + ], + "type": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__EnumValue", + "ofType": None, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "inputFields", + "args": [], + "type": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__InputValue", + "ofType": None, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "ofType", + "args": [], + "type": { + "kind": "OBJECT", + "name": "__Type", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "ENUM", + "name": "__TypeKind", + "fields": None, + "inputFields": None, + "interfaces": None, + "enumValues": [ + { + "name": "SCALAR", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "OBJECT", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "INTERFACE", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "UNION", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "ENUM", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "INPUT_OBJECT", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "LIST", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "NON_NULL", + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "possibleTypes": None, + }, + { + "kind": "SCALAR", + "name": "String", + "fields": None, + "inputFields": None, + "interfaces": None, + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "SCALAR", + "name": "Boolean", + "fields": None, + "inputFields": None, + "interfaces": None, + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__Field", + "fields": [ + { + "name": "name", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "description", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "args", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__InputValue", + }, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "type", + "args": [], + "type": { "kind": "NON_NULL", "name": None, "ofType": { "kind": "OBJECT", - "name": "__InputValue" - } - } - } - }, - "isDeprecated": False, - "deprecationReason": None - }, { - "name": "onOperation", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None - } - }, - "isDeprecated": True, - "deprecationReason": "Use `locations`." - }, { - "name": "onFragment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None - } - }, - "isDeprecated": True, - "deprecationReason": "Use `locations`." - }, { - "name": "onField", - "args": [], - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None - } - }, - "isDeprecated": True, - "deprecationReason": "Use `locations`." - }], - "inputFields": None, - "interfaces": [], - "enumValues": None, - "possibleTypes": None - }, { - "kind": "ENUM", - "name": "__DirectiveLocation", - "fields": None, - "inputFields": None, - "interfaces": None, - "enumValues": [{ - "name": "QUERY", - "isDeprecated": False - }, { - "name": "MUTATION", - "isDeprecated": False - }, { - "name": "SUBSCRIPTION", - "isDeprecated": False - }, { - "name": "FIELD", - "isDeprecated": False - }, { - "name": "FRAGMENT_DEFINITION", - "isDeprecated": False - }, { - "name": "FRAGMENT_SPREAD", - "isDeprecated": False - }, { - "name": "INLINE_FRAGMENT", - "isDeprecated": False - }], - "possibleTypes": None - }], - "directives": [{ - "name": "include", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [{ - "defaultValue": None, - "name": "if", - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None + "name": "__Type", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "isDeprecated", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "deprecationReason", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__InputValue", + "fields": [ + { + "name": "name", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "description", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "type", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__Type", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "defaultValue", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__EnumValue", + "fields": [ + { + "name": "name", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "description", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "isDeprecated", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "deprecationReason", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "OBJECT", + "name": "__Directive", + "fields": [ + { + "name": "name", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "description", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": None, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "locations", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "ENUM", + "name": "__DirectiveLocation", + }, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "args", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "LIST", + "name": None, + "ofType": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "OBJECT", + "name": "__InputValue", + }, + }, + }, + }, + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "onOperation", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, + "isDeprecated": True, + "deprecationReason": "Use `locations`.", + }, + { + "name": "onFragment", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, + "isDeprecated": True, + "deprecationReason": "Use `locations`.", + }, + { + "name": "onField", + "args": [], + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, + "isDeprecated": True, + "deprecationReason": "Use `locations`.", + }, + ], + "inputFields": None, + "interfaces": [], + "enumValues": None, + "possibleTypes": None, + }, + { + "kind": "ENUM", + "name": "__DirectiveLocation", + "fields": None, + "inputFields": None, + "interfaces": None, + "enumValues": [ + {"name": "QUERY", "isDeprecated": False}, + {"name": "MUTATION", "isDeprecated": False}, + {"name": "SUBSCRIPTION", "isDeprecated": False}, + {"name": "FIELD", "isDeprecated": False}, + {"name": "FRAGMENT_DEFINITION", "isDeprecated": False}, + {"name": "FRAGMENT_SPREAD", "isDeprecated": False}, + {"name": "INLINE_FRAGMENT", "isDeprecated": False}, + ], + "possibleTypes": None, + }, + ], + "directives": [ + { + "name": "include", + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "args": [ + { + "defaultValue": None, + "name": "if", + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, } - } - }] - }, { - "name": "skip", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [{ - "defaultValue": None, - "name": "if", - "type": { - "kind": "NON_NULL", - "name": None, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": None + ], + }, + { + "name": "skip", + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "args": [ + { + "defaultValue": None, + "name": "if", + "type": { + "kind": "NON_NULL", + "name": None, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": None, + }, + }, } - } - }] - }] + ], + }, + ], } } assert contain_subset(expected, result.data) def test_introspects_on_input_object(): - TestInputObject = GraphQLInputObjectType('TestInputObject', OrderedDict([ - ('a', GraphQLInputObjectField(GraphQLString, default_value='foo')), - ('b', GraphQLInputObjectField(GraphQLList(GraphQLString))) - ])) - TestType = GraphQLObjectType('TestType', { - 'field': GraphQLField( - type=GraphQLString, - args={'complex': GraphQLArgument(TestInputObject)}, - resolver=lambda obj, info, **args: json.dumps(args.get('complex')) - ) - }) + TestInputObject = GraphQLInputObjectType( + "TestInputObject", + OrderedDict( + [ + ("a", GraphQLInputObjectField(GraphQLString, default_value="foo")), + ("b", GraphQLInputObjectField(GraphQLList(GraphQLString))), + ] + ), + ) + TestType = GraphQLObjectType( + "TestType", + { + "field": GraphQLField( + type=GraphQLString, + args={"complex": GraphQLArgument(TestInputObject)}, + resolver=lambda obj, info, **args: json.dumps(args.get("complex")), + ) + }, + ) schema = GraphQLSchema(TestType) - request = ''' + request = """ { __schema { types { @@ -762,167 +835,226 @@ def test_introspects_on_input_object(): } } } - ''' + """ result = graphql(schema, request) assert not result.errors - assert {'kind': 'INPUT_OBJECT', - 'name': 'TestInputObject', - 'inputFields': - [{'name': 'a', - 'type': - {'kind': 'SCALAR', - 'name': 'String', - 'ofType': None}, - 'defaultValue': '"foo"'}, - {'name': 'b', - 'type': - {'kind': 'LIST', - 'name': None, - 'ofType': - {'kind': 'SCALAR', - 'name': 'String', - 'ofType': None}}, - 'defaultValue': None}]} in result.data['__schema']['types'] + assert { + "kind": "INPUT_OBJECT", + "name": "TestInputObject", + "inputFields": [ + { + "name": "a", + "type": {"kind": "SCALAR", "name": "String", "ofType": None}, + "defaultValue": '"foo"', + }, + { + "name": "b", + "type": { + "kind": "LIST", + "name": None, + "ofType": {"kind": "SCALAR", "name": "String", "ofType": None}, + }, + "defaultValue": None, + }, + ], + } in result.data["__schema"]["types"] def test_supports_the_type_root_field(): - TestType = GraphQLObjectType('TestType', { - 'testField': GraphQLField(GraphQLString) - }) + TestType = GraphQLObjectType("TestType", {"testField": GraphQLField(GraphQLString)}) schema = GraphQLSchema(TestType) request = '{ __type(name: "TestType") { name } }' result = execute(schema, parse(request), object()) assert not result.errors - assert result.data == {'__type': {'name': 'TestType'}} + assert result.data == {"__type": {"name": "TestType"}} def test_identifies_deprecated_fields(): - TestType = GraphQLObjectType('TestType', OrderedDict([ - ('nonDeprecated', GraphQLField(GraphQLString)), - ('deprecated', GraphQLField(GraphQLString, deprecation_reason='Removed in 1.0')) - ])) + TestType = GraphQLObjectType( + "TestType", + OrderedDict( + [ + ("nonDeprecated", GraphQLField(GraphQLString)), + ( + "deprecated", + GraphQLField(GraphQLString, deprecation_reason="Removed in 1.0"), + ), + ] + ), + ) schema = GraphQLSchema(TestType) - request = '''{__type(name: "TestType") { + request = """{__type(name: "TestType") { name fields(includeDeprecated: true) { name isDeprecated deprecationReason } - } }''' + } }""" result = graphql(schema, request) assert not result.errors - assert result.data == {'__type': { - 'name': 'TestType', - 'fields': [ - {'name': 'nonDeprecated', 'isDeprecated': False, 'deprecationReason': None}, - {'name': 'deprecated', 'isDeprecated': True, - 'deprecationReason': 'Removed in 1.0'}, - ] - }} + assert result.data == { + "__type": { + "name": "TestType", + "fields": [ + { + "name": "nonDeprecated", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "deprecated", + "isDeprecated": True, + "deprecationReason": "Removed in 1.0", + }, + ], + } + } def test_respects_the_includedeprecated_parameter_for_fields(): - TestType = GraphQLObjectType('TestType', OrderedDict([ - ('nonDeprecated', GraphQLField(GraphQLString)), - ('deprecated', GraphQLField(GraphQLString, deprecation_reason='Removed in 1.0')) - ])) + TestType = GraphQLObjectType( + "TestType", + OrderedDict( + [ + ("nonDeprecated", GraphQLField(GraphQLString)), + ( + "deprecated", + GraphQLField(GraphQLString, deprecation_reason="Removed in 1.0"), + ), + ] + ), + ) schema = GraphQLSchema(TestType) - request = '''{__type(name: "TestType") { + request = """{__type(name: "TestType") { name trueFields: fields(includeDeprecated: true) { name } falseFields: fields(includeDeprecated: false) { name } omittedFields: fields { name } - } }''' + } }""" result = graphql(schema, request) assert not result.errors - assert result.data == {'__type': { - 'name': 'TestType', - 'trueFields': [{'name': 'nonDeprecated'}, {'name': 'deprecated'}], - 'falseFields': [{'name': 'nonDeprecated'}], - 'omittedFields': [{'name': 'nonDeprecated'}], - }} + assert result.data == { + "__type": { + "name": "TestType", + "trueFields": [{"name": "nonDeprecated"}, {"name": "deprecated"}], + "falseFields": [{"name": "nonDeprecated"}], + "omittedFields": [{"name": "nonDeprecated"}], + } + } def test_identifies_deprecated_enum_values(): - TestEnum = GraphQLEnumType('TestEnum', OrderedDict([ - ('NONDEPRECATED', GraphQLEnumValue(0)), - ('DEPRECATED', GraphQLEnumValue(1, deprecation_reason='Removed in 1.0')), - ('ALSONONDEPRECATED', GraphQLEnumValue(2)) - ])) - TestType = GraphQLObjectType('TestType', { - 'testEnum': GraphQLField(TestEnum) - }) + TestEnum = GraphQLEnumType( + "TestEnum", + OrderedDict( + [ + ("NONDEPRECATED", GraphQLEnumValue(0)), + ( + "DEPRECATED", + GraphQLEnumValue(1, deprecation_reason="Removed in 1.0"), + ), + ("ALSONONDEPRECATED", GraphQLEnumValue(2)), + ] + ), + ) + TestType = GraphQLObjectType("TestType", {"testEnum": GraphQLField(TestEnum)}) schema = GraphQLSchema(TestType) - request = '''{__type(name: "TestEnum") { + request = """{__type(name: "TestEnum") { name enumValues(includeDeprecated: true) { name isDeprecated deprecationReason } - } }''' + } }""" result = graphql(schema, request) assert not result.errors - assert result.data == {'__type': { - 'name': 'TestEnum', - 'enumValues': [ - {'name': 'NONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None}, - {'name': 'DEPRECATED', 'isDeprecated': True, 'deprecationReason': 'Removed in 1.0'}, - {'name': 'ALSONONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None}, - ]}} + assert result.data == { + "__type": { + "name": "TestEnum", + "enumValues": [ + { + "name": "NONDEPRECATED", + "isDeprecated": False, + "deprecationReason": None, + }, + { + "name": "DEPRECATED", + "isDeprecated": True, + "deprecationReason": "Removed in 1.0", + }, + { + "name": "ALSONONDEPRECATED", + "isDeprecated": False, + "deprecationReason": None, + }, + ], + } + } def test_respects_the_includedeprecated_parameter_for_enum_values(): - TestEnum = GraphQLEnumType('TestEnum', OrderedDict([ - ('NONDEPRECATED', GraphQLEnumValue(0)), - ('DEPRECATED', GraphQLEnumValue(1, deprecation_reason='Removed in 1.0')), - ('ALSONONDEPRECATED', GraphQLEnumValue(2)) - ])) - TestType = GraphQLObjectType('TestType', { - 'testEnum': GraphQLField(TestEnum) - }) + TestEnum = GraphQLEnumType( + "TestEnum", + OrderedDict( + [ + ("NONDEPRECATED", GraphQLEnumValue(0)), + ( + "DEPRECATED", + GraphQLEnumValue(1, deprecation_reason="Removed in 1.0"), + ), + ("ALSONONDEPRECATED", GraphQLEnumValue(2)), + ] + ), + ) + TestType = GraphQLObjectType("TestType", {"testEnum": GraphQLField(TestEnum)}) schema = GraphQLSchema(TestType) - request = '''{__type(name: "TestEnum") { + request = """{__type(name: "TestEnum") { name trueValues: enumValues(includeDeprecated: true) { name } falseValues: enumValues(includeDeprecated: false) { name } omittedValues: enumValues { name } - } }''' + } }""" result = graphql(schema, request) assert not result.errors - assert result.data == {'__type': { - 'name': 'TestEnum', - 'trueValues': [{'name': 'NONDEPRECATED'}, {'name': 'DEPRECATED'}, - {'name': 'ALSONONDEPRECATED'}], - 'falseValues': [{'name': 'NONDEPRECATED'}, - {'name': 'ALSONONDEPRECATED'}], - 'omittedValues': [{'name': 'NONDEPRECATED'}, - {'name': 'ALSONONDEPRECATED'}], - }} + assert result.data == { + "__type": { + "name": "TestEnum", + "trueValues": [ + {"name": "NONDEPRECATED"}, + {"name": "DEPRECATED"}, + {"name": "ALSONONDEPRECATED"}, + ], + "falseValues": [{"name": "NONDEPRECATED"}, {"name": "ALSONONDEPRECATED"}], + "omittedValues": [{"name": "NONDEPRECATED"}, {"name": "ALSONONDEPRECATED"}], + } + } def test_fails_as_expected_on_the_type_root_field_without_an_arg(): - TestType = GraphQLObjectType('TestType', { - 'testField': GraphQLField(GraphQLString) - }) + TestType = GraphQLObjectType("TestType", {"testField": GraphQLField(GraphQLString)}) schema = GraphQLSchema(TestType) - request = ''' + request = """ { __type { name } - }''' + }""" result = graphql(schema, request) - expected_error = {'message': ProvidedNonNullArguments.missing_field_arg_message('__type', 'name', 'String!'), - 'locations': [dict(line=3, column=9)]} - assert (expected_error in [format_error(error) for error in result.errors]) + expected_error = { + "message": ProvidedNonNullArguments.missing_field_arg_message( + "__type", "name", "String!" + ), + "locations": [dict(line=3, column=9)], + } + assert expected_error in [format_error(error) for error in result.errors] def test_exposes_descriptions_on_types_and_fields(): - QueryRoot = GraphQLObjectType('QueryRoot', {'f': GraphQLField(GraphQLString)}) + QueryRoot = GraphQLObjectType("QueryRoot", {"f": GraphQLField(GraphQLString)}) schema = GraphQLSchema(QueryRoot) - request = '''{ + request = """{ schemaType: __type(name: "__Schema") { name, description, @@ -932,46 +1064,48 @@ def test_exposes_descriptions_on_types_and_fields(): } } } - ''' + """ result = graphql(schema, request) assert not result.errors - assert result.data == {'schemaType': { - 'name': '__Schema', - 'description': 'A GraphQL Schema defines the capabilities of a ' + - 'GraphQL server. It exposes all available types and ' + - 'directives on the server, as well as the entry ' + - 'points for query, mutation and subscription operations.', - 'fields': [ - { - 'name': 'types', - 'description': 'A list of all types supported by this server.' - }, - { - 'name': 'queryType', - 'description': 'The type that query operations will be rooted at.' - }, - { - 'name': 'mutationType', - 'description': 'If this server supports mutation, the type that ' - 'mutation operations will be rooted at.' - }, - { - 'name': 'subscriptionType', - 'description': 'If this server support subscription, the type ' - 'that subscription operations will be rooted at.' - }, - { - 'name': 'directives', - 'description': 'A list of all directives supported by this server.' - } - ] - }} + assert result.data == { + "schemaType": { + "name": "__Schema", + "description": "A GraphQL Schema defines the capabilities of a " + + "GraphQL server. It exposes all available types and " + + "directives on the server, as well as the entry " + + "points for query, mutation and subscription operations.", + "fields": [ + { + "name": "types", + "description": "A list of all types supported by this server.", + }, + { + "name": "queryType", + "description": "The type that query operations will be rooted at.", + }, + { + "name": "mutationType", + "description": "If this server supports mutation, the type that " + "mutation operations will be rooted at.", + }, + { + "name": "subscriptionType", + "description": "If this server support subscription, the type " + "that subscription operations will be rooted at.", + }, + { + "name": "directives", + "description": "A list of all directives supported by this server.", + }, + ], + } + } def test_exposes_descriptions_on_enums(): - QueryRoot = GraphQLObjectType('QueryRoot', {'f': GraphQLField(GraphQLString)}) + QueryRoot = GraphQLObjectType("QueryRoot", {"f": GraphQLField(GraphQLString)}) schema = GraphQLSchema(QueryRoot) - request = '''{ + request = """{ typeKindType: __type(name: "__TypeKind") { name, description, @@ -981,51 +1115,50 @@ def test_exposes_descriptions_on_enums(): } } } - ''' + """ result = graphql(schema, request) assert not result.errors - assert result.data == {'typeKindType': { - 'name': '__TypeKind', - 'description': 'An enum describing what kind of type a given `__Type` is', - 'enumValues': [ - { - 'description': 'Indicates this type is a scalar.', - 'name': 'SCALAR' - }, - { - 'description': 'Indicates this type is an object. ' + - '`fields` and `interfaces` are valid fields.', - 'name': 'OBJECT' - }, - { - 'description': 'Indicates this type is an interface. ' + - '`fields` and `possibleTypes` are valid fields.', - 'name': 'INTERFACE' - }, - { - 'description': 'Indicates this type is a union. ' + - '`possibleTypes` is a valid field.', - 'name': 'UNION' - }, - { - 'description': 'Indicates this type is an enum. ' + - '`enumValues` is a valid field.', - 'name': 'ENUM' - }, - { - 'description': 'Indicates this type is an input object. ' + - '`inputFields` is a valid field.', - 'name': 'INPUT_OBJECT' - }, - { - 'description': 'Indicates this type is a list. ' + - '`ofType` is a valid field.', - 'name': 'LIST' - }, - { - 'description': 'Indicates this type is a non-null. ' + - '`ofType` is a valid field.', - 'name': 'NON_NULL' - } - ] - }} + assert result.data == { + "typeKindType": { + "name": "__TypeKind", + "description": "An enum describing what kind of type a given `__Type` is", + "enumValues": [ + {"description": "Indicates this type is a scalar.", "name": "SCALAR"}, + { + "description": "Indicates this type is an object. " + + "`fields` and `interfaces` are valid fields.", + "name": "OBJECT", + }, + { + "description": "Indicates this type is an interface. " + + "`fields` and `possibleTypes` are valid fields.", + "name": "INTERFACE", + }, + { + "description": "Indicates this type is a union. " + + "`possibleTypes` is a valid field.", + "name": "UNION", + }, + { + "description": "Indicates this type is an enum. " + + "`enumValues` is a valid field.", + "name": "ENUM", + }, + { + "description": "Indicates this type is an input object. " + + "`inputFields` is a valid field.", + "name": "INPUT_OBJECT", + }, + { + "description": "Indicates this type is a list. " + + "`ofType` is a valid field.", + "name": "LIST", + }, + { + "description": "Indicates this type is a non-null. " + + "`ofType` is a valid field.", + "name": "NON_NULL", + }, + ], + } + } diff --git a/graphql/type/tests/test_schema.py b/graphql/type/tests/test_schema.py index 166cf123..96173f29 100644 --- a/graphql/type/tests/test_schema.py +++ b/graphql/type/tests/test_schema.py @@ -1,33 +1,35 @@ from pytest import raises -from ...type import (GraphQLField, GraphQLInterfaceType, GraphQLObjectType, - GraphQLSchema, GraphQLString) +from ...type import ( + GraphQLField, + GraphQLInterfaceType, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +) interface_type = GraphQLInterfaceType( - name='Interface', + name="Interface", fields={ - 'field_name': GraphQLField( - type=GraphQLString, - resolver=lambda *_: implementing_type + "field_name": GraphQLField( + type=GraphQLString, resolver=lambda *_: implementing_type ) - } + }, ) implementing_type = GraphQLObjectType( - name='Object', + name="Object", interfaces=[interface_type], - fields={ - 'field_name': GraphQLField(type=GraphQLString, resolver=lambda *_: '') - } + fields={"field_name": GraphQLField(type=GraphQLString, resolver=lambda *_: "")}, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'get_object': GraphQLField(type=interface_type, resolver=lambda *_: {}) - } + "get_object": GraphQLField(type=interface_type, resolver=lambda *_: {}) + }, ) ) @@ -36,5 +38,7 @@ def test_throws_human_readable_error_if_schematypes_not_defined(): with raises(AssertionError) as exci: schema.is_possible_type(interface_type, implementing_type) - assert str(exci.value) == ('Could not find possible implementing types for $Interface in schema. Check that ' - 'schema.types is defined and is an array ofall possible types in the schema.') + assert str(exci.value) == ( + "Could not find possible implementing types for $Interface in schema. Check that " + "schema.types is defined and is an array ofall possible types in the schema." + ) diff --git a/graphql/type/tests/test_serialization.py b/graphql/type/tests/test_serialization.py index 4e5c09d0..3cb09338 100644 --- a/graphql/type/tests/test_serialization.py +++ b/graphql/type/tests/test_serialization.py @@ -1,7 +1,6 @@ import pytest -from graphql.type import (GraphQLBoolean, GraphQLFloat, GraphQLInt, - GraphQLString) +from graphql.type import GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLString def test_serializes_output_int(): @@ -20,9 +19,9 @@ def test_serializes_output_int(): GraphQLInt.serialize(1e100) with pytest.raises(Exception): GraphQLInt.serialize(-1e100) - assert GraphQLInt.serialize('-1.1') == -1 + assert GraphQLInt.serialize("-1.1") == -1 with pytest.raises(Exception): - GraphQLInt.serialize('one') + GraphQLInt.serialize("one") assert GraphQLInt.serialize(False) == 0 assert GraphQLInt.serialize(True) == 1 @@ -34,25 +33,25 @@ def test_serializes_output_float(): assert GraphQLFloat.serialize(0.1) == 0.1 assert GraphQLFloat.serialize(1.1) == 1.1 assert GraphQLFloat.serialize(-1.1) == -1.1 - assert GraphQLFloat.serialize('-1.1') == -1.1 + assert GraphQLFloat.serialize("-1.1") == -1.1 with pytest.raises(Exception): - GraphQLFloat.serialize('one') + GraphQLFloat.serialize("one") assert GraphQLFloat.serialize(False) == 0 assert GraphQLFloat.serialize(True) == 1 def test_serializes_output_string(): - assert GraphQLString.serialize('string') == 'string' - assert GraphQLString.serialize(1) == '1' - assert GraphQLString.serialize(-1.1) == '-1.1' - assert GraphQLString.serialize(True) == 'true' - assert GraphQLString.serialize(False) == 'false' - assert GraphQLString.serialize(u'\U0001F601') == u'\U0001F601' + assert GraphQLString.serialize("string") == "string" + assert GraphQLString.serialize(1) == "1" + assert GraphQLString.serialize(-1.1) == "-1.1" + assert GraphQLString.serialize(True) == "true" + assert GraphQLString.serialize(False) == "false" + assert GraphQLString.serialize(u"\U0001F601") == u"\U0001F601" def test_serializes_output_boolean(): - assert GraphQLBoolean.serialize('string') is True - assert GraphQLBoolean.serialize('') is False + assert GraphQLBoolean.serialize("string") is True + assert GraphQLBoolean.serialize("") is False assert GraphQLBoolean.serialize(1) is True assert GraphQLBoolean.serialize(0) is False assert GraphQLBoolean.serialize(True) is True diff --git a/graphql/type/tests/test_validation.py b/graphql/type/tests/test_validation.py index 1b2e2cbf..0667ef91 100644 --- a/graphql/type/tests/test_validation.py +++ b/graphql/type/tests/test_validation.py @@ -2,11 +2,21 @@ from pytest import raises -from graphql.type import (GraphQLEnumType, GraphQLEnumValue, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLScalarType, GraphQLSchema, - GraphQLString, GraphQLUnionType) +from graphql.type import ( + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) from graphql.type.definition import GraphQLArgument _none = lambda *args: None @@ -14,122 +24,87 @@ _false = lambda *args: False SomeScalarType = GraphQLScalarType( - name='SomeScalar', - serialize=_none, - parse_value=_none, - parse_literal=_none + name="SomeScalar", serialize=_none, parse_value=_none, parse_literal=_none ) SomeObjectType = GraphQLObjectType( - name='SomeObject', - fields={ - 'f': GraphQLField(GraphQLString) - } + name="SomeObject", fields={"f": GraphQLField(GraphQLString)} ) ObjectWithIsTypeOf = GraphQLObjectType( - name='ObjectWithIsTypeOf', + name="ObjectWithIsTypeOf", is_type_of=_true, - fields={ - 'f': GraphQLField(GraphQLString) - } + fields={"f": GraphQLField(GraphQLString)}, ) SomeUnionType = GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=[SomeObjectType] + name="SomeUnion", resolve_type=_none, types=[SomeObjectType] ) SomeInterfaceType = GraphQLInterfaceType( - name='SomeInterface', - resolve_type=_none, - fields={ - 'f': GraphQLField(GraphQLString) - } + name="SomeInterface", resolve_type=_none, fields={"f": GraphQLField(GraphQLString)} ) -SomeEnumType = GraphQLEnumType( - name='SomeEnum', - values={ - 'ONLY': GraphQLEnumValue() - } -) +SomeEnumType = GraphQLEnumType(name="SomeEnum", values={"ONLY": GraphQLEnumValue()}) SomeInputObjectType = GraphQLInputObjectType( - name='SomeInputObject', - fields={ - 'val': GraphQLInputObjectField(GraphQLString, default_value='hello') - } + name="SomeInputObject", + fields={"val": GraphQLInputObjectField(GraphQLString, default_value="hello")}, ) def with_modifiers(types): return ( - types + - [GraphQLList(t) for t in types] + - [GraphQLNonNull(t) for t in types] + - [GraphQLNonNull(GraphQLList(t)) for t in types] + types + + [GraphQLList(t) for t in types] + + [GraphQLNonNull(t) for t in types] + + [GraphQLNonNull(GraphQLList(t)) for t in types] ) -output_types = with_modifiers([ - GraphQLString, - SomeScalarType, - SomeEnumType, - SomeObjectType, - SomeUnionType, - SomeInterfaceType -]) +output_types = with_modifiers( + [ + GraphQLString, + SomeScalarType, + SomeEnumType, + SomeObjectType, + SomeUnionType, + SomeInterfaceType, + ] +) -not_output_types = with_modifiers([ - SomeInputObjectType -]) + [str] +not_output_types = with_modifiers([SomeInputObjectType]) + [str] -input_types = with_modifiers([ - GraphQLString, - SomeScalarType, - SomeEnumType, - SomeInputObjectType -]) +input_types = with_modifiers( + [GraphQLString, SomeScalarType, SomeEnumType, SomeInputObjectType] +) -not_input_types = with_modifiers([ - SomeObjectType, - SomeUnionType, - SomeInterfaceType -]) + [str] +not_input_types = with_modifiers([SomeObjectType, SomeUnionType, SomeInterfaceType]) + [ + str +] def schema_with_field_type(t): return GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'f': GraphQLField(t) - } - ), - types=[t] + query=GraphQLObjectType(name="Query", fields={"f": GraphQLField(t)}), types=[t] ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ASchemaMustHaveObjectRootTypes: - def test_accepts_a_schema_whose_query_type_is_an_object_type(self): assert GraphQLSchema(query=SomeObjectType) def test_accepts_a_schema_whose_query_and_mutation_types_are_object_types(self): MutationType = GraphQLObjectType( - name='Mutation', - fields={'edit': GraphQLField(GraphQLString)} + name="Mutation", fields={"edit": GraphQLField(GraphQLString)} ) assert GraphQLSchema(query=SomeObjectType, mutation=MutationType) def test_accepts_a_schema_whose_query_and_subscription_types_are_object_types(self): SubscriptionType = GraphQLObjectType( - name='Subscription', - fields={'subscribe': GraphQLField(GraphQLString)} + name="Subscription", fields={"subscribe": GraphQLField(GraphQLString)} ) assert GraphQLSchema(query=SomeObjectType, subscription=SubscriptionType) @@ -138,777 +113,864 @@ def test_rejects_a_schema_without_a_query_type(self): with raises(AssertionError) as excinfo: GraphQLSchema(query=None) - assert str(excinfo.value) == 'Schema query must be Object Type but got: None.' + assert str(excinfo.value) == "Schema query must be Object Type but got: None." def test_rejects_a_schema_whose_query_type_is_an_input_type(self): with raises(AssertionError) as excinfo: GraphQLSchema(query=SomeInputObjectType) - assert str(excinfo.value) == 'Schema query must be Object Type but got: SomeInputObject.' + assert ( + str(excinfo.value) + == "Schema query must be Object Type but got: SomeInputObject." + ) def test_rejects_a_schema_whose_mutation_type_is_an_input_type(self): with raises(AssertionError) as excinfo: GraphQLSchema(query=SomeObjectType, mutation=SomeInputObjectType) - assert str(excinfo.value) == 'Schema mutation must be Object Type but got: SomeInputObject.' + assert ( + str(excinfo.value) + == "Schema mutation must be Object Type but got: SomeInputObject." + ) def test_rejects_a_schema_whose_subscription_type_is_an_input_type(self): with raises(AssertionError) as excinfo: GraphQLSchema(query=SomeObjectType, subscription=SomeInputObjectType) - assert str(excinfo.value) == 'Schema subscription must be Object Type but got: SomeInputObject.' + assert ( + str(excinfo.value) + == "Schema subscription must be Object Type but got: SomeInputObject." + ) def test_rejects_a_schema_whose_directives_are_incorrectly_typed(self): with raises(AssertionError) as excinfo: - GraphQLSchema(query=SomeObjectType, directives=['somedirective']) + GraphQLSchema(query=SomeObjectType, directives=["somedirective"]) - assert str(excinfo.value) == 'Schema directives must be List[GraphQLDirective] if provided but got: ' \ - '[\'somedirective\'].' + assert ( + str(excinfo.value) + == "Schema directives must be List[GraphQLDirective] if provided but got: " + "['somedirective']." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ASchemaMustContainUniquelyNamedTypes: - def test_it_rejects_a_schema_which_defines_a_builtin_type(self): - FakeString = GraphQLScalarType( - name='String', - serialize=_none - ) + FakeString = GraphQLScalarType(name="String", serialize=_none) QueryType = GraphQLObjectType( - name='Query', + name="Query", fields={ - 'normal': GraphQLField(GraphQLString), - 'fake': GraphQLField(FakeString) - } + "normal": GraphQLField(GraphQLString), + "fake": GraphQLField(FakeString), + }, ) with raises(AssertionError) as excinfo: GraphQLSchema(query=QueryType) - assert str(excinfo.value) == 'Schema must contain unique named types but contains multiple types named ' \ - '"String".' + assert ( + str(excinfo.value) + == "Schema must contain unique named types but contains multiple types named " + '"String".' + ) # noinspection PyUnusedLocal - def test_it_rejects_a_schema_which_have_same_named_objects_implementing_an_interface(self): + def test_it_rejects_a_schema_which_have_same_named_objects_implementing_an_interface( + self + ): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'f': GraphQLField(GraphQLString) - } + fields={"f": GraphQLField(GraphQLString)}, ) FirstBadObject = GraphQLObjectType( - name='BadObject', + name="BadObject", interfaces=[AnotherInterface], - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) SecondBadObject = GraphQLObjectType( - name='BadObject', + name="BadObject", interfaces=[AnotherInterface], - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) QueryType = GraphQLObjectType( - name='Query', - fields={ - 'iface': GraphQLField(AnotherInterface) - } + name="Query", fields={"iface": GraphQLField(AnotherInterface)} ) with raises(AssertionError) as excinfo: GraphQLSchema(query=QueryType, types=[FirstBadObject, SecondBadObject]) - assert str(excinfo.value) == 'Schema must contain unique named types but contains multiple types named ' \ - '"BadObject".' + assert ( + str(excinfo.value) + == "Schema must contain unique named types but contains multiple types named " + '"BadObject".' + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectsMustHaveFields: - def test_accepts_an_object_type_with_fields_object(self): - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'f': GraphQLField(GraphQLString) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", fields={"f": GraphQLField(GraphQLString)} + ) + ) def test_accepts_an_object_type_with_a_field_function(self): - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=lambda: { - 'f': GraphQLField(GraphQLString) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", fields=lambda: {"f": GraphQLField(GraphQLString)} + ) + ) def test_rejects_an_object_type_with_missing_fields(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=None - )) + schema_with_field_type(GraphQLObjectType(name="SomeObject", fields=None)) - assert str(excinfo.value) == 'SomeObject fields must be a mapping (dict / OrderedDict) with field names ' \ - 'as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeObject fields must be a mapping (dict / OrderedDict) with field names " + "as keys or a function which returns such a mapping." + ) def test_rejects_an_object_type_with_incorrectly_named_fields(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'bad-name-with-dashes': GraphQLField(GraphQLString) - } - )) + schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={"bad-name-with-dashes": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' + assert ( + str(excinfo.value) + == 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' + ) def test_rejects_an_object_type_with_incorrectly_typed_fields(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=[ - GraphQLField(GraphQLString) - ] - )) + schema_with_field_type( + GraphQLObjectType( + name="SomeObject", fields=[GraphQLField(GraphQLString)] + ) + ) - assert str(excinfo.value) == 'SomeObject fields must be a mapping (dict / OrderedDict) with field names ' \ - 'as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeObject fields must be a mapping (dict / OrderedDict) with field names " + "as keys or a function which returns such a mapping." + ) def test_rejects_an_object_type_with_empty_fields(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={} - )) + schema_with_field_type(GraphQLObjectType(name="SomeObject", fields={})) - assert str(excinfo.value) == 'SomeObject fields must be a mapping (dict / OrderedDict) with field names ' \ - 'as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeObject fields must be a mapping (dict / OrderedDict) with field names " + "as keys or a function which returns such a mapping." + ) def test_rejects_an_object_type_with_a_field_function_that_returns_nothing(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=_none - )) + schema_with_field_type(GraphQLObjectType(name="SomeObject", fields=_none)) - assert str(excinfo.value) == 'SomeObject fields must be a mapping (dict / OrderedDict) with field names ' \ - 'as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeObject fields must be a mapping (dict / OrderedDict) with field names " + "as keys or a function which returns such a mapping." + ) def test_rejects_an_object_type_with_a_field_function_that_returns_empty(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=lambda: {} - )) + schema_with_field_type( + GraphQLObjectType(name="SomeObject", fields=lambda: {}) + ) - assert str(excinfo.value) == 'SomeObject fields must be a mapping (dict / OrderedDict) with field names ' \ - 'as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeObject fields must be a mapping (dict / OrderedDict) with field names " + "as keys or a function which returns such a mapping." + ) def test_rejects_an_object_type_with_a_field_with_an_invalid_value(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={'f': 'hello'} - )) + schema_with_field_type( + GraphQLObjectType(name="SomeObject", fields={"f": "hello"}) + ) - assert str(excinfo.value) == 'SomeObject.f must be an instance of GraphQLField.' + assert str(excinfo.value) == "SomeObject.f must be an instance of GraphQLField." def test_rejects_an_object_type_with_a_field_function_with_an_invalid_value(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields=lambda: {'f': 'hello'} - )) + schema_with_field_type( + GraphQLObjectType(name="SomeObject", fields=lambda: {"f": "hello"}) + ) - assert str(excinfo.value) == 'SomeObject.f must be an instance of GraphQLField.' + assert str(excinfo.value) == "SomeObject.f must be an instance of GraphQLField." # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_FieldArgsMustBeProperlyNamed: - def test_accepts_field_args_with_valid_names(self): - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'goodField': GraphQLField( - GraphQLString, - args={ - 'goodArg': GraphQLArgument(GraphQLString) - } - ) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={ + "goodField": GraphQLField( + GraphQLString, args={"goodArg": GraphQLArgument(GraphQLString)} + ) + }, + ) + ) def test_reject_field_args_with_invalid_names(self): with raises(AssertionError) as excinfo: - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'badField': GraphQLField( - GraphQLString, - args={ - 'bad-name-with-dashes': GraphQLArgument(GraphQLString) - } - ) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={ + "badField": GraphQLField( + GraphQLString, + args={ + "bad-name-with-dashes": GraphQLArgument(GraphQLString) + }, + ) + }, + ) + ) - assert str(excinfo.value) == 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' + assert ( + str(excinfo.value) + == 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_FieldArgsMustBeObjects: - def test_accepts_an_object_with_field_args(self): - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'goodField': GraphQLField( - GraphQLString, - args={ - 'goodArg': GraphQLArgument(GraphQLString) - } - ) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={ + "goodField": GraphQLField( + GraphQLString, args={"goodArg": GraphQLArgument(GraphQLString)} + ) + }, + ) + ) def test_rejects_an_object_with_incorrectly_typed_field_args(self): with raises(AssertionError) as excinfo: - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'badField': GraphQLField( - GraphQLString, - args=[GraphQLArgument(GraphQLString)] - ) - } - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={ + "badField": GraphQLField( + GraphQLString, args=[GraphQLArgument(GraphQLString)] + ) + }, + ) + ) - assert str(excinfo.value) == 'SomeObject.badField args must be a mapping (dict / OrderedDict) with argument ' \ - 'names as keys.' + assert ( + str(excinfo.value) + == "SomeObject.badField args must be a mapping (dict / OrderedDict) with argument " + "names as keys." + ) - def test_rejects_an_object_with_incorrectly_typed_field_args_with_an_invalid_value(self): - with raises(AssertionError) as excinfo: - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - fields={ - 'badField': GraphQLField( - GraphQLString, - args={'badArg': 'I am bad!'} - ) - } - )) + def test_rejects_an_object_with_incorrectly_typed_field_args_with_an_invalid_value( + self + ): + with raises(AssertionError) as excinfo: + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + fields={ + "badField": GraphQLField( + GraphQLString, args={"badArg": "I am bad!"} + ) + }, + ) + ) - assert str(excinfo.value) == 'SomeObject.badField(badArg:) argument must be an instance of GraphQLArgument.' + assert ( + str(excinfo.value) + == "SomeObject.badField(badArg:) argument must be an instance of GraphQLArgument." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectInterfacesMustBeArray: - def test_accepts_an_object_type_with_array_interface(self): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces=[AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces=[AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - def test_accepts_an_object_type_with_interfaces_as_a_function_returning_an_array(self): + def test_accepts_an_object_type_with_interfaces_as_a_function_returning_an_array( + self + ): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces=lambda: [AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces=lambda: [AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) + ) def test_rejects_an_object_type_with_incorrectly_typed_interfaces(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces={}, - fields={'f': GraphQLField(GraphQLString)} - )) + schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces={}, + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'SomeObject interfaces must be a list/tuple or a function which returns a ' \ - 'list/tuple.' + assert ( + str(excinfo.value) + == "SomeObject interfaces must be a list/tuple or a function which returns a " + "list/tuple." + ) - def test_rejects_an_object_type_with_interfaces_as_a_function_returning_an_incorrect_type(self): + def test_rejects_an_object_type_with_interfaces_as_a_function_returning_an_incorrect_type( + self + ): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces=lambda: {}, - fields={'f': GraphQLField(GraphQLString)} - )) + schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces=lambda: {}, + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'SomeObject interfaces must be a list/tuple or a function which returns a ' \ - 'list/tuple.' + assert ( + str(excinfo.value) + == "SomeObject interfaces must be a list/tuple or a function which returns a " + "list/tuple." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_UnionTypesMustBeArray: - def test_accepts_a_union_type_with_aray_types(self): - assert schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=[SomeObjectType] - )) + assert schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", resolve_type=_none, types=[SomeObjectType] + ) + ) def test_rejects_a_union_without_types(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none - )) + schema_with_field_type( + GraphQLUnionType(name="SomeUnion", resolve_type=_none) + ) - assert str(excinfo.value) == 'Must provide types for Union SomeUnion.' + assert str(excinfo.value) == "Must provide types for Union SomeUnion." def test_rejects_a_union_type_with_empty_types(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=[] - )) + schema_with_field_type( + GraphQLUnionType(name="SomeUnion", resolve_type=_none, types=[]) + ) - assert str(excinfo.value) == 'Must provide types for Union SomeUnion.' + assert str(excinfo.value) == "Must provide types for Union SomeUnion." def test_rejects_a_union_type_with_incorrectly_typed_types(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types={'SomeObjectType': SomeObjectType} - )) + schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", + resolve_type=_none, + types={"SomeObjectType": SomeObjectType}, + ) + ) - assert str(excinfo.value) == 'Must provide types for Union SomeUnion.' + assert str(excinfo.value) == "Must provide types for Union SomeUnion." # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_UnionTypesMustBeCallableThatReturnsArray: - def test_accepts_a_union_type_with_aray_types(self): - assert schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=lambda: [SomeObjectType] - )) + assert schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", resolve_type=_none, types=lambda: [SomeObjectType] + ) + ) def test_rejects_a_union_type_with_empty_types(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=lambda: [] - )) + schema_with_field_type( + GraphQLUnionType(name="SomeUnion", resolve_type=_none, types=lambda: []) + ) - assert str(excinfo.value) == 'Must provide types for Union SomeUnion.' + assert str(excinfo.value) == "Must provide types for Union SomeUnion." def test_rejects_a_union_type_with_incorrectly_typed_types(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=lambda: {'SomeObjectType': SomeObjectType} - )) + schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", + resolve_type=_none, + types=lambda: {"SomeObjectType": SomeObjectType}, + ) + ) - assert str(excinfo.value) == 'Must provide types for Union SomeUnion.' + assert str(excinfo.value) == "Must provide types for Union SomeUnion." def schema_with_input_object(input_object_type): return GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'f': GraphQLField(GraphQLString, args={ - 'badArg': GraphQLArgument(input_object_type) - }) - } + "f": GraphQLField( + GraphQLString, args={"badArg": GraphQLArgument(input_object_type)} + ) + }, ) ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_InputObjectsMustHaveFields: - def test_accepts_an_input_object_type_with_fields(self): - assert schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields={ - 'f': GraphQLInputObjectField(GraphQLString) - } - )) + assert schema_with_input_object( + GraphQLInputObjectType( + name="SomeInputObject", + fields={"f": GraphQLInputObjectField(GraphQLString)}, + ) + ) def test_accepts_an_input_object_type_with_field_function(self): - assert schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=lambda: { - 'f': GraphQLInputObjectField(GraphQLString) - } - )) + assert schema_with_input_object( + GraphQLInputObjectType( + name="SomeInputObject", + fields=lambda: {"f": GraphQLInputObjectField(GraphQLString)}, + ) + ) def test_rejects_an_input_object_type_with_missing_fields(self): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=None - )) + schema_with_input_object( + GraphQLInputObjectType(name="SomeInputObject", fields=None) + ) - assert str(excinfo.value) == 'SomeInputObject fields must be a mapping (dict / OrderedDict) with ' \ - 'field names as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeInputObject fields must be a mapping (dict / OrderedDict) with " + "field names as keys or a function which returns such a mapping." + ) def test_rejects_an_input_object_type_with_incorrectly_typed_fields(self): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=[GraphQLInputObjectField(GraphQLString)] - )) + schema_with_input_object( + GraphQLInputObjectType( + name="SomeInputObject", + fields=[GraphQLInputObjectField(GraphQLString)], + ) + ) - assert str(excinfo.value) == 'SomeInputObject fields must be a mapping (dict / OrderedDict) with ' \ - 'field names as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeInputObject fields must be a mapping (dict / OrderedDict) with " + "field names as keys or a function which returns such a mapping." + ) def test_rejects_an_input_object_type_with_incorrectly_typed_field_value(self): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields={'f': GraphQLField(GraphQLString)} - )) + schema_with_input_object( + GraphQLInputObjectType( + name="SomeInputObject", fields={"f": GraphQLField(GraphQLString)} + ) + ) - assert str(excinfo.value) == 'SomeInputObject.f must be an instance of GraphQLInputObjectField.' + assert ( + str(excinfo.value) + == "SomeInputObject.f must be an instance of GraphQLInputObjectField." + ) - def test_rejects_an_input_object_type_with_fields_function_returning_incorrectly_typed_field_value(self): + def test_rejects_an_input_object_type_with_fields_function_returning_incorrectly_typed_field_value( + self + ): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=lambda: {'f': GraphQLField(GraphQLString)} - )) + schema_with_input_object( + GraphQLInputObjectType( + name="SomeInputObject", + fields=lambda: {"f": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'SomeInputObject.f must be an instance of GraphQLInputObjectField.' + assert ( + str(excinfo.value) + == "SomeInputObject.f must be an instance of GraphQLInputObjectField." + ) def test_rejects_an_input_object_type_with_empty_fields(self): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields={} - )) + schema_with_input_object( + GraphQLInputObjectType(name="SomeInputObject", fields={}) + ) - assert str(excinfo.value) == 'SomeInputObject fields must be a mapping (dict / OrderedDict) with ' \ - 'field names as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeInputObject fields must be a mapping (dict / OrderedDict) with " + "field names as keys or a function which returns such a mapping." + ) - def test_rejects_an_input_object_type_with_a_field_function_that_returns_nothing(self): + def test_rejects_an_input_object_type_with_a_field_function_that_returns_nothing( + self + ): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=_none - )) + schema_with_input_object( + GraphQLInputObjectType(name="SomeInputObject", fields=_none) + ) - assert str(excinfo.value) == 'SomeInputObject fields must be a mapping (dict / OrderedDict) with ' \ - 'field names as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeInputObject fields must be a mapping (dict / OrderedDict) with " + "field names as keys or a function which returns such a mapping." + ) - def test_rejects_an_input_object_type_with_a_field_function_that_returns_empty(self): + def test_rejects_an_input_object_type_with_a_field_function_that_returns_empty( + self + ): with raises(AssertionError) as excinfo: - schema_with_input_object(GraphQLInputObjectType( - name='SomeInputObject', - fields=lambda: {} - )) + schema_with_input_object( + GraphQLInputObjectType(name="SomeInputObject", fields=lambda: {}) + ) - assert str(excinfo.value) == 'SomeInputObject fields must be a mapping (dict / OrderedDict) with ' \ - 'field names as keys or a function which returns such a mapping.' + assert ( + str(excinfo.value) + == "SomeInputObject fields must be a mapping (dict / OrderedDict) with " + "field names as keys or a function which returns such a mapping." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectTypesMustBeAssertable: - def test_accepts_an_object_type_with_an_is_type_of_function(self): - assert schema_with_field_type(GraphQLObjectType( - name='AnotherObject', - is_type_of=_true, - fields={'f': GraphQLField(GraphQLString)} - )) + assert schema_with_field_type( + GraphQLObjectType( + name="AnotherObject", + is_type_of=_true, + fields={"f": GraphQLField(GraphQLString)}, + ) + ) def test_rejects_an_object_type_with_an_incorrect_type_for_is_type_of(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='AnotherObject', - is_type_of={}, - fields={'f': GraphQLField(GraphQLString)} - )) + schema_with_field_type( + GraphQLObjectType( + name="AnotherObject", + is_type_of={}, + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'AnotherObject must provide "is_type_of" as a function.' + assert ( + str(excinfo.value) + == 'AnotherObject must provide "is_type_of" as a function.' + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_InterfaceTypesMustBeResolvable: - def test_accepts_an_interface_type_defining_resolve_type(self): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces=[AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces=[AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) + ) def test_accepts_an_interface_with_implementing_type_defining_is_type_of(self): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', - fields={'f': GraphQLField(GraphQLString)} + name="AnotherInterface", fields={"f": GraphQLField(GraphQLString)} ) - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - is_type_of=_true, - interfaces=[AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + is_type_of=_true, + interfaces=[AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - def test_accepts_an_interface_type_defining_resolve_type_with_implementing_type_defining_is_type_of(self): + def test_accepts_an_interface_type_defining_resolve_type_with_implementing_type_defining_is_type_of( + self + ): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, + ) + assert schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + is_type_of=_true, + interfaces=[AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) ) - assert schema_with_field_type(GraphQLObjectType( - name='SomeObject', - is_type_of=_true, - interfaces=[AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) def test_rejects_an_interface_type_with_an_incorrect_type_for_resolve_type(self): with raises(AssertionError) as excinfo: GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type={}, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) - assert str(excinfo.value) == 'AnotherInterface must provide "resolve_type" as a function.' + assert ( + str(excinfo.value) + == 'AnotherInterface must provide "resolve_type" as a function.' + ) - def test_rejects_an_interface_type_not_defining_resolve_type_with_implementing_type_not_defining_is_type_of(self): + def test_rejects_an_interface_type_not_defining_resolve_type_with_implementing_type_not_defining_is_type_of( + self + ): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', - fields={'f': GraphQLField(GraphQLString)} + name="AnotherInterface", fields={"f": GraphQLField(GraphQLString)} ) with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLObjectType( - name='SomeObject', - interfaces=[AnotherInterfaceType], - fields={'f': GraphQLField(GraphQLString)} - )) + schema_with_field_type( + GraphQLObjectType( + name="SomeObject", + interfaces=[AnotherInterfaceType], + fields={"f": GraphQLField(GraphQLString)}, + ) + ) - assert str(excinfo.value) == 'Interface Type AnotherInterface does not provide a "resolve_type" function and ' \ - 'implementing Type SomeObject does not provide a "is_type_of" function. ' \ - 'There is no way to resolve this implementing type during execution.' + assert ( + str(excinfo.value) + == 'Interface Type AnotherInterface does not provide a "resolve_type" function and ' + 'implementing Type SomeObject does not provide a "is_type_of" function. ' + "There is no way to resolve this implementing type during execution." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_UnionTypesMustBeResolvable: - def test_accepts_a_union_type_defining_resolve_type(self): - assert schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=[SomeObjectType] - )) + assert schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", resolve_type=_none, types=[SomeObjectType] + ) + ) def test_accepts_a_union_of_object_types_defining_is_type_of(self): - assert schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - types=[ObjectWithIsTypeOf] - )) - - def test_accepts_a_union_type_defning_resolve_type_of_objects_defning_is_type_of(self): - assert schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type=_none, - types=[ObjectWithIsTypeOf] - )) + assert schema_with_field_type( + GraphQLUnionType(name="SomeUnion", types=[ObjectWithIsTypeOf]) + ) + + def test_accepts_a_union_type_defning_resolve_type_of_objects_defning_is_type_of( + self + ): + assert schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", resolve_type=_none, types=[ObjectWithIsTypeOf] + ) + ) def test_rejects_an_interface_type_with_an_incorrect_type_for_resolve_type(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - resolve_type={}, - types=[ObjectWithIsTypeOf] - )) + schema_with_field_type( + GraphQLUnionType( + name="SomeUnion", resolve_type={}, types=[ObjectWithIsTypeOf] + ) + ) - assert str(excinfo.value) == 'SomeUnion must provide "resolve_type" as a function.' + assert ( + str(excinfo.value) == 'SomeUnion must provide "resolve_type" as a function.' + ) - def test_rejects_a_union_type_not_defining_resolve_type_of_object_types_not_defining_is_type_of(self): + def test_rejects_a_union_type_not_defining_resolve_type_of_object_types_not_defining_is_type_of( + self + ): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLUnionType( - name='SomeUnion', - types=[SomeObjectType] - )) + schema_with_field_type( + GraphQLUnionType(name="SomeUnion", types=[SomeObjectType]) + ) - assert str(excinfo.value) == 'Union Type SomeUnion does not provide a "resolve_type" function and possible ' \ - 'Type SomeObject does not provide a "is_type_of" function. ' \ - 'There is no way to resolve this possible type during execution.' + assert ( + str(excinfo.value) + == 'Union Type SomeUnion does not provide a "resolve_type" function and possible ' + 'Type SomeObject does not provide a "is_type_of" function. ' + "There is no way to resolve this possible type during execution." + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ScalarTypesMustBeSerializable: - def test_accepts_a_scalar_type_defining_serialize(self): - assert schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize=_none - )) + assert schema_with_field_type( + GraphQLScalarType(name="SomeScalar", serialize=_none) + ) def test_rejects_a_scalar_type_not_defining_serialize(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLScalarType( - name='SomeScalar' - )) + schema_with_field_type(GraphQLScalarType(name="SomeScalar")) - assert str(excinfo.value) == 'SomeScalar must provide "serialize" function. If this custom Scalar is also ' \ - 'used as an input type, ensure "parse_value" and "parse_literal" ' \ - 'functions are also provided.' + assert ( + str(excinfo.value) + == 'SomeScalar must provide "serialize" function. If this custom Scalar is also ' + 'used as an input type, ensure "parse_value" and "parse_literal" ' + "functions are also provided." + ) def test_rejects_a_scalar_type_defining_serialize_with_an_incorrect_type(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize={} - )) + schema_with_field_type(GraphQLScalarType(name="SomeScalar", serialize={})) - assert str(excinfo.value) == 'SomeScalar must provide "serialize" function. If this custom Scalar is also ' \ - 'used as an input type, ensure "parse_value" and "parse_literal" ' \ - 'functions are also provided.' + assert ( + str(excinfo.value) + == 'SomeScalar must provide "serialize" function. If this custom Scalar is also ' + 'used as an input type, ensure "parse_value" and "parse_literal" ' + "functions are also provided." + ) def test_accepts_scalar_type_defining_parse_value_and_parse_literal(self): - assert schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize=_none, - parse_literal=_none, - parse_value=_none - )) + assert schema_with_field_type( + GraphQLScalarType( + name="SomeScalar", + serialize=_none, + parse_literal=_none, + parse_value=_none, + ) + ) def test_rejects_a_scalar_type_defining_parse_value_but_not_parse_literal(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize=_none, - parse_value=_none - )) + schema_with_field_type( + GraphQLScalarType(name="SomeScalar", serialize=_none, parse_value=_none) + ) - assert str(excinfo.value) == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + assert ( + str(excinfo.value) + == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + ) def test_rejects_a_scalar_type_defining_parse_literal_but_not_parse_value(self): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize=_none, - parse_literal=_none - )) + schema_with_field_type( + GraphQLScalarType( + name="SomeScalar", serialize=_none, parse_literal=_none + ) + ) - assert str(excinfo.value) == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + assert ( + str(excinfo.value) + == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + ) - def test_rejects_a_scalar_type_defining_parse_literal_and_parse_value_with_an_incorrect_type(self): + def test_rejects_a_scalar_type_defining_parse_literal_and_parse_value_with_an_incorrect_type( + self + ): with raises(AssertionError) as excinfo: - schema_with_field_type(GraphQLScalarType( - name='SomeScalar', - serialize=_none, - parse_literal={}, - parse_value={} - )) + schema_with_field_type( + GraphQLScalarType( + name="SomeScalar", serialize=_none, parse_literal={}, parse_value={} + ) + ) - assert str(excinfo.value) == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + assert ( + str(excinfo.value) + == 'SomeScalar must provide both "parse_value" and "parse_literal" functions.' + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_EnumTypesMustBeWellDefined: - def test_accepts_a_well_defined_enum_type_with_empty_value_definition(self): assert GraphQLEnumType( - name='SomeEnum', - values={ - 'FOO': GraphQLEnumValue(), - 'BAR': GraphQLEnumValue() - } + name="SomeEnum", + values={"FOO": GraphQLEnumValue(), "BAR": GraphQLEnumValue()}, ) def test_accepts_a_well_defined_enum_type_with_internal_value_definition(self): assert GraphQLEnumType( - name='SomeEnum', - values={ - 'FOO': GraphQLEnumValue(10), - 'BAR': GraphQLEnumValue(20) - } + name="SomeEnum", + values={"FOO": GraphQLEnumValue(10), "BAR": GraphQLEnumValue(20)}, ) def test_rejects_an_enum_without_values(self): with raises(AssertionError) as excinfo: - GraphQLEnumType( - name='SomeEnum', - values=None - ) + GraphQLEnumType(name="SomeEnum", values=None) - assert str(excinfo.value) == 'SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys.' + assert ( + str(excinfo.value) + == "SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys." + ) def test_rejects_an_enum_with_empty_values(self): with raises(AssertionError) as excinfo: - GraphQLEnumType( - name='SomeEnum', - values={} - ) - assert str(excinfo.value) == 'SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys.' + GraphQLEnumType(name="SomeEnum", values={}) + assert ( + str(excinfo.value) + == "SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys." + ) def test_rejects_an_enum_with_incorrectly_typed_values(self): with raises(AssertionError) as excinfo: - GraphQLEnumType( - name='SomeEnum', - values=[{'foo': GraphQLEnumValue(10)}] - ) + GraphQLEnumType(name="SomeEnum", values=[{"foo": GraphQLEnumValue(10)}]) - assert str(excinfo.value) == 'SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys.' + assert ( + str(excinfo.value) + == "SomeEnum values must be a mapping (dict / OrderedDict) with value names as keys." + ) def test_rejects_an_enum_with_missing_value_definition(self): with raises(AssertionError) as excinfo: - GraphQLEnumType( - name='SomeEnum', - values={ - 'FOO': None - } - ) - assert str(excinfo.value) == 'SomeEnum.FOO must be an instance of GraphQLEnumValue, but got: None' + GraphQLEnumType(name="SomeEnum", values={"FOO": None}) + assert ( + str(excinfo.value) + == "SomeEnum.FOO must be an instance of GraphQLEnumValue, but got: None" + ) def test_rejects_an_enum_with_incorrectly_typed_value_definition(self): with raises(AssertionError) as excinfo: - GraphQLEnumType( - name='SomeEnum', - values={ - 'FOO': 10 - } - ) - assert str(excinfo.value) == 'SomeEnum.FOO must be an instance of GraphQLEnumValue, but got: 10' + GraphQLEnumType(name="SomeEnum", values={"FOO": 10}) + assert ( + str(excinfo.value) + == "SomeEnum.FOO must be an instance of GraphQLEnumValue, but got: 10" + ) def schema_with_object_field_of_type(field_type): BadObjectType = GraphQLObjectType( - name='BadObject', - fields={ - 'badField': GraphQLField(field_type) - } + name="BadObject", fields={"badField": GraphQLField(field_type)} ) return schema_with_field_type(BadObjectType) @@ -916,68 +978,75 @@ def schema_with_object_field_of_type(field_type): def repr_type_as_syntax_safe_fn(_type): if isinstance(_type, GraphQLList): - return 'list_' + repr_type_as_syntax_safe_fn(_type.of_type) + return "list_" + repr_type_as_syntax_safe_fn(_type.of_type) if isinstance(_type, GraphQLNonNull): - return 'non_null_' + repr_type_as_syntax_safe_fn(_type.of_type) + return "non_null_" + repr_type_as_syntax_safe_fn(_type.of_type) - return re.sub(r'[^a-zA-Z]', '_', str(_type)) + '_' + type(_type).__name__ + return re.sub(r"[^a-zA-Z]", "_", str(_type)) + "_" + type(_type).__name__ # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectFieldsMustHaveOutputTypes: - def accepts(self, type): assert schema_with_object_field_of_type(type) for i, type in enumerate(output_types): - exec('def test_accepts_an_output_type_as_an_object_field_type_{}(self): self.accepts(output_types[{}])' - .format(repr_type_as_syntax_safe_fn(type), i)) + exec( + "def test_accepts_an_output_type_as_an_object_field_type_{}(self): self.accepts(output_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def test_rejects_an_empty_object_field_type(self): with raises(AssertionError) as excinfo: schema_with_object_field_of_type(None) - assert str(excinfo.value) == 'BadObject.badField field type must be Output Type but got: None.' + assert ( + str(excinfo.value) + == "BadObject.badField field type must be Output Type but got: None." + ) def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_object_field_of_type(type) - assert str(excinfo.value) == 'BadObject.badField field type must be Output Type but got: {}.'.format(type) + assert str( + excinfo.value + ) == "BadObject.badField field type must be Output Type but got: {}.".format( + type + ) for i, type in enumerate(not_output_types): - exec('def test_rejects_a_non_output_type_as_an_object_field_type_{}(self): self.rejects(not_output_types[{}])' - .format(repr_type_as_syntax_safe_fn(type), i)) + exec( + "def test_rejects_a_non_output_type_as_an_object_field_type_{}(self): self.rejects(not_output_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def schema_with_object_implementing_type(implemented_type): BadObjectType = GraphQLObjectType( - name='BadObject', + name="BadObject", interfaces=[implemented_type], - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) return schema_with_field_type(BadObjectType) -not_interface_types = with_modifiers([ - SomeScalarType, - SomeEnumType, - SomeObjectType, - SomeUnionType, - SomeInputObjectType -]) +not_interface_types = with_modifiers( + [SomeScalarType, SomeEnumType, SomeObjectType, SomeUnionType, SomeInputObjectType] +) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectsCanOnlyImplementInterfaces: - def test_accepts_an_object_implementing_an_interface(self): AnotherInterfaceType = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={'f': GraphQLField(GraphQLString)} + fields={"f": GraphQLField(GraphQLString)}, ) assert schema_with_object_implementing_type(AnotherInterfaceType) @@ -986,37 +1055,40 @@ def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_object_implementing_type(type) - assert str(excinfo.value) == 'BadObject may only implement Interface types, it cannot implement: {}.'.format( - type) + assert str( + excinfo.value + ) == "BadObject may only implement Interface types, it cannot implement: {}.".format( + type + ) for i, type in enumerate(not_interface_types): exec( - 'def test_rejects_an_object_implementing_a_non_interface_type_{}(self):' - ' self.rejects(not_interface_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_an_object_implementing_a_non_interface_type_{}(self):" + " self.rejects(not_interface_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) -not_object_types = with_modifiers([ - SomeScalarType, - SomeEnumType, - SomeInterfaceType, - SomeUnionType, - SomeInputObjectType -]) +not_object_types = with_modifiers( + [ + SomeScalarType, + SomeEnumType, + SomeInterfaceType, + SomeUnionType, + SomeInputObjectType, + ] +) def schema_with_union_of_type(type): - BadUnionType = GraphQLUnionType( - name='BadUnion', - resolve_type=_none, - types=[type] - ) + BadUnionType = GraphQLUnionType(name="BadUnion", resolve_type=_none, types=[type]) return schema_with_field_type(BadUnionType) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_UnionMustRepresentObjectTypes: - def test_accepts_a_union_of_an_object_type(self): assert schema_with_union_of_type(SomeObjectType) @@ -1024,20 +1096,24 @@ def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_union_of_type(type) - assert str(excinfo.value) == 'BadUnion may only contain Object types, it cannot contain: {}.'.format(type) + assert str( + excinfo.value + ) == "BadUnion may only contain Object types, it cannot contain: {}.".format( + type + ) for i, type in enumerate(not_object_types): exec( - 'def test_rejects_a_union_of_non_object_type_{}(self):' - ' self.rejects(not_object_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_a_union_of_non_object_type_{}(self):" + " self.rejects(not_object_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def schema_with_interface_field_of_type(field_type): BadInterfaceType = GraphQLInterfaceType( - name='BadInterface', - fields={ - 'badField': GraphQLField(field_type) - } + name="BadInterface", fields={"badField": GraphQLField(field_type)} ) return schema_with_field_type(BadInterfaceType) @@ -1045,7 +1121,6 @@ def schema_with_interface_field_of_type(field_type): # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_InterfaceFieldsMustHaveOutputTypes: - def accepts(self, type): assert schema_with_interface_field_of_type(type) @@ -1053,34 +1128,41 @@ def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_interface_field_of_type(type) - assert str(excinfo.value) == 'BadInterface.badField field type must be Output Type but got: {}.'.format(type) + assert str( + excinfo.value + ) == "BadInterface.badField field type must be Output Type but got: {}.".format( + type + ) for i, type in enumerate(output_types): exec( - 'def test_accepts_an_output_type_as_an_interface_field_type_{}(self):' - ' self.accepts(output_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_an_output_type_as_an_interface_field_type_{}(self):" + " self.accepts(output_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def test_rejects_an_empty_interface_field_type(self): self.rejects(None) for i, type in enumerate(not_output_types): exec( - 'def test_rejects_a_non_output_type_as_an_interface_field_type_{}(self):' - ' self.rejects(not_output_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_a_non_output_type_as_an_interface_field_type_{}(self):" + " self.rejects(not_output_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) # noinspection PyMethodMayBeStatic,PyPep8Naming def schema_with_arg_of_type(arg_type): BadObjectType = GraphQLObjectType( - name='BadObject', + name="BadObject", fields={ - 'badField': GraphQLField( - type=GraphQLString, - args={ - 'badArg': GraphQLArgument(arg_type) - } + "badField": GraphQLField( + type=GraphQLString, args={"badArg": GraphQLArgument(arg_type)} ) - } + }, ) return schema_with_field_type(BadObjectType) @@ -1088,7 +1170,6 @@ def schema_with_arg_of_type(arg_type): # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_FieldArgumentsMustHaveInputTypes: - def accepts(self, type): assert schema_with_arg_of_type(type) @@ -1096,49 +1177,53 @@ def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_arg_of_type(type) - assert str(excinfo.value) == 'BadObject.badField(badArg:) argument type must be Input ' \ - 'Type but got: {}.'.format(type) + assert str( + excinfo.value + ) == "BadObject.badField(badArg:) argument type must be Input " "Type but got: {}.".format( + type + ) for i, type in enumerate(input_types): exec( - 'def test_accepts_an_input_type_as_a_field_arg_type_{}(self):' - ' self.accepts(input_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_an_input_type_as_a_field_arg_type_{}(self):" + " self.accepts(input_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def test_rejects_an_empty_field_arg_type(self): self.rejects(None) for i, type in enumerate(not_input_types): exec( - 'def test_rejects_a_not_input_type_as_a_field_arg_type_{}(self):' - ' self.rejects(not_input_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_a_not_input_type_as_a_field_arg_type_{}(self):" + " self.rejects(not_input_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def schema_with_input_field_of_type(input_field_type): BadInputObjectType = GraphQLInputObjectType( - name='BadInputObject', - fields={ - 'badField': GraphQLInputObjectField(input_field_type) - } + name="BadInputObject", + fields={"badField": GraphQLInputObjectField(input_field_type)}, ) return GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'f': GraphQLField( + "f": GraphQLField( type=GraphQLString, - args={ - 'badArg': GraphQLArgument(BadInputObjectType) - } + args={"badArg": GraphQLArgument(BadInputObjectType)}, ) - } + }, ) ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_InputObjectFieldsMustHaveInputTypes: - def accepts(self, type): assert schema_with_input_field_of_type(type) @@ -1146,45 +1231,48 @@ def rejects(self, type): with raises(AssertionError) as excinfo: schema_with_input_field_of_type(type) - assert str(excinfo.value) == 'BadInputObject.badField field type must be Input Type but got: {}.'.format(type) + assert str( + excinfo.value + ) == "BadInputObject.badField field type must be Input Type but got: {}.".format( + type + ) for i, type in enumerate(input_types): exec( - 'def test_accepts_an_input_type_as_an_input_field_type_{}(self):' - ' self.accepts(input_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_an_input_type_as_an_input_field_type_{}(self):" + " self.accepts(input_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) def test_rejects_an_empty_input_field_type(self): self.rejects(None) for i, type in enumerate(not_input_types): exec( - 'def test_rejects_non_input_type_as_an_input_field_type_{}(self):' - ' self.rejects(not_input_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_non_input_type_as_an_input_field_type_{}(self):" + " self.rejects(not_input_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) -types = with_modifiers([ - GraphQLString, - SomeScalarType, - SomeObjectType, - SomeUnionType, - SomeInterfaceType, - SomeEnumType, - SomeInputObjectType -]) - -not_types = [ - {}, - str, - None, - object(), - set(), - (), - [], -] +types = with_modifiers( + [ + GraphQLString, + SomeScalarType, + SomeObjectType, + SomeUnionType, + SomeInterfaceType, + SomeEnumType, + SomeInputObjectType, + ] +) +not_types = [{}, str, None, object(), set(), (), []] -class TestTypeSystem_ListMustAcceptGraphQLTypes: +class TestTypeSystem_ListMustAcceptGraphQLTypes: def accepts(self, type): assert GraphQLList(type) @@ -1192,17 +1280,21 @@ def rejects(self, type): with raises(AssertionError) as excinfo: GraphQLList(type) - assert str(excinfo.value) == 'Can only create List of a GraphQLType but got: {}.'.format(type) + assert str( + excinfo.value + ) == "Can only create List of a GraphQLType but got: {}.".format(type) for i, type in enumerate(types): exec( - 'def test_accepts_a_type_as_item_type_of_list_{}(self):' - ' self.accepts(types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_a_type_as_item_type_of_list_{}(self):" + " self.accepts(types[{}])".format(repr_type_as_syntax_safe_fn(type), i) + ) for i, type in enumerate(not_types): exec( - 'def test_accepts_a_type_as_item_type_of_list_{}(self):' - ' self.rejects(not_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_a_type_as_item_type_of_list_{}(self):" + " self.rejects(not_types[{}])".format(repr_type_as_syntax_safe_fn(type), i) + ) nullable_types = [ @@ -1217,18 +1309,11 @@ def rejects(self, type): GraphQLList(GraphQLNonNull(GraphQLString)), ] -not_nullable_types = [ - GraphQLNonNull(GraphQLString), - {}, - str, - None, - [] -] +not_nullable_types = [GraphQLNonNull(GraphQLString), {}, str, None, []] # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_NonNullMustAcceptGraphQLTypes: - def accepts(self, type): assert GraphQLNonNull(type) @@ -1236,438 +1321,397 @@ def rejects(self, type): with raises(AssertionError) as excinfo: GraphQLNonNull(type) - assert str(excinfo.value) == 'Can only create NonNull of a Nullable GraphQLType but got: {}.'.format(type) + assert str( + excinfo.value + ) == "Can only create NonNull of a Nullable GraphQLType but got: {}.".format( + type + ) for i, type in enumerate(nullable_types): exec( - 'def test_accepts_a_type_as_nullable_type_of_not_null_{}(self):' - ' self.accepts(nullable_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_accepts_a_type_as_nullable_type_of_not_null_{}(self):" + " self.accepts(nullable_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) for i, type in enumerate(not_nullable_types): exec( - 'def test_rejects_a_non_type_as_nullable_type_of_non_null_{}(self):' - ' self.rejects(not_nullable_types[{}])'.format(repr_type_as_syntax_safe_fn(type), i)) + "def test_rejects_a_non_type_as_nullable_type_of_non_null_{}(self):" + " self.rejects(not_nullable_types[{}])".format( + repr_type_as_syntax_safe_fn(type), i + ) + ) # noinspection PyMethodMayBeStatic,PyPep8Naming class TestTypeSystem_ObjectsMustAdhereToInterfacesTheyImplement: - def test_accepts_an_object_which_implements_an_interface(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) assert schema_with_field_type(AnotherObject) - def test_accepts_an_object_which_implements_an_interface_along_with_more_fields(self): + def test_accepts_an_object_which_implements_an_interface_along_with_more_fields( + self + ): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString), - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ), - 'anotherfield': GraphQLField(GraphQLString) - } + "anotherfield": GraphQLField(GraphQLString), + }, ) assert schema_with_field_type(AnotherObject) - def test_accepts_an_object_which_implements_an_interface_field_along_with_more_arguments(self): + def test_accepts_an_object_which_implements_an_interface_field_along_with_more_arguments( + self + ): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], fields={ - 'field': GraphQLField( + "field": GraphQLField( type=GraphQLString, args={ - 'input': GraphQLArgument(GraphQLString), - 'anotherInput': GraphQLArgument(GraphQLString), - } - ), - } + "input": GraphQLArgument(GraphQLString), + "anotherInput": GraphQLArgument(GraphQLString), + }, + ) + }, ) assert schema_with_field_type(AnotherObject) - def test_rejects_an_object_which_implements_an_interface_field_along_with_additional_required_arguments(self): + def test_rejects_an_object_which_implements_an_interface_field_along_with_additional_required_arguments( + self + ): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], fields={ - 'field': GraphQLField( + "field": GraphQLField( type=GraphQLString, args={ - 'input': GraphQLArgument(GraphQLString), - 'anotherInput': GraphQLArgument(GraphQLNonNull(GraphQLString)), - } - ), - } + "input": GraphQLArgument(GraphQLString), + "anotherInput": GraphQLArgument(GraphQLNonNull(GraphQLString)), + }, + ) + }, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherObject.field(anotherInput:) is of required type "String!" but ' \ - 'is not also provided by the interface AnotherInterface.field.' + assert ( + str(excinfo.value) + == 'AnotherObject.field(anotherInput:) is of required type "String!" but ' + "is not also provided by the interface AnotherInterface.field." + ) def test_rejects_an_object_missing_an_interface_field(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField( - type=GraphQLString, - args={ - 'input': GraphQLArgument(GraphQLString) - } + "field": GraphQLField( + type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) - } + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'anotherfield': GraphQLField(GraphQLString) - } + fields={"anotherfield": GraphQLField(GraphQLString)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == '"AnotherInterface" expects field "field" but "AnotherObject" does not provide it.' + assert ( + str(excinfo.value) + == '"AnotherInterface" expects field "field" but "AnotherObject" does not provide it.' + ) def test_rejects_an_object_with_an_incorrectly_typed_interface_field(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(SomeScalarType) - } + fields={"field": GraphQLField(SomeScalarType)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "String" ' \ - 'but AnotherObject.field provides type "SomeScalar".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "String" ' + 'but AnotherObject.field provides type "SomeScalar".' + ) def test_rejects_an_object_missing_an_interface_argument(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField(GraphQLString, args={ - 'input': GraphQLArgument(GraphQLString) - }) - } + "field": GraphQLField( + GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + ) + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects argument "input" ' \ - 'but AnotherObject.field does not provide it.' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects argument "input" ' + "but AnotherObject.field does not provide it." + ) def test_rejects_an_object_with_an_incorrectly_typed_interface_argument(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, fields={ - 'field': GraphQLField(GraphQLString, args={ - 'input': GraphQLArgument(GraphQLString) - }) - } + "field": GraphQLField( + GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + ) + }, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], fields={ - 'field': GraphQLField(GraphQLString, args={ - 'input': GraphQLArgument(SomeScalarType) - }) - - } + "field": GraphQLField( + GraphQLString, args={"input": GraphQLArgument(SomeScalarType)} + ) + }, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field(input:) expects type "String" ' \ - 'but AnotherObject.field(input:) provides type "SomeScalar".' + assert ( + str(excinfo.value) + == 'AnotherInterface.field(input:) expects type "String" ' + 'but AnotherObject.field(input:) provides type "SomeScalar".' + ) def test_rejects_an_object_with_an_incorrectly_typed_interface_field(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(SomeScalarType) - } + fields={"field": GraphQLField(SomeScalarType)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "String" ' \ - 'but AnotherObject.field provides type "SomeScalar".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "String" ' + 'but AnotherObject.field provides type "SomeScalar".' + ) def test_rejects_an_object_with_a_differently_typed_Interface_field(self): - TypeA = GraphQLObjectType( - name='A', - fields={ - 'foo': GraphQLField(GraphQLString) - } - ) - TypeB = GraphQLObjectType( - name='B', - fields={ - 'foo': GraphQLField(GraphQLString) - } - ) + TypeA = GraphQLObjectType(name="A", fields={"foo": GraphQLField(GraphQLString)}) + TypeB = GraphQLObjectType(name="B", fields={"foo": GraphQLField(GraphQLString)}) AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(TypeA) - } + fields={"field": GraphQLField(TypeA)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(TypeB) - } + fields={"field": GraphQLField(TypeB)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "A" but ' \ - 'AnotherObject.field provides type "B".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "A" but ' + 'AnotherObject.field provides type "B".' + ) def test_accepts_an_object_with_a_subtyped_interface_field_interface(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields=lambda: { - 'field': GraphQLField(AnotherInterface) - } + fields=lambda: {"field": GraphQLField(AnotherInterface)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields=lambda: { - 'field': GraphQLField(AnotherObject) - } + fields=lambda: {"field": GraphQLField(AnotherObject)}, ) assert schema_with_field_type(AnotherObject) def test_accepts_an_object_with_a_subtyped_interface_field_union(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields=lambda: { - 'field': GraphQLField(SomeUnionType) - } + fields=lambda: {"field": GraphQLField(SomeUnionType)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields=lambda: { - 'field': GraphQLField(SomeObjectType) - } + fields=lambda: {"field": GraphQLField(SomeObjectType)}, ) assert schema_with_field_type(AnotherObject) def test_accepts_an_object_with_an_equivalently_modified_interface_field_type(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString))) - } + fields={"field": GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString))) - - } + fields={"field": GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))}, ) assert schema_with_field_type(AnotherObject) def test_rejects_an_object_with_a_non_list_interface_field_list_type(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLList(GraphQLString)) - } + fields={"field": GraphQLField(GraphQLList(GraphQLString))}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "[String]" ' \ - 'but AnotherObject.field provides type "String".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "[String]" ' + 'but AnotherObject.field provides type "String".' + ) def test_rejects_a_object_with_a_list_interface_field_non_list_type(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLList(GraphQLString)) - - } + fields={"field": GraphQLField(GraphQLList(GraphQLString))}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "String" ' \ - 'but AnotherObject.field provides type "[String]".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "String" ' + 'but AnotherObject.field provides type "[String]".' + ) def test_accepts_an_object_with_a_subset_non_null_interface_field_type(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLNonNull(GraphQLString)) - } + fields={"field": GraphQLField(GraphQLNonNull(GraphQLString))}, ) assert schema_with_field_type(AnotherObject) def test_rejects_a_object_with_a_superset_nullable_interface_field_type(self): AnotherInterface = GraphQLInterfaceType( - name='AnotherInterface', + name="AnotherInterface", resolve_type=_none, - fields={ - 'field': GraphQLField(GraphQLNonNull(GraphQLString)) - } + fields={"field": GraphQLField(GraphQLNonNull(GraphQLString))}, ) AnotherObject = GraphQLObjectType( - name='AnotherObject', + name="AnotherObject", interfaces=[AnotherInterface], - fields={ - 'field': GraphQLField(GraphQLString) - - } + fields={"field": GraphQLField(GraphQLString)}, ) with raises(AssertionError) as excinfo: schema_with_field_type(AnotherObject) - assert str(excinfo.value) == 'AnotherInterface.field expects type "String!" but ' \ - 'AnotherObject.field provides type "String".' + assert ( + str(excinfo.value) == 'AnotherInterface.field expects type "String!" but ' + 'AnotherObject.field provides type "String".' + ) diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index d7953d80..f8eab077 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -2,21 +2,29 @@ from functools import reduce from ..utils.type_comparators import is_equal_type, is_type_sub_type_of -from .definition import (GraphQLArgument, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLUnionType, is_input_type, - is_output_type) +from .definition import ( + GraphQLArgument, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLUnionType, + is_input_type, + is_output_type, +) + if False: from typing import Any, List, Optional, Union class GraphQLTypeMap(OrderedDict): - - def __init__(self, - # type: Union[List[Optional[GraphQLObjectType]], List[GraphQLObjectType]] - types, - ): + def __init__( + self, + # type: Union[List[Optional[GraphQLObjectType]], List[GraphQLObjectType]] + types, + ): # type: (...) -> None super(GraphQLTypeMap, self).__init__() self.update(reduce(self.reducer, types, OrderedDict())) @@ -27,42 +35,45 @@ def __init__(self, for gql_type in self.values(): if isinstance(gql_type, GraphQLObjectType): for interface in gql_type.interfaces: - self._implementations.setdefault( - interface.name, []).append(gql_type) + self._implementations.setdefault(interface.name, []).append( + gql_type + ) # Enforce correct interface implementations. for type in self.values(): if isinstance(type, GraphQLObjectType): for interface in type.interfaces: - self.assert_object_implements_interface( - self, type, interface) + self.assert_object_implements_interface(self, type, interface) - def get_possible_types(self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, - ): + def get_possible_types( + self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + ): # type: (...) -> List[GraphQLObjectType] if isinstance(abstract_type, GraphQLUnionType): return abstract_type.types assert isinstance(abstract_type, GraphQLInterfaceType) return self._implementations.get(abstract_type.name, None) - def is_possible_type(self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, - possible_type, # type: GraphQLObjectType - ): + def is_possible_type( + self, + # type: Union[GraphQLInterfaceType, GraphQLUnionType] + abstract_type, + possible_type, # type: GraphQLObjectType + ): # type: (...) -> bool possible_types = self.get_possible_types(abstract_type) assert isinstance(possible_types, Sequence), ( - 'Could not find possible implementing types for ${} in ' + - 'schema. Check that schema.types is defined and is an array of' + - 'all possible types in the schema.' + "Could not find possible implementing types for ${} in " + + "schema. Check that schema.types is defined and is an array of" + + "all possible types in the schema." ).format(abstract_type) if not self._possible_type_map[abstract_type.name]: self._possible_type_map[abstract_type.name].update( - [p.name for p in possible_types]) + [p.name for p in possible_types] + ) return possible_type.name in self._possible_type_map[abstract_type.name] @@ -94,46 +105,53 @@ def reducer(cls, map, type): for t in type.interfaces: reduced_map = cls.reducer(reduced_map, t) - if isinstance(type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType)): + if isinstance( + type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType) + ): field_map = type.fields type_is_input = isinstance(type, GraphQLInputObjectType) for field_name, field in field_map.items(): if type_is_input: - assert isinstance(field, GraphQLInputObjectField), ( - '{}.{} must be an instance of GraphQLInputObjectField.'.format( - type, field_name) + assert isinstance( + field, GraphQLInputObjectField + ), "{}.{} must be an instance of GraphQLInputObjectField.".format( + type, field_name ) - assert is_input_type(field.type), ( - '{}.{} field type must be Input Type but got: {}.'.format( - type, field_name, field.type) + assert is_input_type( + field.type + ), "{}.{} field type must be Input Type but got: {}.".format( + type, field_name, field.type ) else: - assert is_output_type(field.type), ( - '{}.{} field type must be Output Type but got: {}.'.format( - type, field_name, field.type) + assert is_output_type( + field.type + ), "{}.{} field type must be Output Type but got: {}.".format( + type, field_name, field.type ) for arg_name, arg in field.args.items(): - assert isinstance(arg, (GraphQLArgument, GraphQLArgument)), ( - '{}.{}({}:) argument must be an instance of GraphQLArgument.'.format( - type, field_name, arg_name) + assert isinstance( + arg, (GraphQLArgument, GraphQLArgument) + ), "{}.{}({}:) argument must be an instance of GraphQLArgument.".format( + type, field_name, arg_name ) - assert is_input_type(arg.type), ( - '{}.{}({}:) argument type must be Input Type but got: {}.'.format(type, field_name, arg_name, - arg.type) + assert is_input_type( + arg.type + ), "{}.{}({}:) argument type must be Input Type but got: {}.".format( + type, field_name, arg_name, arg.type ) reduced_map = cls.reducer(reduced_map, arg.type) - reduced_map = cls.reducer( - reduced_map, getattr(field, 'type', None)) + reduced_map = cls.reducer(reduced_map, getattr(field, "type", None)) return reduced_map @classmethod - def assert_object_implements_interface(cls, - schema, # type: GraphQLTypeMap - object, # type: GraphQLObjectType - interface, # type: GraphQLInterfaceType - ): + def assert_object_implements_interface( + cls, + schema, # type: GraphQLTypeMap + object, # type: GraphQLObjectType + interface, # type: GraphQLInterfaceType + ): # type: (...) -> None object_field_map = object.fields interface_field_map = interface.fields @@ -141,13 +159,22 @@ def assert_object_implements_interface(cls, for field_name, interface_field in interface_field_map.items(): object_field = object_field_map.get(field_name) - assert object_field, '"{}" expects field "{}" but "{}" does not provide it.'.format( + assert ( + object_field + ), '"{}" expects field "{}" but "{}" does not provide it.'.format( interface, field_name, object ) - assert is_type_sub_type_of(schema, object_field.type, interface_field.type), ( - '{}.{} expects type "{}" but {}.{} provides type "{}".' - ).format(interface, field_name, interface_field.type, object, field_name, object_field.type) + assert is_type_sub_type_of( + schema, object_field.type, interface_field.type + ), ('{}.{} expects type "{}" but {}.{} provides type "{}".').format( + interface, + field_name, + interface_field.type, + object, + field_name, + object_field.type, + ) for arg_name, interface_arg in interface_field.args.items(): object_arg = object_field.args.get(arg_name) @@ -158,13 +185,29 @@ def assert_object_implements_interface(cls, assert is_equal_type(interface_arg.type, object_arg.type), ( '{}.{}({}:) expects type "{}" but {}.{}({}:) provides type "{}".' - ).format(interface, field_name, arg_name, interface_arg.type, object, field_name, arg_name, object_arg.type) + ).format( + interface, + field_name, + arg_name, + interface_arg.type, + object, + field_name, + arg_name, + object_arg.type, + ) for arg_name, object_arg in object_field.args.items(): interface_arg = interface_field.args.get(arg_name) if not interface_arg: assert not isinstance(object_arg.type, GraphQLNonNull), ( - '{}.{}({}:) is of required type ' + "{}.{}({}:) is of required type " '"{}" but is not also provided by the ' - 'interface {}.{}.' - ).format(object, field_name, arg_name, object_arg.type, interface, field_name) + "interface {}.{}." + ).format( + object, + field_name, + arg_name, + object_arg.type, + interface, + field_name, + ) diff --git a/graphql/utils/extend_schema.py b/graphql/utils/extend_schema.py index 5c3e031c..7f4868db 100644 --- a/graphql/utils/extend_schema.py +++ b/graphql/utils/extend_schema.py @@ -387,4 +387,3 @@ def build_field_type(type_ast): def cannot_execute_client_schema(*args, **kwargs): raise Exception("Client Schema cannot be used for execution.") - diff --git a/graphql/utils/suggestion_list.py b/graphql/utils/suggestion_list.py index 208f8e31..fc5ca554 100644 --- a/graphql/utils/suggestion_list.py +++ b/graphql/utils/suggestion_list.py @@ -2,10 +2,10 @@ def suggestion_list(inp, options): - ''' + """ Given an invalid input string and a list of valid options, returns a filtered list of valid options sorted based on their similarity with the input. - ''' + """ options_by_distance = OrderedDict() input_threshold = len(inp) / 2 @@ -15,11 +15,13 @@ def suggestion_list(inp, options): if distance <= threshold: options_by_distance[option] = distance - return sorted(list(options_by_distance.keys()), key=lambda k: options_by_distance[k]) + return sorted( + list(options_by_distance.keys()), key=lambda k: options_by_distance[k] + ) def lexical_distance(a, b): - ''' + """ Computes the lexical distance between strings A and B. The "distance" between two strings is given by counting the minimum number of edits needed to transform string A into string B. An edit can be an @@ -27,7 +29,7 @@ def lexical_distance(a, b): adjacent characters. This distance can be useful for detecting typos in input or sorting @returns distance in number of edits - ''' + """ d = [[i] for i in range(len(a) + 1)] or [] d_len = len(d) or 1 @@ -42,15 +44,9 @@ def lexical_distance(a, b): for j in range(1, len(b) + 1): cost = 0 if a[i - 1] == b[j - 1] else 1 - d[i][j] = min( - d[i - 1][j] + 1, - d[i][j - 1] + 1, - d[i - 1][j - 1] + cost - ) + d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost) - if (i > 1 and j < 1 and - a[i - 1] == b[j - 2] and - a[i - 2] == b[j - 1]): + if i > 1 and j < 1 and a[i - 1] == b[j - 2] and a[i - 2] == b[j - 1]: d[i][j] = min(d[i][j], d[i - 2][j - 2] + cost) return d[len(a)][len(b)] diff --git a/graphql/utils/tests/test_ast_from_value.py b/graphql/utils/tests/test_ast_from_value.py index 5ac23072..b25f1ed1 100644 --- a/graphql/utils/tests/test_ast_from_value.py +++ b/graphql/utils/tests/test_ast_from_value.py @@ -1,9 +1,13 @@ from collections import OrderedDict from graphql.language import ast -from graphql.type.definition import (GraphQLEnumType, GraphQLEnumValue, - GraphQLInputObjectField, - GraphQLInputObjectType, GraphQLList) +from graphql.type.definition import ( + GraphQLEnumType, + GraphQLEnumValue, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLList, +) from graphql.type.scalars import GraphQLFloat from graphql.utils.ast_from_value import ast_from_value @@ -14,90 +18,72 @@ def test_converts_boolean_values_to_asts(): def test_converts_numeric_values_to_asts(): - assert ast_from_value(123) == ast.IntValue('123') - assert ast_from_value(123.0) == ast.IntValue('123') - assert ast_from_value(123.5) == ast.FloatValue('123.5') - assert ast_from_value(1e4) == ast.IntValue('10000') - assert ast_from_value(1e40) == ast.FloatValue('1e+40') + assert ast_from_value(123) == ast.IntValue("123") + assert ast_from_value(123.0) == ast.IntValue("123") + assert ast_from_value(123.5) == ast.FloatValue("123.5") + assert ast_from_value(1e4) == ast.IntValue("10000") + assert ast_from_value(1e40) == ast.FloatValue("1e+40") def test_it_converts_numeric_values_to_float_asts(): - assert ast_from_value(123, GraphQLFloat) == ast.FloatValue('123.0') - assert ast_from_value(123.0, GraphQLFloat) == ast.FloatValue('123.0') - assert ast_from_value(123.5, GraphQLFloat) == ast.FloatValue('123.5') - assert ast_from_value(1e4, GraphQLFloat) == ast.FloatValue('10000.0') - assert ast_from_value(1e40, GraphQLFloat) == ast.FloatValue('1e+40') + assert ast_from_value(123, GraphQLFloat) == ast.FloatValue("123.0") + assert ast_from_value(123.0, GraphQLFloat) == ast.FloatValue("123.0") + assert ast_from_value(123.5, GraphQLFloat) == ast.FloatValue("123.5") + assert ast_from_value(1e4, GraphQLFloat) == ast.FloatValue("10000.0") + assert ast_from_value(1e40, GraphQLFloat) == ast.FloatValue("1e+40") def test_it_converts_string_values_to_asts(): - assert ast_from_value('hello') == ast.StringValue('hello') - assert ast_from_value('VALUE') == ast.StringValue('VALUE') - assert ast_from_value(u'VAL\nUE') == ast.StringValue('VAL\\nUE') - assert ast_from_value('VAL\nUE') == ast.StringValue('VAL\\nUE') - assert ast_from_value('123') == ast.StringValue('123') + assert ast_from_value("hello") == ast.StringValue("hello") + assert ast_from_value("VALUE") == ast.StringValue("VALUE") + assert ast_from_value(u"VAL\nUE") == ast.StringValue("VAL\\nUE") + assert ast_from_value("VAL\nUE") == ast.StringValue("VAL\\nUE") + assert ast_from_value("123") == ast.StringValue("123") my_enum = GraphQLEnumType( - 'MyEnum', { - 'HELLO': GraphQLEnumValue(1), - 'GOODBYE': GraphQLEnumValue(2) - } + "MyEnum", {"HELLO": GraphQLEnumValue(1), "GOODBYE": GraphQLEnumValue(2)} ) def test_converts_string_values_to_enum_asts_if_possible(): - assert ast_from_value('hello', my_enum) == ast.EnumValue('hello') - assert ast_from_value('HELLO', my_enum) == ast.EnumValue('HELLO') - assert ast_from_value('VAL\nUE', my_enum) == ast.StringValue('VAL\\nUE') - assert ast_from_value('123', my_enum) == ast.StringValue('123') + assert ast_from_value("hello", my_enum) == ast.EnumValue("hello") + assert ast_from_value("HELLO", my_enum) == ast.EnumValue("HELLO") + assert ast_from_value("VAL\nUE", my_enum) == ast.StringValue("VAL\\nUE") + assert ast_from_value("123", my_enum) == ast.StringValue("123") def test_converts_array_values_to_list_asts(): - assert ast_from_value(['FOO', 'BAR']) == ast.ListValue( - values=[ - ast.StringValue('FOO'), - ast.StringValue('BAR') - ] + assert ast_from_value(["FOO", "BAR"]) == ast.ListValue( + values=[ast.StringValue("FOO"), ast.StringValue("BAR")] ) def test_converts_list_singletons(): - assert ast_from_value('FOO', GraphQLList(my_enum)) == ast.EnumValue('FOO') + assert ast_from_value("FOO", GraphQLList(my_enum)) == ast.EnumValue("FOO") def test_converts_input_objects(): - value = OrderedDict([ - ('foo', 3), - ('bar', 'HELLO') - ]) + value = OrderedDict([("foo", 3), ("bar", "HELLO")]) assert ast_from_value(value) == ast.ObjectValue( fields=[ - ast.ObjectField( - name=ast.Name('foo'), - value=ast.IntValue('3') - ), - ast.ObjectField( - name=ast.Name('bar'), - value=ast.StringValue('HELLO') - ) + ast.ObjectField(name=ast.Name("foo"), value=ast.IntValue("3")), + ast.ObjectField(name=ast.Name("bar"), value=ast.StringValue("HELLO")), ] ) - input_obj = GraphQLInputObjectType('MyInputObj', { - 'foo': GraphQLInputObjectField(GraphQLFloat), - 'bar': GraphQLInputObjectField(my_enum) - }) + input_obj = GraphQLInputObjectType( + "MyInputObj", + { + "foo": GraphQLInputObjectField(GraphQLFloat), + "bar": GraphQLInputObjectField(my_enum), + }, + ) assert ast_from_value(value, input_obj) == ast.ObjectValue( fields=[ - ast.ObjectField( - name=ast.Name('foo'), - value=ast.FloatValue('3.0') - ), - ast.ObjectField( - name=ast.Name('bar'), - value=ast.EnumValue('HELLO') - ) + ast.ObjectField(name=ast.Name("foo"), value=ast.FloatValue("3.0")), + ast.ObjectField(name=ast.Name("bar"), value=ast.EnumValue("HELLO")), ] ) diff --git a/graphql/utils/tests/test_ast_to_code.py b/graphql/utils/tests/test_ast_to_code.py index e86a4ee7..29d62d46 100644 --- a/graphql/utils/tests/test_ast_to_code.py +++ b/graphql/utils/tests/test_ast_to_code.py @@ -11,7 +11,8 @@ def test_ast_to_code_using_kitchen_sink(): code_ast = ast_to_code(doc) source = Source(fixtures.KITCHEN_SINK) - def loc(start, end): return Loc(start, end, source) + def loc(start, end): + return Loc(start, end, source) - parsed_code_ast = eval(code_ast, {}, {'ast': ast, 'loc': loc}) + parsed_code_ast = eval(code_ast, {}, {"ast": ast, "loc": loc}) assert doc == parsed_code_ast diff --git a/graphql/utils/tests/test_ast_to_dict.py b/graphql/utils/tests/test_ast_to_dict.py index 6c4cdc49..cc480964 100644 --- a/graphql/utils/tests/test_ast_to_dict.py +++ b/graphql/utils/tests/test_ast_to_dict.py @@ -4,19 +4,19 @@ def test_converts_simple_ast_to_dict(): - node = ast.Name(value='test', loc=Loc(start=5, end=10)) + node = ast.Name(value="test", loc=Loc(start=5, end=10)) - assert ast_to_dict(node) == {'kind': 'Name', 'value': 'test'} + assert ast_to_dict(node) == {"kind": "Name", "value": "test"} assert ast_to_dict(node, include_loc=True) == { - 'kind': 'Name', 'value': 'test', 'loc': { - 'start': 5, - 'end': 10 - } + "kind": "Name", + "value": "test", + "loc": {"start": 5, "end": 10}, } def test_converts_nested_ast_to_dict(): - parsed_ast = parse(''' + parsed_ast = parse( + """ query x { someQuery(arg: "x") { a @@ -27,88 +27,111 @@ def test_converts_nested_ast_to_dict(): d } } - ''') + """ + ) - expected_ast_dict = {'definitions': [{'directives': [], - 'kind': 'OperationDefinition', - 'name': {'kind': 'Name', 'value': 'x'}, - 'operation': 'query', - 'selection_set': {'kind': 'SelectionSet', - 'selections': [{'alias': None, - 'arguments': [{'kind': 'Argument', - 'name': {'kind': 'Name', - 'value': 'arg'}, - 'value': { - 'kind': 'StringValue', - 'value': 'x'}}], - 'directives': [], - 'kind': 'Field', - 'name': {'kind': 'Name', - 'value': 'someQuery'}, - 'selection_set': {'kind': 'SelectionSet', - 'selections': [ - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': { - 'kind': 'Name', - 'value': 'a'}, - 'selection_set': None}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': { - 'kind': 'Name', - 'value': 'b'}, - 'selection_set': None}]}}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': {'kind': 'Name', - 'value': 'fragment'}, - 'selection_set': None}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': {'kind': 'Name', - 'value': 'Test'}, - 'selection_set': None}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': {'kind': 'Name', - 'value': 'on'}, - 'selection_set': None}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': {'kind': 'Name', - 'value': 'TestFoo'}, - 'selection_set': {'kind': 'SelectionSet', - 'selections': [ - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': { - 'kind': 'Name', - 'value': 'c'}, - 'selection_set': None}, - {'alias': None, - 'arguments': [], - 'directives': [], - 'kind': 'Field', - 'name': { - 'kind': 'Name', - 'value': 'd'}, - 'selection_set': None}]}}]}, - 'variable_definitions': []}], - 'kind': 'Document'} + expected_ast_dict = { + "definitions": [ + { + "directives": [], + "kind": "OperationDefinition", + "name": {"kind": "Name", "value": "x"}, + "operation": "query", + "selection_set": { + "kind": "SelectionSet", + "selections": [ + { + "alias": None, + "arguments": [ + { + "kind": "Argument", + "name": {"kind": "Name", "value": "arg"}, + "value": {"kind": "StringValue", "value": "x"}, + } + ], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "someQuery"}, + "selection_set": { + "kind": "SelectionSet", + "selections": [ + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "a"}, + "selection_set": None, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "b"}, + "selection_set": None, + }, + ], + }, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "fragment"}, + "selection_set": None, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "Test"}, + "selection_set": None, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "on"}, + "selection_set": None, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "TestFoo"}, + "selection_set": { + "kind": "SelectionSet", + "selections": [ + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "c"}, + "selection_set": None, + }, + { + "alias": None, + "arguments": [], + "directives": [], + "kind": "Field", + "name": {"kind": "Name", "value": "d"}, + "selection_set": None, + }, + ], + }, + }, + ], + }, + "variable_definitions": [], + } + ], + "kind": "Document", + } assert ast_to_dict(parsed_ast) == expected_ast_dict diff --git a/graphql/utils/tests/test_build_ast_schema.py b/graphql/utils/tests/test_build_ast_schema.py index 17032f55..6f84aa64 100644 --- a/graphql/utils/tests/test_build_ast_schema.py +++ b/graphql/utils/tests/test_build_ast_schema.py @@ -4,8 +4,11 @@ from graphql.utils.build_ast_schema import build_ast_schema from graphql.utils.schema_printer import print_schema -from ...type import (GraphQLDeprecatedDirective, GraphQLIncludeDirective, - GraphQLSkipDirective) +from ...type import ( + GraphQLDeprecatedDirective, + GraphQLIncludeDirective, + GraphQLSkipDirective, +) def cycle_output(body): @@ -14,11 +17,11 @@ def cycle_output(body): and then finally printing that GraphQL into the DSL""" ast = parse(body) schema = build_ast_schema(ast) - return '\n' + print_schema(schema) + return "\n" + print_schema(schema) def test_simple_type(): - body = ''' + body = """ schema { query: HelloScalars } @@ -30,13 +33,13 @@ def test_simple_type(): id: ID bool: Boolean } -''' +""" output = cycle_output(body) assert output == body def test_with_directives(): - body = ''' + body = """ schema { query: Hello } @@ -46,13 +49,13 @@ def test_with_directives(): type Hello { str: String } -''' +""" output = cycle_output(body) assert output == body def test_maintains_skip_and_include_directives(): - body = ''' + body = """ schema { query: Hello } @@ -60,17 +63,17 @@ def test_maintains_skip_and_include_directives(): type Hello { str: String } - ''' + """ schema = build_ast_schema(parse(body)) assert len(schema.get_directives()) == 3 - assert schema.get_directive('skip') == GraphQLSkipDirective - assert schema.get_directive('include') == GraphQLIncludeDirective - assert schema.get_directive('deprecated') == GraphQLDeprecatedDirective + assert schema.get_directive("skip") == GraphQLSkipDirective + assert schema.get_directive("include") == GraphQLIncludeDirective + assert schema.get_directive("deprecated") == GraphQLDeprecatedDirective def test_overriding_directives_excludes_specified(): - body = ''' + body = """ schema { query: Hello } @@ -82,20 +85,20 @@ def test_overriding_directives_excludes_specified(): type Hello { str: String } - ''' + """ schema = build_ast_schema(parse(body)) assert len(schema.get_directives()) == 3 - assert schema.get_directive('skip') != GraphQLSkipDirective - assert schema.get_directive('skip') is not None - assert schema.get_directive('include') != GraphQLIncludeDirective - assert schema.get_directive('include') is not None - assert schema.get_directive('deprecated') != GraphQLDeprecatedDirective - assert schema.get_directive('deprecated') is not None + assert schema.get_directive("skip") != GraphQLSkipDirective + assert schema.get_directive("skip") is not None + assert schema.get_directive("include") != GraphQLIncludeDirective + assert schema.get_directive("include") is not None + assert schema.get_directive("deprecated") != GraphQLDeprecatedDirective + assert schema.get_directive("deprecated") is not None def test_overriding_skip_directive_excludes_built_in_one(): - body = ''' + body = """ schema { query: Hello } @@ -105,18 +108,18 @@ def test_overriding_skip_directive_excludes_built_in_one(): type Hello { str: String } - ''' + """ schema = build_ast_schema(parse(body)) assert len(schema.get_directives()) == 3 - assert schema.get_directive('skip') != GraphQLSkipDirective - assert schema.get_directive('skip') is not None - assert schema.get_directive('include') == GraphQLIncludeDirective - assert schema.get_directive('deprecated') == GraphQLDeprecatedDirective + assert schema.get_directive("skip") != GraphQLSkipDirective + assert schema.get_directive("skip") is not None + assert schema.get_directive("include") == GraphQLIncludeDirective + assert schema.get_directive("deprecated") == GraphQLDeprecatedDirective def test_overriding_include_directive_excludes_built_in_one(): - body = ''' + body = """ schema { query: Hello } @@ -126,18 +129,18 @@ def test_overriding_include_directive_excludes_built_in_one(): type Hello { str: String } - ''' + """ schema = build_ast_schema(parse(body)) assert len(schema.get_directives()) == 3 - assert schema.get_directive('skip') == GraphQLSkipDirective - assert schema.get_directive('deprecated') == GraphQLDeprecatedDirective - assert schema.get_directive('include') != GraphQLIncludeDirective - assert schema.get_directive('include') is not None + assert schema.get_directive("skip") == GraphQLSkipDirective + assert schema.get_directive("deprecated") == GraphQLDeprecatedDirective + assert schema.get_directive("include") != GraphQLIncludeDirective + assert schema.get_directive("include") is not None def test_adding_directives_maintains_skip_and_include_directives(): - body = ''' + body = """ schema { query: Hello } @@ -147,17 +150,17 @@ def test_adding_directives_maintains_skip_and_include_directives(): type Hello { str: String } - ''' + """ schema = build_ast_schema(parse(body)) assert len(schema.get_directives()) == 4 - assert schema.get_directive('skip') == GraphQLSkipDirective - assert schema.get_directive('include') == GraphQLIncludeDirective - assert schema.get_directive('deprecated') == GraphQLDeprecatedDirective + assert schema.get_directive("skip") == GraphQLSkipDirective + assert schema.get_directive("include") == GraphQLIncludeDirective + assert schema.get_directive("deprecated") == GraphQLDeprecatedDirective def test_type_modifiers(): - body = ''' + body = """ schema { query: HelloScalars } @@ -169,13 +172,13 @@ def test_type_modifiers(): nonNullListOfStrs: [String]! nonNullListOfNonNullStrs: [String!]! } -''' +""" output = cycle_output(body) assert output == body def test_recursive_type(): - body = ''' + body = """ schema { query: Recurse } @@ -184,13 +187,13 @@ def test_recursive_type(): str: String recurse: Recurse } -''' +""" output = cycle_output(body) assert output == body def test_two_types_circular(): - body = ''' + body = """ schema { query: TypeOne } @@ -204,13 +207,13 @@ def test_two_types_circular(): str: String typeOne: TypeOne } -''' +""" output = cycle_output(body) assert output == body def test_single_argument_field(): - body = ''' + body = """ schema { query: Hello } @@ -222,13 +225,13 @@ def test_single_argument_field(): booleanToStr(bool: Boolean): String strToStr(bool: String): String } -''' +""" output = cycle_output(body) assert output == body def test_simple_type_with_multiple_arguments(): - body = ''' + body = """ schema { query: Hello } @@ -236,13 +239,13 @@ def test_simple_type_with_multiple_arguments(): type Hello { str(int: Int, bool: Boolean): String } -''' +""" output = cycle_output(body) assert output == body def test_simple_type_with_interface(): - body = ''' + body = """ schema { query: HelloInterface } @@ -254,13 +257,13 @@ def test_simple_type_with_interface(): interface WorldInterface { str: String } -''' +""" output = cycle_output(body) assert output == body def test_simple_output_enum(): - body = ''' + body = """ schema { query: OutputEnumRoot } @@ -272,13 +275,13 @@ def test_simple_output_enum(): type OutputEnumRoot { hello: Hello } -''' +""" output = cycle_output(body) assert output == body def test_simple_input_enum(): - body = ''' + body = """ schema { query: InputEnumRoot } @@ -290,13 +293,13 @@ def test_simple_input_enum(): type InputEnumRoot { str(hello: Hello): String } -''' +""" output = cycle_output(body) assert output == body def test_multiple_value_enum(): - body = ''' + body = """ schema { query: OutputEnumRoot } @@ -309,13 +312,13 @@ def test_multiple_value_enum(): type OutputEnumRoot { hello: Hello } -''' +""" output = cycle_output(body) assert output == body def test_simple_union(): - body = ''' + body = """ schema { query: Root } @@ -329,13 +332,13 @@ def test_simple_union(): type World { str: String } -''' +""" output = cycle_output(body) assert output == body def test_multiple_union(): - body = ''' + body = """ schema { query: Root } @@ -353,13 +356,13 @@ def test_multiple_union(): type WorldTwo { str: String } -''' +""" output = cycle_output(body) assert output == body def test_custom_scalar(): - body = ''' + body = """ schema { query: Root } @@ -369,13 +372,13 @@ def test_custom_scalar(): type Root { customScalar: CustomScalar } -''' +""" output = cycle_output(body) assert output == body def test_input_object(): - body = ''' + body = """ schema { query: Root } @@ -387,13 +390,15 @@ def test_input_object(): type Root { field(in: Input): String } -''' +""" output = cycle_output(body) assert output == body def test_input_types_are_read(): - schema = build_ast_schema(parse(""" + schema = build_ast_schema( + parse( + """ schema { query: Query } @@ -405,14 +410,18 @@ def test_input_types_are_read(): input Input { id: Int } - """)) + """ + ) + ) input_type = schema.get_type("Input") assert input_type.fields["id"].type == GraphQLInt def test_input_types_can_be_recursive(): - schema = build_ast_schema(parse(""" + schema = build_ast_schema( + parse( + """ schema { query: Query } @@ -424,14 +433,16 @@ def test_input_types_can_be_recursive(): input Input { id: Input } - """)) + """ + ) + ) input_type = schema.get_type("Input") assert input_type.fields["id"].type == input_type def test_simple_argument_field_with_default(): - body = ''' + body = """ schema { query: Hello } @@ -439,13 +450,13 @@ def test_simple_argument_field_with_default(): type Hello { str(int: Int = 2): String } -''' +""" output = cycle_output(body) assert output == body def test_simple_type_with_mutation(): - body = ''' + body = """ schema { query: HelloScalars mutation: Mutation @@ -460,13 +471,13 @@ def test_simple_type_with_mutation(): type Mutation { addHelloScalars(str: String, int: Int, bool: Boolean): HelloScalars } -''' +""" output = cycle_output(body) assert output == body def test_simple_type_with_subscription(): - body = ''' + body = """ schema { query: HelloScalars subscription: Subscription @@ -481,13 +492,13 @@ def test_simple_type_with_subscription(): type Subscription { subscribeHelloScalars(str: String, int: Int, bool: Boolean): HelloScalars } -''' +""" output = cycle_output(body) assert output == body def test_unreferenced_type_implementing_referenced_interface(): - body = ''' + body = """ schema { query: Query } @@ -503,13 +514,13 @@ def test_unreferenced_type_implementing_referenced_interface(): type Query { iface: Iface } -''' +""" output = cycle_output(body) assert output == body def test_unreferenced_type_implementing_referenced_union(): - body = ''' + body = """ schema { query: Query } @@ -523,13 +534,13 @@ def test_unreferenced_type_implementing_referenced_union(): } union Union = Concrete -''' +""" output = cycle_output(body) assert output == body def test_supports_deprecated_directive(): - body = ''' + body = """ schema { query: Query } @@ -545,27 +556,27 @@ def test_supports_deprecated_directive(): field2: Int @deprecated(reason: "Because I said so") enum: MyEnum } -''' +""" output = cycle_output(body) assert output == body def test_requires_a_schema_definition(): - body = ''' + body = """ type Hello { bar: Bar } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide a schema definition.' == str(excinfo.value) + assert "Must provide a schema definition." == str(excinfo.value) def test_allows_only_a_single_schema_definition(): - body = ''' + body = """ schema { query: Hello } @@ -577,16 +588,16 @@ def test_allows_only_a_single_schema_definition(): type Hello { bar: Bar } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide only one schema definition.' == str(excinfo.value) + assert "Must provide only one schema definition." == str(excinfo.value) def test_requires_a_query_type(): - body = ''' + body = """ schema { mutation: Hello } @@ -594,16 +605,16 @@ def test_requires_a_query_type(): type Hello { bar: Bar } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide schema definition with query type.' == str(excinfo.value) + assert "Must provide schema definition with query type." == str(excinfo.value) def test_allows_only_a_single_query_type(): - body = ''' + body = """ schema { query: Hello query: Yellow @@ -616,16 +627,16 @@ def test_allows_only_a_single_query_type(): type Yellow { isColor: Boolean } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide only one query type in schema.' == str(excinfo.value) + assert "Must provide only one query type in schema." == str(excinfo.value) def test_allows_only_a_single_mutation_type(): - body = ''' + body = """ schema { query: Hello mutation: Hello @@ -639,16 +650,16 @@ def test_allows_only_a_single_mutation_type(): type Yellow { isColor: Boolean } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide only one mutation type in schema.' == str(excinfo.value) + assert "Must provide only one mutation type in schema." == str(excinfo.value) def test_allows_only_a_single_subscription_type(): - body = ''' + body = """ schema { query: Hello subscription: Hello @@ -662,16 +673,16 @@ def test_allows_only_a_single_subscription_type(): type Yellow { isColor: Boolean } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Must provide only one subscription type in schema.' == str(excinfo.value) + assert "Must provide only one subscription type in schema." == str(excinfo.value) def test_unknown_type_referenced(): - body = ''' + body = """ schema { query: Hello } @@ -679,7 +690,7 @@ def test_unknown_type_referenced(): type Hello { bar: Bar } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) @@ -688,14 +699,14 @@ def test_unknown_type_referenced(): def test_unknown_type_in_union_list(): - body = ''' + body = """ schema { query: Hello } union TestUnion = Bar type Hello { testUnion: TestUnion } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) @@ -704,7 +715,7 @@ def test_unknown_type_in_union_list(): def test_unknown_query_type(): - body = ''' + body = """ schema { query: Wat } @@ -712,7 +723,7 @@ def test_unknown_query_type(): type Hello { str: String } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) @@ -721,7 +732,7 @@ def test_unknown_query_type(): def test_unknown_mutation_type(): - body = ''' + body = """ schema { query: Hello mutation: Wat @@ -730,7 +741,7 @@ def test_unknown_mutation_type(): type Hello { str: String } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) @@ -739,7 +750,7 @@ def test_unknown_mutation_type(): def test_unknown_subscription_type(): - body = ''' + body = """ schema { query: Hello mutation: Wat @@ -753,16 +764,18 @@ def test_unknown_subscription_type(): type Wat { str: String } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) - assert 'Specified subscription type "Awesome" not found in document' in str(excinfo.value) + assert 'Specified subscription type "Awesome" not found in document' in str( + excinfo.value + ) def test_does_not_consider_query_names(): - body = ''' + body = """ schema { query: Foo } @@ -770,7 +783,7 @@ def test_does_not_consider_query_names(): type Hello { str: String } -''' +""" doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) @@ -779,11 +792,11 @@ def test_does_not_consider_query_names(): def test_does_not_consider_fragment_names(): - body = '''schema { + body = """schema { query: Foo } -fragment Foo on Type { field } ''' +fragment Foo on Type { field } """ doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc) diff --git a/graphql/utils/tests/test_build_client_schema.py b/graphql/utils/tests/test_build_client_schema.py index 6abecb3e..5e2f496a 100644 --- a/graphql/utils/tests/test_build_client_schema.py +++ b/graphql/utils/tests/test_build_client_schema.py @@ -4,13 +4,26 @@ from graphql import graphql from graphql.error import format_error -from graphql.type import (GraphQLArgument, GraphQLBoolean, GraphQLEnumType, - GraphQLEnumValue, GraphQLField, GraphQLFloat, - GraphQLID, GraphQLInputObjectField, - GraphQLInputObjectType, GraphQLInt, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLScalarType, GraphQLSchema, - GraphQLString, GraphQLUnionType) +from graphql.type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLFloat, + GraphQLID, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) from graphql.type.directives import GraphQLDirective from graphql.utils.build_client_schema import build_client_schema from graphql.utils.introspection_query import introspection_query @@ -30,11 +43,13 @@ def _test_schema(server_schema): def test_it_builds_a_simple_schema(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Simple', - description='This is a simple type', + name="Simple", + description="This is a simple type", fields={ - 'string': GraphQLField(GraphQLString, description='This is a string field') - } + "string": GraphQLField( + GraphQLString, description="This is a string field" + ) + }, ) ) _test_schema(schema) @@ -42,30 +57,31 @@ def test_it_builds_a_simple_schema(): def test_builds_a_simple_schema_with_both_operation_types(): QueryType = GraphQLObjectType( - name='QueryType', - description='This is a simple query type', + name="QueryType", + description="This is a simple query type", fields={ - 'string': GraphQLField(GraphQLString, description='This is a string field.') - } + "string": GraphQLField(GraphQLString, description="This is a string field.") + }, ) MutationType = GraphQLObjectType( - name='MutationType', - description='This is a simple mutation type', + name="MutationType", + description="This is a simple mutation type", fields={ - 'setString': GraphQLField(GraphQLString, description='Set the string field', args={ - 'value': GraphQLArgument(GraphQLString) - }) - } + "setString": GraphQLField( + GraphQLString, + description="Set the string field", + args={"value": GraphQLArgument(GraphQLString)}, + ) + }, ) SubscriptionType = GraphQLObjectType( - name='SubscriptionType', - description='This is a simple subscription type', + name="SubscriptionType", + description="This is a simple subscription type", fields={ - 'string': GraphQLField( - type=GraphQLString, - description='This is a string field' + "string": GraphQLField( + type=GraphQLString, description="This is a string field" ) - } + }, ) schema = GraphQLSchema(QueryType, MutationType, SubscriptionType) @@ -73,42 +89,38 @@ def test_builds_a_simple_schema_with_both_operation_types(): def test_uses_built_in_scalars_when_possible(): - customScalar = GraphQLScalarType( - name='CustomScalar', - serialize=lambda: None - ) + customScalar = GraphQLScalarType(name="CustomScalar", serialize=lambda: None) schema = GraphQLSchema( query=GraphQLObjectType( - name='Scalars', - fields=OrderedDict([ - ('int', GraphQLField(GraphQLInt)), - ('float', GraphQLField(GraphQLFloat)), - ('string', GraphQLField(GraphQLString)), - ('boolean', GraphQLField(GraphQLBoolean)), - ('id', GraphQLField(GraphQLID)), - ('custom', GraphQLField(customScalar)), - ]) + name="Scalars", + fields=OrderedDict( + [ + ("int", GraphQLField(GraphQLInt)), + ("float", GraphQLField(GraphQLFloat)), + ("string", GraphQLField(GraphQLString)), + ("boolean", GraphQLField(GraphQLBoolean)), + ("id", GraphQLField(GraphQLID)), + ("custom", GraphQLField(customScalar)), + ] + ), ) ) client_schema = _test_schema(schema) - assert client_schema.get_type('Int') == GraphQLInt - assert client_schema.get_type('Float') == GraphQLFloat - assert client_schema.get_type('String') == GraphQLString - assert client_schema.get_type('Boolean') == GraphQLBoolean - assert client_schema.get_type('ID') == GraphQLID + assert client_schema.get_type("Int") == GraphQLInt + assert client_schema.get_type("Float") == GraphQLFloat + assert client_schema.get_type("String") == GraphQLString + assert client_schema.get_type("Boolean") == GraphQLBoolean + assert client_schema.get_type("ID") == GraphQLID - assert client_schema.get_type('CustomScalar') != customScalar + assert client_schema.get_type("CustomScalar") != customScalar def test_builds_a_schema_with_a_recursive_type_reference(): recurType = GraphQLObjectType( - name='Recur', - fields=lambda: { - 'recur': GraphQLField(recurType) - } + name="Recur", fields=lambda: {"recur": GraphQLField(recurType)} ) schema = GraphQLSchema(query=recurType) @@ -117,63 +129,53 @@ def test_builds_a_schema_with_a_recursive_type_reference(): def test_builds_a_schema_with_a_circular_type_reference(): DogType = GraphQLObjectType( - name='Dog', - fields=lambda: { - 'bestFriend': GraphQLField(HumanType) - } + name="Dog", fields=lambda: {"bestFriend": GraphQLField(HumanType)} ) HumanType = GraphQLObjectType( - name='Human', - fields=lambda: { - 'bestFriend': GraphQLField(DogType) - } + name="Human", fields=lambda: {"bestFriend": GraphQLField(DogType)} ) - schema = GraphQLSchema(query=GraphQLObjectType( - name='Circular', - fields=OrderedDict([ - ('dog', GraphQLField(DogType)), - ('human', GraphQLField(HumanType)), - ]) - )) + schema = GraphQLSchema( + query=GraphQLObjectType( + name="Circular", + fields=OrderedDict( + [("dog", GraphQLField(DogType)), ("human", GraphQLField(HumanType))] + ), + ) + ) _test_schema(schema) def test_builds_a_schema_with_an_interface(): FriendlyType = GraphQLInterfaceType( - name='Friendly', + name="Friendly", resolve_type=lambda: None, fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType, description='The best friend of this friendly thing.') - } + "bestFriend": GraphQLField( + FriendlyType, description="The best friend of this friendly thing." + ) + }, ) DogType = GraphQLObjectType( - name='DogType', + name="DogType", interfaces=[FriendlyType], - fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType) - } + fields=lambda: {"bestFriend": GraphQLField(FriendlyType)}, ) HumanType = GraphQLObjectType( - name='Human', + name="Human", interfaces=[FriendlyType], - fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType) - } + fields=lambda: {"bestFriend": GraphQLField(FriendlyType)}, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='WithInterface', - fields={ - 'friendly': GraphQLField(FriendlyType) - } + name="WithInterface", fields={"friendly": GraphQLField(FriendlyType)} ), - types=[DogType, HumanType] + types=[DogType, HumanType], ) _test_schema(schema) @@ -181,27 +183,24 @@ def test_builds_a_schema_with_an_interface(): def test_builds_a_schema_with_an_implicit_interface(): FriendlyType = GraphQLInterfaceType( - name='Friendly', + name="Friendly", resolve_type=lambda: None, fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType, description='The best friend of this friendly thing.') - } + "bestFriend": GraphQLField( + FriendlyType, description="The best friend of this friendly thing." + ) + }, ) DogType = GraphQLObjectType( - name='DogType', + name="DogType", interfaces=[FriendlyType], - fields=lambda: { - 'bestFriend': GraphQLField(DogType) - } + fields=lambda: {"bestFriend": GraphQLField(DogType)}, ) schema = GraphQLSchema( query=GraphQLObjectType( - name='WithInterface', - fields={ - 'dog': GraphQLField(DogType) - } + name="WithInterface", fields={"dog": GraphQLField(DogType)} ) ) @@ -210,31 +209,20 @@ def test_builds_a_schema_with_an_implicit_interface(): def test_builds_a_schema_with_a_union(): DogType = GraphQLObjectType( - name='Dog', - fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType) - } + name="Dog", fields=lambda: {"bestFriend": GraphQLField(FriendlyType)} ) HumanType = GraphQLObjectType( - name='Human', - fields=lambda: { - 'bestFriend': GraphQLField(FriendlyType) - } + name="Human", fields=lambda: {"bestFriend": GraphQLField(FriendlyType)} ) FriendlyType = GraphQLUnionType( - name='Friendly', - resolve_type=lambda: None, - types=[DogType, HumanType] + name="Friendly", resolve_type=lambda: None, types=[DogType, HumanType] ) schema = GraphQLSchema( query=GraphQLObjectType( - name='WithUnion', - fields={ - 'friendly': GraphQLField(FriendlyType) - } + name="WithUnion", fields={"friendly": GraphQLField(FriendlyType)} ) ) @@ -244,16 +232,24 @@ def test_builds_a_schema_with_a_union(): def test_builds_a_schema_with_complex_field_values(): schema = GraphQLSchema( query=GraphQLObjectType( - name='ComplexFields', - fields=OrderedDict([ - ('string', GraphQLField(GraphQLString)), - ('listOfString', GraphQLField(GraphQLList(GraphQLString))), - ('nonNullString', GraphQLField(GraphQLNonNull(GraphQLString))), - ('nonNullListOfString', GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))), - ('nonNullListOfNonNullString', GraphQLField( - GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))) - )) - ]) + name="ComplexFields", + fields=OrderedDict( + [ + ("string", GraphQLField(GraphQLString)), + ("listOfString", GraphQLField(GraphQLList(GraphQLString))), + ("nonNullString", GraphQLField(GraphQLNonNull(GraphQLString))), + ( + "nonNullListOfString", + GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString))), + ), + ( + "nonNullListOfNonNullString", + GraphQLField( + GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))) + ), + ), + ] + ), ) ) @@ -263,22 +259,48 @@ def test_builds_a_schema_with_complex_field_values(): def test_builds_a_schema_with_field_arguments(): schema = GraphQLSchema( query=GraphQLObjectType( - name='ArgFields', - fields=OrderedDict([ - ('one', GraphQLField(GraphQLString, description='A field with a single arg', args={ - 'intArg': GraphQLArgument(GraphQLInt, description='This is an int arg') - })), - ('two', GraphQLField(GraphQLString, description='A field with two args', args=OrderedDict([ - ('listArg', GraphQLArgument( - GraphQLList(GraphQLInt), - description='This is a list of int arg' - )), - ('requiredArg', GraphQLArgument( - GraphQLNonNull(GraphQLBoolean), - description='This is a required arg' - )) - ]))), - ]) + name="ArgFields", + fields=OrderedDict( + [ + ( + "one", + GraphQLField( + GraphQLString, + description="A field with a single arg", + args={ + "intArg": GraphQLArgument( + GraphQLInt, description="This is an int arg" + ) + }, + ), + ), + ( + "two", + GraphQLField( + GraphQLString, + description="A field with two args", + args=OrderedDict( + [ + ( + "listArg", + GraphQLArgument( + GraphQLList(GraphQLInt), + description="This is a list of int arg", + ), + ), + ( + "requiredArg", + GraphQLArgument( + GraphQLNonNull(GraphQLBoolean), + description="This is a required arg", + ), + ), + ] + ), + ), + ), + ] + ), ) ) @@ -287,78 +309,123 @@ def test_builds_a_schema_with_field_arguments(): def test_builds_a_schema_with_an_enum(): FoodEnum = GraphQLEnumType( - name='Food', - description='Varieties of food stuffs', - values=OrderedDict([ - ('VEGETABLES', GraphQLEnumValue(1, description='Foods that are vegetables.')), - ('FRUITS', GraphQLEnumValue(2, description='Foods that are fruits.')), - ('OILS', GraphQLEnumValue(3, description='Foods that are oils.')), - ('DAIRY', GraphQLEnumValue(4, description='Foods that are dairy.')), - ('MEAT', GraphQLEnumValue(5, description='Foods that are meat.')), - ]) + name="Food", + description="Varieties of food stuffs", + values=OrderedDict( + [ + ( + "VEGETABLES", + GraphQLEnumValue(1, description="Foods that are vegetables."), + ), + ("FRUITS", GraphQLEnumValue(2, description="Foods that are fruits.")), + ("OILS", GraphQLEnumValue(3, description="Foods that are oils.")), + ("DAIRY", GraphQLEnumValue(4, description="Foods that are dairy.")), + ("MEAT", GraphQLEnumValue(5, description="Foods that are meat.")), + ] + ), ) schema = GraphQLSchema( query=GraphQLObjectType( - name='EnumFields', + name="EnumFields", fields={ - 'food': GraphQLField( + "food": GraphQLField( FoodEnum, - description='Repeats the arg you give it', + description="Repeats the arg you give it", args={ - 'kind': GraphQLArgument( - FoodEnum, - description='what kind of food?' + "kind": GraphQLArgument( + FoodEnum, description="what kind of food?" ) - } + }, ) - } + }, ) ) client_schema = _test_schema(schema) - clientFoodEnum = client_schema.get_type('Food') + clientFoodEnum = client_schema.get_type("Food") assert isinstance(clientFoodEnum, GraphQLEnumType) assert clientFoodEnum.values == [ - GraphQLEnumValue(name='VEGETABLES', value='VEGETABLES', description='Foods that are vegetables.', - deprecation_reason=None), - GraphQLEnumValue(name='FRUITS', value='FRUITS', description='Foods that are fruits.', deprecation_reason=None), - GraphQLEnumValue(name='OILS', value='OILS', description='Foods that are oils.', deprecation_reason=None), - GraphQLEnumValue(name='DAIRY', value='DAIRY', description='Foods that are dairy.', deprecation_reason=None), - GraphQLEnumValue(name='MEAT', value='MEAT', description='Foods that are meat.', deprecation_reason=None) + GraphQLEnumValue( + name="VEGETABLES", + value="VEGETABLES", + description="Foods that are vegetables.", + deprecation_reason=None, + ), + GraphQLEnumValue( + name="FRUITS", + value="FRUITS", + description="Foods that are fruits.", + deprecation_reason=None, + ), + GraphQLEnumValue( + name="OILS", + value="OILS", + description="Foods that are oils.", + deprecation_reason=None, + ), + GraphQLEnumValue( + name="DAIRY", + value="DAIRY", + description="Foods that are dairy.", + deprecation_reason=None, + ), + GraphQLEnumValue( + name="MEAT", + value="MEAT", + description="Foods that are meat.", + deprecation_reason=None, + ), ] def test_builds_a_schema_with_an_input_object(): AddressType = GraphQLInputObjectType( - name='Address', - description='An input address', - fields=OrderedDict([ - ('street', - GraphQLInputObjectField(GraphQLNonNull(GraphQLString), description='What street is this address?')), - ('city', - GraphQLInputObjectField(GraphQLNonNull(GraphQLString), description='The city the address is within?')), - ('country', GraphQLInputObjectField(GraphQLString, description='The country (blank will assume USA).', - default_value='USA')), - ]) + name="Address", + description="An input address", + fields=OrderedDict( + [ + ( + "street", + GraphQLInputObjectField( + GraphQLNonNull(GraphQLString), + description="What street is this address?", + ), + ), + ( + "city", + GraphQLInputObjectField( + GraphQLNonNull(GraphQLString), + description="The city the address is within?", + ), + ), + ( + "country", + GraphQLInputObjectField( + GraphQLString, + description="The country (blank will assume USA).", + default_value="USA", + ), + ), + ] + ), ) schema = GraphQLSchema( query=GraphQLObjectType( - name='HasInputObjectFields', + name="HasInputObjectFields", fields={ - 'geocode': GraphQLField( - description='Get a geocode from an address', + "geocode": GraphQLField( + description="Get a geocode from an address", type=GraphQLString, args={ - 'address': GraphQLArgument( - description='The address to lookup', - type=AddressType + "address": GraphQLArgument( + description="The address to lookup", type=AddressType ) - } + }, ) - } + }, ) ) @@ -367,45 +434,54 @@ def test_builds_a_schema_with_an_input_object(): def test_builds_a_schema_with_field_arguments_with_default_values(): GeoType = GraphQLInputObjectType( - name='Geo', - fields=OrderedDict([ - ('lat', GraphQLInputObjectField(GraphQLFloat)), - ('lon', GraphQLInputObjectField(GraphQLFloat)), - ]) + name="Geo", + fields=OrderedDict( + [ + ("lat", GraphQLInputObjectField(GraphQLFloat)), + ("lon", GraphQLInputObjectField(GraphQLFloat)), + ] + ), ) schema = GraphQLSchema( query=GraphQLObjectType( - name='ArgFields', - fields=OrderedDict([ - ('defaultInt', GraphQLField( - GraphQLString, - args={ - 'intArg': GraphQLArgument( - GraphQLInt, - default_value=10 - ) - } - )), - ('defaultList', GraphQLField( - GraphQLString, - args={ - 'listArg': GraphQLArgument( - GraphQLList(GraphQLInt), - default_value=[1, 2, 3] - ) - } - )), - ('defaultObject', GraphQLField( - GraphQLString, - args={ - 'objArg': GraphQLArgument( - GeoType, - default_value={'lat': 37.485, 'lon': -122.148} - ) - } - )) - ]) + name="ArgFields", + fields=OrderedDict( + [ + ( + "defaultInt", + GraphQLField( + GraphQLString, + args={ + "intArg": GraphQLArgument(GraphQLInt, default_value=10) + }, + ), + ), + ( + "defaultList", + GraphQLField( + GraphQLString, + args={ + "listArg": GraphQLArgument( + GraphQLList(GraphQLInt), default_value=[1, 2, 3] + ) + }, + ), + ), + ( + "defaultObject", + GraphQLField( + GraphQLString, + args={ + "objArg": GraphQLArgument( + GeoType, + default_value={"lat": 37.485, "lon": -122.148}, + ) + }, + ), + ), + ] + ), ) ) @@ -415,22 +491,21 @@ def test_builds_a_schema_with_field_arguments_with_default_values(): def test_builds_a_schema_with_custom_directives(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Simple', - description='This is a simple type', + name="Simple", + description="This is a simple type", fields={ - 'string': GraphQLField( - type=GraphQLString, - description='This is a string field' + "string": GraphQLField( + type=GraphQLString, description="This is a string field" ) }, ), directives=[ GraphQLDirective( - name='customDirective', - description='This is a custom directive', - locations=['FIELD'] + name="customDirective", + description="This is a custom directive", + locations=["FIELD"], ) - ] + ], ) _test_schema(schema) @@ -439,61 +514,55 @@ def test_builds_a_schema_with_custom_directives(): def test_builds_a_schema_with_legacy_directives(): old_introspection = { "__schema": { - "queryType": { - "name": "Simple" - }, - "types": [{ - "name": "Simple", - "kind": "OBJECT", - "fields": [{ - "name": "simple", - "args": [], - "type": { - "name": "Simple" - } - }], - "interfaces": [] - }], - "directives": [{ - "name": "Old1", - "args": [], - "onField": True - }, { - "name": "Old2", - "args": [], - "onFragment": True - }, { - "name": "Old3", - "args": [], - "onOperation": True - }, { - "name": "Old4", - "args": [], - "onField": True, - "onFragment": True - }] + "queryType": {"name": "Simple"}, + "types": [ + { + "name": "Simple", + "kind": "OBJECT", + "fields": [ + {"name": "simple", "args": [], "type": {"name": "Simple"}} + ], + "interfaces": [], + } + ], + "directives": [ + {"name": "Old1", "args": [], "onField": True}, + {"name": "Old2", "args": [], "onFragment": True}, + {"name": "Old3", "args": [], "onOperation": True}, + {"name": "Old4", "args": [], "onField": True, "onFragment": True}, + ], } } new_introspection = { "__schema": { - "directives": [{ - "name": "Old1", - "args": [], - "locations": ["FIELD"] - }, { - "name": "Old2", - "args": [], - "locations": ["FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"] - }, { - "name": "Old3", - "args": [], - "locations": ["QUERY", "MUTATION", "SUBSCRIPTION"] - }, { - "name": "Old4", - "args": [], - "locations": ["FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"] - }] + "directives": [ + {"name": "Old1", "args": [], "locations": ["FIELD"]}, + { + "name": "Old2", + "args": [], + "locations": [ + "FRAGMENT_DEFINITION", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT", + ], + }, + { + "name": "Old3", + "args": [], + "locations": ["QUERY", "MUTATION", "SUBSCRIPTION"], + }, + { + "name": "Old4", + "args": [], + "locations": [ + "FIELD", + "FRAGMENT_DEFINITION", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT", + ], + }, + ] } } @@ -506,31 +575,58 @@ def test_builds_a_schema_with_legacy_directives(): def test_builds_a_schema_aware_of_deprecation(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Simple', - description='This is a simple type', - fields=OrderedDict([ - ('shinyString', GraphQLField( - type=GraphQLString, - description='This is a shiny string field' - )), - ('deprecatedString', GraphQLField( - type=GraphQLString, - description='This is a deprecated string field', - deprecation_reason='Use shinyString' - )), - ('color', GraphQLField( - type=GraphQLEnumType( - name='Color', - values=OrderedDict([ - ('RED', GraphQLEnumValue(description='So rosy')), - ('GREEN', GraphQLEnumValue(description='So grassy')), - ('BLUE', GraphQLEnumValue(description='So calming')), - ('MAUVE', GraphQLEnumValue(description='So sickening', - deprecation_reason='No longer in fashion')), - ]) - ) - )) - ]) + name="Simple", + description="This is a simple type", + fields=OrderedDict( + [ + ( + "shinyString", + GraphQLField( + type=GraphQLString, + description="This is a shiny string field", + ), + ), + ( + "deprecatedString", + GraphQLField( + type=GraphQLString, + description="This is a deprecated string field", + deprecation_reason="Use shinyString", + ), + ), + ( + "color", + GraphQLField( + type=GraphQLEnumType( + name="Color", + values=OrderedDict( + [ + ( + "RED", + GraphQLEnumValue(description="So rosy"), + ), + ( + "GREEN", + GraphQLEnumValue(description="So grassy"), + ), + ( + "BLUE", + GraphQLEnumValue(description="So calming"), + ), + ( + "MAUVE", + GraphQLEnumValue( + description="So sickening", + deprecation_reason="No longer in fashion", + ), + ), + ] + ), + ) + ), + ), + ] + ), ) ) @@ -538,23 +634,22 @@ def test_builds_a_schema_aware_of_deprecation(): def test_cannot_use_client_schema_for_general_execution(): - customScalar = GraphQLScalarType( - name='CustomScalar', - serialize=lambda: None - ) + customScalar = GraphQLScalarType(name="CustomScalar", serialize=lambda: None) schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'foo': GraphQLField( + "foo": GraphQLField( GraphQLString, - args=OrderedDict([ - ('custom1', GraphQLArgument(customScalar)), - ('custom2', GraphQLArgument(customScalar)) - ]) + args=OrderedDict( + [ + ("custom1", GraphQLArgument(customScalar)), + ("custom2", GraphQLArgument(customScalar)), + ] + ), ) - } + }, ) ) @@ -562,70 +657,77 @@ def test_cannot_use_client_schema_for_general_execution(): client_schema = build_client_schema(introspection.data) class data: - foo = 'bar' + foo = "bar" result = graphql( client_schema, - 'query NoNo($v: CustomScalar) { foo(custom1: 123, custom2: $v) }', + "query NoNo($v: CustomScalar) { foo(custom1: 123, custom2: $v) }", data, - {'v': 'baz'} + {"v": "baz"}, ) - assert result.data == {'foo': None} + assert result.data == {"foo": None} assert [format_error(e) for e in result.errors] == [ { - 'locations': [{'column': 32, 'line': 1}], - 'message': 'Client Schema cannot be used for execution.', - 'path': ['foo'] + "locations": [{"column": 32, "line": 1}], + "message": "Client Schema cannot be used for execution.", + "path": ["foo"], } ] def test_throws_when_given_empty_types(): incomplete_introspection = { - '__schema': { - 'queryType': {'name': 'QueryType'}, - 'types': [] - } + "__schema": {"queryType": {"name": "QueryType"}, "types": []} } with raises(Exception) as excinfo: build_client_schema(incomplete_introspection) - assert str(excinfo.value) == 'Invalid or incomplete schema, unknown type: QueryType. Ensure that a full ' \ - 'introspection query is used in order to build a client schema.' + assert ( + str(excinfo.value) + == "Invalid or incomplete schema, unknown type: QueryType. Ensure that a full " + "introspection query is used in order to build a client schema." + ) def test_throws_when_missing_kind(): incomplete_introspection = { - '__schema': { - 'queryType': {'name': 'QueryType'}, - 'types': [{ - 'name': 'QueryType' - }] + "__schema": { + "queryType": {"name": "QueryType"}, + "types": [{"name": "QueryType"}], } } with raises(Exception) as excinfo: build_client_schema(incomplete_introspection) - assert str(excinfo.value) == 'Invalid or incomplete schema, unknown kind: None. Ensure that a full ' \ - 'introspection query is used in order to build a client schema.' + assert ( + str(excinfo.value) + == "Invalid or incomplete schema, unknown kind: None. Ensure that a full " + "introspection query is used in order to build a client schema." + ) def test_succeds_on_smaller_equals_than_7_deep_lists(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'foo': GraphQLField( - GraphQLNonNull(GraphQLList( - GraphQLNonNull(GraphQLList(GraphQLNonNull( - GraphQLList(GraphQLNonNull(GraphQLString)) - )) - ))) + "foo": GraphQLField( + GraphQLNonNull( + GraphQLList( + GraphQLNonNull( + GraphQLList( + GraphQLNonNull( + GraphQLList(GraphQLNonNull(GraphQLString)) + ) + ) + ) + ) + ) ) - } + }, ) ) @@ -636,16 +738,26 @@ def test_succeds_on_smaller_equals_than_7_deep_lists(): def test_fails_on_very_deep_lists(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'foo': GraphQLField( - GraphQLList(GraphQLList(GraphQLList(GraphQLList( - GraphQLList(GraphQLList(GraphQLList(GraphQLList( - GraphQLList(GraphQLString) - )))) - )))) + "foo": GraphQLField( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList(GraphQLList(GraphQLString)) + ) + ) + ) + ) + ) + ) + ) ) - } + }, ) ) @@ -654,22 +766,34 @@ def test_fails_on_very_deep_lists(): with raises(Exception) as excinfo: build_client_schema(introspection.data) - assert str(excinfo.value) == 'Decorated type deeper than introspection query.' + assert str(excinfo.value) == "Decorated type deeper than introspection query." def test_fails_on_a_very_deep_non_null(): schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', + name="Query", fields={ - 'foo': GraphQLField( - GraphQLList(GraphQLList(GraphQLList(GraphQLList( - GraphQLList(GraphQLList(GraphQLList(GraphQLList( - GraphQLNonNull(GraphQLString) - )))) - )))) + "foo": GraphQLField( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLList( + GraphQLNonNull(GraphQLString) + ) + ) + ) + ) + ) + ) + ) + ) ) - } + }, ) ) @@ -678,4 +802,4 @@ def test_fails_on_a_very_deep_non_null(): with raises(Exception) as excinfo: build_client_schema(introspection.data) - assert str(excinfo.value) == 'Decorated type deeper than introspection query.' + assert str(excinfo.value) == "Decorated type deeper than introspection query." diff --git a/graphql/utils/tests/test_concat_ast.py b/graphql/utils/tests/test_concat_ast.py index 5218b298..977a2b3c 100644 --- a/graphql/utils/tests/test_concat_ast.py +++ b/graphql/utils/tests/test_concat_ast.py @@ -4,18 +4,22 @@ def test_it_concatenates_two_acts_together(): - source_a = Source('{ a, b, ... Frag }') - source_b = Source(''' + source_a = Source("{ a, b, ... Frag }") + source_b = Source( + """ fragment Frag on T { c } - ''') + """ + ) ast_a = parse(source_a) ast_b = parse(source_b) ast_c = concat_ast([ast_a, ast_b]) - assert print_ast(ast_c) == '''{ + assert ( + print_ast(ast_c) + == """{ a b ...Frag @@ -24,4 +28,5 @@ def test_it_concatenates_two_acts_together(): fragment Frag on T { c } -''' +""" + ) diff --git a/graphql/utils/tests/test_extend_schema.py b/graphql/utils/tests/test_extend_schema.py index 194d984d..ac1c882d 100644 --- a/graphql/utils/tests/test_extend_schema.py +++ b/graphql/utils/tests/test_extend_schema.py @@ -4,132 +4,149 @@ from graphql import parse from graphql.execution import execute -from graphql.type import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue, - GraphQLField, GraphQLID, GraphQLInterfaceType, - GraphQLList, GraphQLNonNull, GraphQLObjectType, - GraphQLSchema, GraphQLString, GraphQLUnionType) +from graphql.type import ( + GraphQLArgument, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLID, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) from graphql.utils.extend_schema import extend_schema from graphql.utils.schema_printer import print_schema # Test schema. SomeInterfaceType = GraphQLInterfaceType( - name='SomeInterface', + name="SomeInterface", resolve_type=lambda: FooType, - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLString)), - ('some', GraphQLField(SomeInterfaceType)), - ]) + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLString)), + ("some", GraphQLField(SomeInterfaceType)), + ] + ), ) FooType = GraphQLObjectType( - name='Foo', + name="Foo", interfaces=[SomeInterfaceType], - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLString)), - ('some', GraphQLField(SomeInterfaceType)), - ('tree', GraphQLField(GraphQLNonNull(GraphQLList(FooType)))), - ]) + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLString)), + ("some", GraphQLField(SomeInterfaceType)), + ("tree", GraphQLField(GraphQLNonNull(GraphQLList(FooType)))), + ] + ), ) BarType = GraphQLObjectType( - name='Bar', + name="Bar", interfaces=[SomeInterfaceType], - fields=lambda: OrderedDict([ - ('name', GraphQLField(GraphQLString)), - ('some', GraphQLField(SomeInterfaceType)), - ('foo', GraphQLField(FooType)), - ]) + fields=lambda: OrderedDict( + [ + ("name", GraphQLField(GraphQLString)), + ("some", GraphQLField(SomeInterfaceType)), + ("foo", GraphQLField(FooType)), + ] + ), ) BizType = GraphQLObjectType( - name='Biz', - fields=lambda: OrderedDict([ - ('fizz', GraphQLField(GraphQLString)), - ]) + name="Biz", fields=lambda: OrderedDict([("fizz", GraphQLField(GraphQLString))]) ) SomeUnionType = GraphQLUnionType( - name='SomeUnion', - resolve_type=lambda: FooType, - types=[FooType, BizType], + name="SomeUnion", resolve_type=lambda: FooType, types=[FooType, BizType] ) SomeEnumType = GraphQLEnumType( - name='SomeEnum', - values=OrderedDict([ - ('ONE', GraphQLEnumValue(1)), - ('TWO', GraphQLEnumValue(2)), - ]) + name="SomeEnum", + values=OrderedDict([("ONE", GraphQLEnumValue(1)), ("TWO", GraphQLEnumValue(2))]), ) test_schema = GraphQLSchema( query=GraphQLObjectType( - name='Query', - fields=lambda: OrderedDict([ - ('foo', GraphQLField(FooType)), - ('someUnion', GraphQLField(SomeUnionType)), - ('someEnum', GraphQLField(SomeEnumType)), - ('someInterface', GraphQLField( - SomeInterfaceType, - args={ - 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)) - }, - )), - ]) + name="Query", + fields=lambda: OrderedDict( + [ + ("foo", GraphQLField(FooType)), + ("someUnion", GraphQLField(SomeUnionType)), + ("someEnum", GraphQLField(SomeEnumType)), + ( + "someInterface", + GraphQLField( + SomeInterfaceType, + args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))}, + ), + ), + ] + ), ), - types=[FooType, BarType] + types=[FooType, BarType], ) def test_returns_original_schema_if_no_type_definitions(): - ast = parse('{ field }') + ast = parse("{ field }") extended_schema = extend_schema(test_schema, ast) assert extended_schema == test_schema def test_extends_without_altering_original_schema(): - ast = parse(''' + ast = parse( + """ extend type Query { newField: String } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print - assert 'newField' in print_schema(extended_schema) - assert 'newField' not in print_schema(test_schema) + assert "newField" in print_schema(extended_schema) + assert "newField" not in print_schema(test_schema) def test_cannot_be_used_for_execution(): - ast = parse(''' + ast = parse( + """ extend type Query { newField: String } - ''') + """ + ) extended_schema = extend_schema(test_schema, ast) - clientQuery = parse('{ newField }') + clientQuery = parse("{ newField }") result = execute(extended_schema, clientQuery, object()) - assert result.data['newField'] is None - assert str(result.errors[0] - ) == 'Client Schema cannot be used for execution.' + assert result.data["newField"] is None + assert str(result.errors[0]) == "Client Schema cannot be used for execution." def test_extends_objects_by_adding_new_fields(): - ast = parse(''' + ast = parse( + """ extend type Foo { newField: String } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print # print original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -168,22 +185,26 @@ def test_extends_objects_by_adding_new_fields(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_by_adding_new_unused_types(): - ast = parse(''' + ast = parse( + """ type Unused { someField: String } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print # print original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -225,11 +246,13 @@ def test_extends_objects_by_adding_new_unused_types(): type Unused { someField: String } -''' +""" + ) def test_extends_objects_by_adding_new_fields_with_arguments(): - ast = parse(''' + ast = parse( + """ extend type Foo { newField(arg1: String, arg2: NewInputObj!): String } @@ -238,13 +261,15 @@ def test_extends_objects_by_adding_new_fields_with_arguments(): field2: [Float] field3: String! } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -289,21 +314,25 @@ def test_extends_objects_by_adding_new_fields_with_arguments(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_by_adding_new_fields_with_existing_types(): - ast = parse(''' + ast = parse( + """ extend type Foo { newField(arg1: SomeEnum!): SomeEnum } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -342,22 +371,26 @@ def test_extends_objects_by_adding_new_fields_with_existing_types(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_by_adding_implemented_interfaces(): - ast = parse(''' + ast = parse( + """ extend type Biz implements SomeInterface { name: String some: SomeInterface } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -397,11 +430,13 @@ def test_extends_objects_by_adding_implemented_interfaces(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_by_adding_implemented_interfaces_2(): - ast = parse(''' + ast = parse( + """ extend type Foo { newObject: NewObject newInterface: NewInterface @@ -425,13 +460,15 @@ def test_extends_objects_by_adding_implemented_interfaces_2(): OPTION_A OPTION_B } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -496,24 +533,28 @@ def test_extends_objects_by_adding_implemented_interfaces_2(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_by_adding_implemented_new_interfaces(): - ast = parse(''' + ast = parse( + """ extend type Foo implements NewInterface { baz: String } interface NewInterface { baz: String } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -556,11 +597,13 @@ def test_extends_objects_by_adding_implemented_new_interfaces(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_extends_objects_multiple_times(): - ast = parse(''' + ast = parse( + """ extend type Biz implements NewInterface { buzz: String } @@ -576,13 +619,15 @@ def test_extends_objects_multiple_times(): interface NewInterface { buzz: String } - ''') + """ + ) original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extended_schema != test_schema assert print_schema(test_schema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query } @@ -629,32 +674,25 @@ def test_extends_objects_multiple_times(): } union SomeUnion = Foo | Biz -''' +""" + ) def test_may_extend_mutations_and_subscriptions(): mutationSchema = GraphQLSchema( query=GraphQLObjectType( - 'Query', - fields=lambda: { - 'queryField': GraphQLField(GraphQLString), - } + "Query", fields=lambda: {"queryField": GraphQLField(GraphQLString)} ), mutation=GraphQLObjectType( - 'Mutation', - fields={ - 'mutationField': GraphQLField(GraphQLString), - } + "Mutation", fields={"mutationField": GraphQLField(GraphQLString)} ), subscription=GraphQLObjectType( - 'Subscription', - fields={ - 'subscriptionField': GraphQLField(GraphQLString), - } + "Subscription", fields={"subscriptionField": GraphQLField(GraphQLString)} ), ) - ast = parse(''' + ast = parse( + """ extend type Query { newQueryField: Int } @@ -664,13 +702,15 @@ def test_may_extend_mutations_and_subscriptions(): extend type Subscription { newSubscriptionField: Int } - ''') + """ + ) original_print = print_schema(mutationSchema) extended_schema = extend_schema(mutationSchema, ast) assert extended_schema != mutationSchema assert print_schema(mutationSchema) == original_print - assert print_schema(extended_schema) == \ - '''schema { + assert ( + print_schema(extended_schema) + == """schema { query: Query mutation: Mutation subscription: Subscription @@ -690,85 +730,103 @@ def test_may_extend_mutations_and_subscriptions(): subscriptionField: String newSubscriptionField: Int } -''' +""" + ) def test_does_not_allow_replacing_an_existing_type(): - ast = parse(''' + ast = parse( + """ type Bar { baz: String } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) - assert str(exc_info.value) == \ - ('Type "Bar" already exists in the schema. It cannot also be defined ' + - 'in this type definition.') + assert str(exc_info.value) == ( + 'Type "Bar" already exists in the schema. It cannot also be defined ' + + "in this type definition." + ) def test_does_not_allow_replacing_an_existing_field(): - ast = parse(''' + ast = parse( + """ extend type Bar { foo: Foo } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) - assert str(exc_info.value) == \ - ('Field "Bar.foo" already exists in the schema. It cannot also be ' + - 'defined in this type extension.') + assert str(exc_info.value) == ( + 'Field "Bar.foo" already exists in the schema. It cannot also be ' + + "defined in this type extension." + ) def test_does_not_allow_replacing_an_existing_interface(): - ast = parse(''' + ast = parse( + """ extend type Foo implements SomeInterface { otherField: String } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) - assert str(exc_info.value) == \ - ('Type "Foo" already implements "SomeInterface". It cannot also be ' + - 'implemented in this type extension.') + assert str(exc_info.value) == ( + 'Type "Foo" already implements "SomeInterface". It cannot also be ' + + "implemented in this type extension." + ) def test_does_not_allow_referencing_an_unknown_type(): - ast = parse(''' + ast = parse( + """ extend type Bar { quix: Quix } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) - assert str(exc_info.value) == \ - ('Unknown type: "Quix". Ensure that this type exists either in the ' + - 'original schema, or is added in a type definition.') + assert str(exc_info.value) == ( + 'Unknown type: "Quix". Ensure that this type exists either in the ' + + "original schema, or is added in a type definition." + ) def test_does_not_allow_extending_an_unknown_type(): - ast = parse(''' + ast = parse( + """ extend type UnknownType { baz: String } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) - assert str(exc_info.value) == \ - ('Cannot extend type "UnknownType" because it does not exist in the ' + - 'existing schema.') + assert str(exc_info.value) == ( + 'Cannot extend type "UnknownType" because it does not exist in the ' + + "existing schema." + ) def test_does_not_allow_extending_an_interface(): - ast = parse(''' + ast = parse( + """ extend type SomeInterface { baz: String } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) @@ -776,11 +834,13 @@ def test_does_not_allow_extending_an_interface(): def test_does_not_allow_extending_a_scalar(): - ast = parse(''' + ast = parse( + """ extend type String { baz: String } - ''') + """ + ) with raises(Exception) as exc_info: extend_schema(test_schema, ast) diff --git a/graphql/utils/tests/test_get_operation_ast.py b/graphql/utils/tests/test_get_operation_ast.py index 1147f67d..1839483e 100644 --- a/graphql/utils/tests/test_get_operation_ast.py +++ b/graphql/utils/tests/test_get_operation_ast.py @@ -3,54 +3,60 @@ def test_gets_an_operation_from_a_simple_document(): - doc = parse('{ field }') + doc = parse("{ field }") assert get_operation_ast(doc) == doc.definitions[0] def test_gets_an_operation_from_a_document_with_named_mutation_operation(): - doc = parse('mutation Test { field }') + doc = parse("mutation Test { field }") assert get_operation_ast(doc) == doc.definitions[0] def test_gets_an_operation_from_a_document_with_named_subscription_operation(): - doc = parse('subscription Test { field }') + doc = parse("subscription Test { field }") assert get_operation_ast(doc) == doc.definitions[0] def test_does_not_get_missing_operation(): - doc = parse('{ field } mutation Test { field }') + doc = parse("{ field } mutation Test { field }") assert not get_operation_ast(doc) def test_does_not_get_ambiguous_unnamed_operation(): - doc = parse('{ field } mutation TestM { field } subscription TestSub { field }') + doc = parse("{ field } mutation TestM { field } subscription TestSub { field }") assert not get_operation_ast(doc) def test_does_not_get_ambiguous_named_operation(): - doc = parse('query TestQ { field } mutation TestM { field } subscription TestSub { field }') + doc = parse( + "query TestQ { field } mutation TestM { field } subscription TestSub { field }" + ) assert not get_operation_ast(doc) def test_does_not_get_misnamed_operation(): - doc = parse('query TestQ { field } mutation TestM { field } subscription TestSub { field }') - assert not get_operation_ast(doc, 'Unknown') + doc = parse( + "query TestQ { field } mutation TestM { field } subscription TestSub { field }" + ) + assert not get_operation_ast(doc, "Unknown") def test_gets_named_operation(): - doc = parse('query TestQ { field } mutation TestM { field } subscription TestS { field }') - assert get_operation_ast(doc, 'TestQ') == doc.definitions[0] - assert get_operation_ast(doc, 'TestM') == doc.definitions[1] - assert get_operation_ast(doc, 'TestS') == doc.definitions[2] + doc = parse( + "query TestQ { field } mutation TestM { field } subscription TestS { field }" + ) + assert get_operation_ast(doc, "TestQ") == doc.definitions[0] + assert get_operation_ast(doc, "TestM") == doc.definitions[1] + assert get_operation_ast(doc, "TestS") == doc.definitions[2] def test_does_not_get_fragment(): - doc = parse('fragment Foo on Type { field }') + doc = parse("fragment Foo on Type { field }") assert not get_operation_ast(doc) - assert not get_operation_ast(doc, 'Foo') + assert not get_operation_ast(doc, "Foo") def test_does_not_get_fragment_with_same_name_query(): - doc = parse('fragment Foo on Type { field } query Foo { field }') + doc = parse("fragment Foo on Type { field } query Foo { field }") assert get_operation_ast(doc) == doc.definitions[1] - assert get_operation_ast(doc, 'Foo') == doc.definitions[1] + assert get_operation_ast(doc, "Foo") == doc.definitions[1] diff --git a/graphql/utils/tests/test_quoted_or_list.py b/graphql/utils/tests/test_quoted_or_list.py index 201aade1..f709f773 100644 --- a/graphql/utils/tests/test_quoted_or_list.py +++ b/graphql/utils/tests/test_quoted_or_list.py @@ -9,16 +9,16 @@ def test_does_not_accept_an_empty_list(): def test_returns_single_quoted_item(): - assert quoted_or_list(['A']) == '"A"' + assert quoted_or_list(["A"]) == '"A"' def test_returns_two_item_list(): - assert quoted_or_list(['A', 'B']) == '"A" or "B"' + assert quoted_or_list(["A", "B"]) == '"A" or "B"' def test_returns_comma_separated_many_item_list(): - assert quoted_or_list(['A', 'B', 'C']) == '"A", "B" or "C"' + assert quoted_or_list(["A", "B", "C"]) == '"A", "B" or "C"' def test_limits_to_five_items(): - assert quoted_or_list(['A', 'B', 'C', 'D', 'E', 'F']) == '"A", "B", "C", "D" or "E"' + assert quoted_or_list(["A", "B", "C", "D", "E", "F"]) == '"A", "B", "C", "D" or "E"' diff --git a/graphql/utils/tests/test_schema_printer.py b/graphql/utils/tests/test_schema_printer.py index f5d4a11c..0d61facf 100644 --- a/graphql/utils/tests/test_schema_printer.py +++ b/graphql/utils/tests/test_schema_printer.py @@ -1,33 +1,42 @@ from collections import OrderedDict -from graphql.type import (GraphQLBoolean, GraphQLEnumType, - GraphQLInputObjectType, GraphQLInt, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLScalarType, GraphQLSchema, - GraphQLString, GraphQLUnionType) -from graphql.type.definition import (GraphQLArgument, GraphQLEnumValue, - GraphQLField, GraphQLInputObjectField) -from graphql.utils.schema_printer import (print_introspection_schema, - print_schema) +from graphql.type import ( + GraphQLBoolean, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) +from graphql.type.definition import ( + GraphQLArgument, + GraphQLEnumValue, + GraphQLField, + GraphQLInputObjectField, +) +from graphql.utils.schema_printer import print_introspection_schema, print_schema def print_for_test(schema): - return '\n' + print_schema(schema) + return "\n" + print_schema(schema) def print_single_field_schema(field_config): - Root = GraphQLObjectType( - name='Root', - fields={ - 'singleField': field_config - } - ) + Root = GraphQLObjectType(name="Root", fields={"singleField": field_config}) return print_for_test(GraphQLSchema(Root)) def test_prints_string_field(): output = print_single_field_schema(GraphQLField(GraphQLString)) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -35,12 +44,15 @@ def test_prints_string_field(): type Root { singleField: String } -''' +""" + ) def test_prints_list_string_field(): output = print_single_field_schema(GraphQLField(GraphQLList(GraphQLString))) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -48,12 +60,17 @@ def test_prints_list_string_field(): type Root { singleField: [String] } -''' +""" + ) def test_prints_non_null_list_string_field(): - output = print_single_field_schema(GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))) - assert output == ''' + output = print_single_field_schema( + GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString))) + ) + assert ( + output + == """ schema { query: Root } @@ -61,12 +78,17 @@ def test_prints_non_null_list_string_field(): type Root { singleField: [String]! } -''' +""" + ) def test_prints_list_non_null_string_field(): - output = print_single_field_schema(GraphQLField((GraphQLList(GraphQLNonNull(GraphQLString))))) - assert output == ''' + output = print_single_field_schema( + GraphQLField((GraphQLList(GraphQLNonNull(GraphQLString)))) + ) + assert ( + output + == """ schema { query: Root } @@ -74,12 +96,17 @@ def test_prints_list_non_null_string_field(): type Root { singleField: [String!] } -''' +""" + ) def test_prints_non_null_list_non_null_string_field(): - output = print_single_field_schema(GraphQLField(GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))))) - assert output == ''' + output = print_single_field_schema( + GraphQLField(GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString)))) + ) + assert ( + output + == """ schema { query: Root } @@ -87,29 +114,22 @@ def test_prints_non_null_list_non_null_string_field(): type Root { singleField: [String!]! } -''' +""" + ) def test_prints_object_field(): - FooType = GraphQLObjectType( - name='Foo', - fields={ - 'str': GraphQLField(GraphQLString) - } - ) + FooType = GraphQLObjectType(name="Foo", fields={"str": GraphQLField(GraphQLString)}) - Root = GraphQLObjectType( - name='Root', - fields={ - 'foo': GraphQLField(FooType) - } - ) + Root = GraphQLObjectType(name="Root", fields={"foo": GraphQLField(FooType)}) Schema = GraphQLSchema(Root) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -121,15 +141,17 @@ def test_prints_object_field(): type Root { foo: Foo } -''' +""" + ) def test_prints_string_field_with_int_arg(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args={'argOne': GraphQLArgument(GraphQLInt)} - )) - assert output == ''' + output = print_single_field_schema( + GraphQLField(type=GraphQLString, args={"argOne": GraphQLArgument(GraphQLInt)}) + ) + assert ( + output + == """ schema { query: Root } @@ -137,15 +159,20 @@ def test_prints_string_field_with_int_arg(): type Root { singleField(argOne: Int): String } -''' +""" + ) def test_prints_string_field_with_int_arg_with_default(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args={'argOne': GraphQLArgument(GraphQLInt, default_value=2)} - )) - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args={"argOne": GraphQLArgument(GraphQLInt, default_value=2)}, + ) + ) + assert ( + output + == """ schema { query: Root } @@ -153,15 +180,20 @@ def test_prints_string_field_with_int_arg_with_default(): type Root { singleField(argOne: Int = 2): String } -''' +""" + ) def test_prints_string_field_with_non_null_int_arg(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args={'argOne': GraphQLArgument(GraphQLNonNull(GraphQLInt))} - )) - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args={"argOne": GraphQLArgument(GraphQLNonNull(GraphQLInt))}, + ) + ) + assert ( + output + == """ schema { query: Root } @@ -169,19 +201,26 @@ def test_prints_string_field_with_non_null_int_arg(): type Root { singleField(argOne: Int!): String } -''' +""" + ) def test_prints_string_field_with_multiple_args(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args=OrderedDict([ - ('argOne', GraphQLArgument(GraphQLInt)), - ('argTwo', GraphQLArgument(GraphQLString)) - ]) - )) - - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args=OrderedDict( + [ + ("argOne", GraphQLArgument(GraphQLInt)), + ("argTwo", GraphQLArgument(GraphQLString)), + ] + ), + ) + ) + + assert ( + output + == """ schema { query: Root } @@ -189,20 +228,27 @@ def test_prints_string_field_with_multiple_args(): type Root { singleField(argOne: Int, argTwo: String): String } -''' +""" + ) def test_prints_string_field_with_multiple_args_first_is_default(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args=OrderedDict([ - ('argOne', GraphQLArgument(GraphQLInt, default_value=1)), - ('argTwo', GraphQLArgument(GraphQLString)), - ('argThree', GraphQLArgument(GraphQLBoolean)) - ]) - )) - - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args=OrderedDict( + [ + ("argOne", GraphQLArgument(GraphQLInt, default_value=1)), + ("argTwo", GraphQLArgument(GraphQLString)), + ("argThree", GraphQLArgument(GraphQLBoolean)), + ] + ), + ) + ) + + assert ( + output + == """ schema { query: Root } @@ -210,20 +256,27 @@ def test_prints_string_field_with_multiple_args_first_is_default(): type Root { singleField(argOne: Int = 1, argTwo: String, argThree: Boolean): String } -''' +""" + ) def test_prints_string_field_with_multiple_args_second_is_default(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args=OrderedDict([ - ('argOne', GraphQLArgument(GraphQLInt)), - ('argTwo', GraphQLArgument(GraphQLString, default_value="foo")), - ('argThree', GraphQLArgument(GraphQLBoolean)) - ]) - )) - - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args=OrderedDict( + [ + ("argOne", GraphQLArgument(GraphQLInt)), + ("argTwo", GraphQLArgument(GraphQLString, default_value="foo")), + ("argThree", GraphQLArgument(GraphQLBoolean)), + ] + ), + ) + ) + + assert ( + output + == """ schema { query: Root } @@ -231,20 +284,27 @@ def test_prints_string_field_with_multiple_args_second_is_default(): type Root { singleField(argOne: Int, argTwo: String = "foo", argThree: Boolean): String } -''' +""" + ) def test_prints_string_field_with_multiple_args_last_is_default(): - output = print_single_field_schema(GraphQLField( - type=GraphQLString, - args=OrderedDict([ - ('argOne', GraphQLArgument(GraphQLInt)), - ('argTwo', GraphQLArgument(GraphQLString)), - ('argThree', GraphQLArgument(GraphQLBoolean, default_value=False)) - ]) - )) - - assert output == ''' + output = print_single_field_schema( + GraphQLField( + type=GraphQLString, + args=OrderedDict( + [ + ("argOne", GraphQLArgument(GraphQLInt)), + ("argTwo", GraphQLArgument(GraphQLString)), + ("argThree", GraphQLArgument(GraphQLBoolean, default_value=False)), + ] + ), + ) + ) + + assert ( + output + == """ schema { query: Root } @@ -252,37 +312,29 @@ def test_prints_string_field_with_multiple_args_last_is_default(): type Root { singleField(argOne: Int, argTwo: String, argThree: Boolean = false): String } -''' +""" + ) def test_prints_interface(): FooType = GraphQLInterfaceType( - name='Foo', + name="Foo", resolve_type=lambda *_: None, - fields={ - 'str': GraphQLField(GraphQLString) - } + fields={"str": GraphQLField(GraphQLString)}, ) BarType = GraphQLObjectType( - name='Bar', - fields={ - 'str': GraphQLField(GraphQLString), - }, - interfaces=[FooType] + name="Bar", fields={"str": GraphQLField(GraphQLString)}, interfaces=[FooType] ) - Root = GraphQLObjectType( - name='Root', - fields={ - 'bar': GraphQLField(BarType) - } - ) + Root = GraphQLObjectType(name="Root", fields={"bar": GraphQLField(BarType)}) Schema = GraphQLSchema(Root, types=[BarType]) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -298,45 +350,38 @@ def test_prints_interface(): type Root { bar: Bar } -''' +""" + ) def test_prints_multiple_interfaces(): FooType = GraphQLInterfaceType( - name='Foo', + name="Foo", resolve_type=lambda *_: None, - fields={ - 'str': GraphQLField(GraphQLString) - } + fields={"str": GraphQLField(GraphQLString)}, ) BaazType = GraphQLInterfaceType( - name='Baaz', + name="Baaz", resolve_type=lambda *_: None, - fields={ - 'int': GraphQLField(GraphQLInt) - } + fields={"int": GraphQLField(GraphQLInt)}, ) BarType = GraphQLObjectType( - name='Bar', - fields=OrderedDict([ - ('str', GraphQLField(GraphQLString)), - ('int', GraphQLField(GraphQLInt)) - ]), - interfaces=[FooType, BaazType] + name="Bar", + fields=OrderedDict( + [("str", GraphQLField(GraphQLString)), ("int", GraphQLField(GraphQLInt))] + ), + interfaces=[FooType, BaazType], ) - Root = GraphQLObjectType( - name='Root', - fields={ - 'bar': GraphQLField(BarType) - } - ) + Root = GraphQLObjectType(name="Root", fields={"bar": GraphQLField(BarType)}) Schema = GraphQLSchema(Root, types=[BarType]) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -357,48 +402,41 @@ def test_prints_multiple_interfaces(): type Root { bar: Bar } -''' +""" + ) def test_prints_unions(): FooType = GraphQLObjectType( - name='Foo', - fields={ - 'bool': GraphQLField(GraphQLBoolean), - }, + name="Foo", fields={"bool": GraphQLField(GraphQLBoolean)} ) - BarType = GraphQLObjectType( - name='Bar', - fields={ - 'str': GraphQLField(GraphQLString), - }, - ) + BarType = GraphQLObjectType(name="Bar", fields={"str": GraphQLField(GraphQLString)}) SingleUnion = GraphQLUnionType( - name='SingleUnion', - resolve_type=lambda *_: None, - types=[FooType] + name="SingleUnion", resolve_type=lambda *_: None, types=[FooType] ) MultipleUnion = GraphQLUnionType( - name='MultipleUnion', - resolve_type=lambda *_: None, - types=[FooType, BarType], + name="MultipleUnion", resolve_type=lambda *_: None, types=[FooType, BarType] ) Root = GraphQLObjectType( - name='Root', - fields=OrderedDict([ - ('single', GraphQLField(SingleUnion)), - ('multiple', GraphQLField(MultipleUnion)), - ]) + name="Root", + fields=OrderedDict( + [ + ("single", GraphQLField(SingleUnion)), + ("multiple", GraphQLField(MultipleUnion)), + ] + ), ) Schema = GraphQLSchema(Root) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -419,28 +457,30 @@ def test_prints_unions(): } union SingleUnion = Foo -''' +""" + ) def test_prints_input_type(): InputType = GraphQLInputObjectType( - name='InputType', - fields={ - 'int': GraphQLInputObjectField(GraphQLInt) - } + name="InputType", fields={"int": GraphQLInputObjectField(GraphQLInt)} ) Root = GraphQLObjectType( - name='Root', + name="Root", fields={ - 'str': GraphQLField(GraphQLString, args={'argOne': GraphQLArgument(InputType)}) - } + "str": GraphQLField( + GraphQLString, args={"argOne": GraphQLArgument(InputType)} + ) + }, ) Schema = GraphQLSchema(Root) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -452,26 +492,23 @@ def test_prints_input_type(): type Root { str(argOne: InputType): String } -''' +""" + ) def test_prints_custom_scalar(): OddType = GraphQLScalarType( - name='Odd', - serialize=lambda v: v if v % 2 == 1 else None + name="Odd", serialize=lambda v: v if v % 2 == 1 else None ) - Root = GraphQLObjectType( - name='Root', - fields={ - 'odd': GraphQLField(OddType) - } - ) + Root = GraphQLObjectType(name="Root", fields={"odd": GraphQLField(OddType)}) Schema = GraphQLSchema(Root) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -481,30 +518,30 @@ def test_prints_custom_scalar(): type Root { odd: Odd } -''' +""" + ) def test_print_enum(): RGBType = GraphQLEnumType( - name='RGB', - values=OrderedDict([ - ('RED', GraphQLEnumValue(0)), - ('GREEN', GraphQLEnumValue(1)), - ('BLUE', GraphQLEnumValue(2)) - ]) + name="RGB", + values=OrderedDict( + [ + ("RED", GraphQLEnumValue(0)), + ("GREEN", GraphQLEnumValue(1)), + ("BLUE", GraphQLEnumValue(2)), + ] + ), ) - Root = GraphQLObjectType( - name='Root', - fields={ - 'rgb': GraphQLField(RGBType) - } - ) + Root = GraphQLObjectType(name="Root", fields={"rgb": GraphQLField(RGBType)}) Schema = GraphQLSchema(Root) output = print_for_test(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -518,21 +555,21 @@ def test_print_enum(): type Root { rgb: RGB } -''' +""" + ) def test_print_introspection_schema(): Root = GraphQLObjectType( - name='Root', - fields={ - 'onlyField': GraphQLField(GraphQLString) - } + name="Root", fields={"onlyField": GraphQLField(GraphQLString)} ) Schema = GraphQLSchema(Root) - output = '\n' + print_introspection_schema(Schema) + output = "\n" + print_introspection_schema(Schema) - assert output == ''' + assert ( + output + == """ schema { query: Root } @@ -627,4 +664,5 @@ def test_print_introspection_schema(): LIST NON_NULL } -''' +""" + ) diff --git a/graphql/utils/tests/test_suggestion_list.py b/graphql/utils/tests/test_suggestion_list.py index 3d99ae72..90043da6 100644 --- a/graphql/utils/tests/test_suggestion_list.py +++ b/graphql/utils/tests/test_suggestion_list.py @@ -2,14 +2,18 @@ def test_returns_results_when_input_is_empty(): - assert suggestion_list('', ['a']) == ['a'] + assert suggestion_list("", ["a"]) == ["a"] def test_returns_empty_array_when_there_are_no_options(): - assert suggestion_list('input', []) == [] + assert suggestion_list("input", []) == [] def test_returns_options_sorted_based_on_similarity(): - assert suggestion_list('abc', ['a', 'ab', 'abc']) == ['abc', 'ab'] + assert suggestion_list("abc", ["a", "ab", "abc"]) == ["abc", "ab"] - assert suggestion_list('csutomer', ['customer', 'stomer', 'store']) == ['customer', 'stomer', 'store'] + assert suggestion_list("csutomer", ["customer", "stomer", "store"]) == [ + "customer", + "stomer", + "store", + ] diff --git a/graphql/utils/tests/test_type_comparators.py b/graphql/utils/tests/test_type_comparators.py index 59a5d7b7..82174da1 100644 --- a/graphql/utils/tests/test_type_comparators.py +++ b/graphql/utils/tests/test_type_comparators.py @@ -1,9 +1,17 @@ from collections import OrderedDict -from graphql.type import (GraphQLField, GraphQLFloat, GraphQLInt, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLSchema, GraphQLString, - GraphQLUnionType) +from graphql.type import ( + GraphQLField, + GraphQLFloat, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) from ..type_comparators import is_equal_type, is_type_sub_type_of @@ -11,10 +19,7 @@ def _test_schema(field_type): return GraphQLSchema( query=GraphQLObjectType( - name='Query', - fields=OrderedDict([ - ('field', GraphQLField(field_type)), - ]) + name="Query", fields=OrderedDict([("field", GraphQLField(field_type))]) ) ) @@ -28,10 +33,7 @@ def test_is_equal_type_int_and_float_are_not_equal(): def test_is_equal_type_lists_of_same_type_are_equal(): - assert is_equal_type( - GraphQLList(GraphQLInt), - GraphQLList(GraphQLInt) - ) + assert is_equal_type(GraphQLList(GraphQLInt), GraphQLList(GraphQLInt)) def test_is_equal_type_lists_is_not_equal_to_item(): @@ -39,10 +41,7 @@ def test_is_equal_type_lists_is_not_equal_to_item(): def test_is_equal_type_nonnull_of_same_type_are_equal(): - assert is_equal_type( - GraphQLNonNull(GraphQLInt), - GraphQLNonNull(GraphQLInt) - ) + assert is_equal_type(GraphQLNonNull(GraphQLInt), GraphQLNonNull(GraphQLInt)) def test_is_equal_type_nonnull_is_not_equal_to_nullable(): @@ -85,31 +84,24 @@ def test_is_type_sub_type_of_list_is_not_subtype_of_item(): def test_is_type_sub_type_of_member_is_subtype_of_union(): member = GraphQLObjectType( - name='Object', + name="Object", is_type_of=lambda *_: True, - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) - union = GraphQLUnionType(name='Union', types=[member]) + union = GraphQLUnionType(name="Union", types=[member]) schema = _test_schema(union) assert is_type_sub_type_of(schema, member, union) def test_is_type_sub_type_of_implementation_is_subtype_of_interface(): iface = GraphQLInterfaceType( - name='Interface', - fields={ - 'field': GraphQLField(GraphQLString) - } + name="Interface", fields={"field": GraphQLField(GraphQLString)} ) impl = GraphQLObjectType( - name='Object', + name="Object", is_type_of=lambda *_: True, interfaces=[iface], - fields={ - 'field': GraphQLField(GraphQLString) - } + fields={"field": GraphQLField(GraphQLString)}, ) schema = _test_schema(impl) assert is_type_sub_type_of(schema, impl, iface) diff --git a/graphql/validation/__init__.py b/graphql/validation/__init__.py index 893af3e7..ce474e11 100644 --- a/graphql/validation/__init__.py +++ b/graphql/validation/__init__.py @@ -1,4 +1,4 @@ from .validation import validate from .rules import specified_rules -__all__ = ['validate', 'specified_rules'] +__all__ = ["validate", "specified_rules"] diff --git a/graphql/validation/rules/__init__.py b/graphql/validation/rules/__init__.py index b1ebd7d6..8ed07e5b 100644 --- a/graphql/validation/rules/__init__.py +++ b/graphql/validation/rules/__init__.py @@ -47,33 +47,33 @@ VariablesInAllowedPosition, OverlappingFieldsCanBeMerged, UniqueInputFieldNames, - UniqueVariableNames + UniqueVariableNames, ] __all__ = [ - 'ArgumentsOfCorrectType', - 'DefaultValuesOfCorrectType', - 'FieldsOnCorrectType', - 'FragmentsOnCompositeTypes', - 'KnownArgumentNames', - 'KnownDirectives', - 'KnownFragmentNames', - 'KnownTypeNames', - 'LoneAnonymousOperation', - 'NoFragmentCycles', - 'UniqueVariableNames', - 'NoUndefinedVariables', - 'NoUnusedFragments', - 'NoUnusedVariables', - 'OverlappingFieldsCanBeMerged', - 'PossibleFragmentSpreads', - 'ProvidedNonNullArguments', - 'ScalarLeafs', - 'UniqueArgumentNames', - 'UniqueFragmentNames', - 'UniqueInputFieldNames', - 'UniqueOperationNames', - 'VariablesAreInputTypes', - 'VariablesInAllowedPosition', - 'specified_rules' + "ArgumentsOfCorrectType", + "DefaultValuesOfCorrectType", + "FieldsOnCorrectType", + "FragmentsOnCompositeTypes", + "KnownArgumentNames", + "KnownDirectives", + "KnownFragmentNames", + "KnownTypeNames", + "LoneAnonymousOperation", + "NoFragmentCycles", + "UniqueVariableNames", + "NoUndefinedVariables", + "NoUnusedFragments", + "NoUnusedVariables", + "OverlappingFieldsCanBeMerged", + "PossibleFragmentSpreads", + "ProvidedNonNullArguments", + "ScalarLeafs", + "UniqueArgumentNames", + "UniqueFragmentNames", + "UniqueInputFieldNames", + "UniqueOperationNames", + "VariablesAreInputTypes", + "VariablesInAllowedPosition", + "specified_rules", ] diff --git a/graphql/validation/rules/known_directives.py b/graphql/validation/rules/known_directives.py index f672105d..86728355 100644 --- a/graphql/validation/rules/known_directives.py +++ b/graphql/validation/rules/known_directives.py @@ -5,30 +5,37 @@ class KnownDirectives(ValidationRule): - def enter_Directive(self, node, key, parent, path, ancestors): - directive_def = next(( - definition for definition in self.context.get_schema().get_directives() - if definition.name == node.name.value - ), None) + directive_def = next( + ( + definition + for definition in self.context.get_schema().get_directives() + if definition.name == node.name.value + ), + None, + ) if not directive_def: - return self.context.report_error(GraphQLError( - self.unknown_directive_message(node.name.value), - [node] - )) + return self.context.report_error( + GraphQLError(self.unknown_directive_message(node.name.value), [node]) + ) candidate_location = get_directive_location_for_ast_path(ancestors) if not candidate_location: - self.context.report_error(GraphQLError( - self.misplaced_directive_message(node.name.value, node.type), - [node] - )) + self.context.report_error( + GraphQLError( + self.misplaced_directive_message(node.name.value, node.type), [node] + ) + ) elif candidate_location not in directive_def.locations: - self.context.report_error(GraphQLError( - self.misplaced_directive_message(node.name.value, candidate_location), - [node] - )) + self.context.report_error( + GraphQLError( + self.misplaced_directive_message( + node.name.value, candidate_location + ), + [node], + ) + ) @staticmethod def unknown_directive_message(directive_name): @@ -36,13 +43,15 @@ def unknown_directive_message(directive_name): @staticmethod def misplaced_directive_message(directive_name, location): - return 'Directive "{}" may not be used on "{}".'.format(directive_name, location) + return 'Directive "{}" may not be used on "{}".'.format( + directive_name, location + ) _operation_definition_map = { - 'query': DirectiveLocation.QUERY, - 'mutation': DirectiveLocation.MUTATION, - 'subscription': DirectiveLocation.SUBSCRIPTION, + "query": DirectiveLocation.QUERY, + "mutation": DirectiveLocation.MUTATION, + "subscription": DirectiveLocation.SUBSCRIPTION, } @@ -92,6 +101,8 @@ def get_directive_location_for_ast_path(ancestors): elif isinstance(applied_to, ast.InputValueDefinition): parent_node = ancestors[-3] - return (DirectiveLocation.INPUT_FIELD_DEFINITION - if isinstance(parent_node, ast.InputObjectTypeDefinition) - else DirectiveLocation.ARGUMENT_DEFINITION) + return ( + DirectiveLocation.INPUT_FIELD_DEFINITION + if isinstance(parent_node, ast.InputObjectTypeDefinition) + else DirectiveLocation.ARGUMENT_DEFINITION + ) diff --git a/graphql/validation/rules/known_fragment_names.py b/graphql/validation/rules/known_fragment_names.py index 6c7375e3..e572ce8e 100644 --- a/graphql/validation/rules/known_fragment_names.py +++ b/graphql/validation/rules/known_fragment_names.py @@ -3,16 +3,14 @@ class KnownFragmentNames(ValidationRule): - def enter_FragmentSpread(self, node, key, parent, path, ancestors): fragment_name = node.name.value fragment = self.context.get_fragment(fragment_name) if not fragment: - self.context.report_error(GraphQLError( - self.unknown_fragment_message(fragment_name), - [node.name] - )) + self.context.report_error( + GraphQLError(self.unknown_fragment_message(fragment_name), [node.name]) + ) @staticmethod def unknown_fragment_message(fragment_name): diff --git a/graphql/validation/rules/variables_are_input_types.py b/graphql/validation/rules/variables_are_input_types.py index f510fbba..49397ad9 100644 --- a/graphql/validation/rules/variables_are_input_types.py +++ b/graphql/validation/rules/variables_are_input_types.py @@ -6,16 +6,21 @@ class VariablesAreInputTypes(ValidationRule): - def enter_VariableDefinition(self, node, key, parent, path, ancestors): type = type_from_ast(self.context.get_schema(), node.type) if type and not is_input_type(type): - self.context.report_error(GraphQLError( - self.non_input_type_on_variable_message(node.variable.name.value, print_ast(node.type)), - [node.type] - )) + self.context.report_error( + GraphQLError( + self.non_input_type_on_variable_message( + node.variable.name.value, print_ast(node.type) + ), + [node.type], + ) + ) @staticmethod def non_input_type_on_variable_message(variable_name, type_name): - return 'Variable "${}" cannot be non-input type "{}".'.format(variable_name, type_name) + return 'Variable "${}" cannot be non-input type "{}".'.format( + variable_name, type_name + ) diff --git a/graphql/validation/tests/test_arguments_of_correct_type.py b/graphql/validation/tests/test_arguments_of_correct_type.py index 828aa61c..db165669 100644 --- a/graphql/validation/tests/test_arguments_of_correct_type.py +++ b/graphql/validation/tests/test_arguments_of_correct_type.py @@ -9,598 +9,729 @@ def bad_value(arg_name, type_name, value, line, column, errors=None): errors = [u'Expected type "{}", found {}.'.format(type_name, value)] return { - 'message': ArgumentsOfCorrectType.bad_value_message(arg_name, type_name, value, errors), - 'locations': [SourceLocation(line, column)] + "message": ArgumentsOfCorrectType.bad_value_message( + arg_name, type_name, value, errors + ), + "locations": [SourceLocation(line, column)], } # noinspection PyMethodMayBeStatic class TestValidValues(object): - def test_good_int_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: 2) } } - ''') + """, + ) def test_good_boolean_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { booleanArgField(booleanArg: true) } } - ''') + """, + ) def test_good_string_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringArgField(stringArg: "foo") } } - ''') + """, + ) def test_good_float_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { floatArgField(floatArg: 1.1) } } - ''') + """, + ) def test_int_into_float(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { floatArgField(floatArg: 1) } } - ''') + """, + ) def test_int_into_id(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { idArgField(idArg: 1) } } - ''') + """, + ) def test_string_into_id(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { idArgField(idArg: "someIdString") } } - ''') + """, + ) def test_good_enum_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: SIT) } } - ''') + """, + ) # noinspection PyMethodMayBeStatic class TestInvalidStringValues(object): - def test_int_into_string(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringArgField(stringArg: 1) } } - ''', [ - bad_value('stringArg', 'String', '1', 4, 43) - ]) + """, + [bad_value("stringArg", "String", "1", 4, 43)], + ) def test_float_into_string(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringArgField(stringArg: 1.0) } } - ''', [ - bad_value('stringArg', 'String', '1.0', 4, 43) - ]) + """, + [bad_value("stringArg", "String", "1.0", 4, 43)], + ) def test_bool_into_string(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringArgField(stringArg: true) } } - ''', [ - bad_value('stringArg', 'String', 'true', 4, 43) - ]) + """, + [bad_value("stringArg", "String", "true", 4, 43)], + ) def test_unquoted_string_into_string(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringArgField(stringArg: BAR) } } - ''', [ - bad_value('stringArg', 'String', 'BAR', 4, 43) - ]) + """, + [bad_value("stringArg", "String", "BAR", 4, 43)], + ) # noinspection PyMethodMayBeStatic class TestInvalidIntValues(object): - def test_string_into_int(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: "3") } } - ''', [ - bad_value('intArg', 'Int', '"3"', 4, 37) - ]) + """, + [bad_value("intArg", "Int", '"3"', 4, 37)], + ) def test_big_int_into_int(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: 829384293849283498239482938) } } - ''', [ - bad_value('intArg', 'Int', '829384293849283498239482938', 4, 37) - ]) + """, + [bad_value("intArg", "Int", "829384293849283498239482938", 4, 37)], + ) def test_unquoted_string_into_int(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: FOO) } } - ''', [ - bad_value('intArg', 'Int', 'FOO', 4, 37) - ]) + """, + [bad_value("intArg", "Int", "FOO", 4, 37)], + ) def test_simple_float_into_int(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: 3.0) } } - ''', [ - bad_value('intArg', 'Int', '3.0', 4, 37) - ]) + """, + [bad_value("intArg", "Int", "3.0", 4, 37)], + ) def test_float_into_int(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { intArgField(intArg: 3.333) } } - ''', [ - bad_value('intArg', 'Int', '3.333', 4, 37) - ]) + """, + [bad_value("intArg", "Int", "3.333", 4, 37)], + ) # noinspection PyMethodMayBeStatic class TestInvalidFloatValues(object): - def test_string_into_float(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { floatArgField(floatArg: "3.333") } } - ''', [ - bad_value('floatArg', 'Float', '"3.333"', 4, 41) - ]) + """, + [bad_value("floatArg", "Float", '"3.333"', 4, 41)], + ) def test_boolean_into_float(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { floatArgField(floatArg: true) } } - ''', [ - bad_value('floatArg', 'Float', 'true', 4, 41) - ]) + """, + [bad_value("floatArg", "Float", "true", 4, 41)], + ) def test_unquoted_into_float(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { floatArgField(floatArg: FOO) } } - ''', [ - bad_value('floatArg', 'Float', 'FOO', 4, 41) - ]) + """, + [bad_value("floatArg", "Float", "FOO", 4, 41)], + ) # noinspection PyMethodMayBeStatic class TestInvalidBooleanValues(object): - def test_int_into_boolean(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { booleanArgField(booleanArg: 2) } } - ''', [ - bad_value('booleanArg', 'Boolean', '2', 4, 45) - ]) + """, + [bad_value("booleanArg", "Boolean", "2", 4, 45)], + ) def test_float_into_boolean(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { booleanArgField(booleanArg: 1.0) } } - ''', [ - bad_value('booleanArg', 'Boolean', '1.0', 4, 45) - ]) + """, + [bad_value("booleanArg", "Boolean", "1.0", 4, 45)], + ) def test_string_into_boolean(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { booleanArgField(booleanArg: "true") } } - ''', [ - bad_value('booleanArg', 'Boolean', '"true"', 4, 45) - ]) + """, + [bad_value("booleanArg", "Boolean", '"true"', 4, 45)], + ) def test_unquoted_into_boolean(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { booleanArgField(booleanArg: TRUE) } } - ''', [ - bad_value('booleanArg', 'Boolean', 'TRUE', 4, 45) - ]) + """, + [bad_value("booleanArg", "Boolean", "TRUE", 4, 45)], + ) # noinspection PyMethodMayBeStatic class TestInvalidIDValues(object): - def test_float_into_id(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { idArgField(idArg: 1.0) } } - ''', [ - bad_value('idArg', 'ID', '1.0', 4, 35) - ]) + """, + [bad_value("idArg", "ID", "1.0", 4, 35)], + ) def test_boolean_into_id(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { idArgField(idArg: true) } } - ''', [ - bad_value('idArg', 'ID', 'true', 4, 35) - ]) + """, + [bad_value("idArg", "ID", "true", 4, 35)], + ) def test_unquoted_into_id(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { idArgField(idArg: SOMETHING) } } - ''', [ - bad_value('idArg', 'ID', 'SOMETHING', 4, 35) - ]) + """, + [bad_value("idArg", "ID", "SOMETHING", 4, 35)], + ) # noinspection PyMethodMayBeStatic class TestInvalidEnumValues(object): - def test_int_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: 2) } } - ''', [ - bad_value('dogCommand', 'DogCommand', '2', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", "2", 4, 45)], + ) def test_float_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: 1.0) } } - ''', [ - bad_value('dogCommand', 'DogCommand', '1.0', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", "1.0", 4, 45)], + ) def test_string_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: "SIT") } } - ''', [ - bad_value('dogCommand', 'DogCommand', '"SIT"', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", '"SIT"', 4, 45)], + ) def test_boolean_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: true) } } - ''', [ - bad_value('dogCommand', 'DogCommand', 'true', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", "true", 4, 45)], + ) def test_unknown_enum_value_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: JUGGLE) } } - ''', [ - bad_value('dogCommand', 'DogCommand', 'JUGGLE', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", "JUGGLE", 4, 45)], + ) def test_different_case_enum_value_into_enum(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog { doesKnowCommand(dogCommand: sit) } } - ''', [ - bad_value('dogCommand', 'DogCommand', 'sit', 4, 45) - ]) + """, + [bad_value("dogCommand", "DogCommand", "sit", 4, 45)], + ) # noinspection PyMethodMayBeStatic class TestValidListValues(object): - def test_good_list_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringListArgField(stringListArg: ["one", "two"]) } } - ''') + """, + ) def test_empty_list_value(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringListArgField(stringListArg: []) } } - ''') + """, + ) def test_single_value_into_list(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringListArgField(stringListArg: "one") } } - ''') + """, + ) # noinspection PyMethodMayBeStatic class TestInvalidListValues(object): - def test_incorrect_item_type(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringListArgField(stringListArg: ["one", 2]) } } - ''', [ - bad_value('stringListArg', 'String', '["one", 2]', 4, 51, [ - 'In element #1: Expected type "String", found 2.' - ]) - ]) + """, + [ + bad_value( + "stringListArg", + "String", + '["one", 2]', + 4, + 51, + ['In element #1: Expected type "String", found 2.'], + ) + ], + ) def test_single_value_of_incorrect_type(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { stringListArgField(stringListArg: 1) } } - ''', [ - bad_value('stringListArg', 'String', '1', 4, 51) - ]) + """, + [bad_value("stringListArg", "String", "1", 4, 51)], + ) # noinspection PyMethodMayBeStatic class TestValidNonNullableValues(object): - def test_arg_on_optional_arg(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { dog { isHousetrained(atOtherHomes: true) } } - ''') + """, + ) def test_no_arg_on_optional_arg(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { dog { isHousetrained } } - ''') + """, + ) def test_multiple_args(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } - ''') + """, + ) def test_multiple_args_reverse_order(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } - ''') + """, + ) def test_no_args_on_multiple_optional(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOpts } } - ''') + """, + ) def test_one_arg_on_multiple_optional(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOpts(opt1: 1) } } - ''') + """, + ) def test_second_arg_on_multiple_optional(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOpts(opt2: 1) } } - ''') + """, + ) def test_multiple_reqs_and_one_opt_on_mixed_list(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOpts(req1: 3, req2: 4, opt1: 5) } } - ''') + """, + ) def test_all_reqs_and_opts_on_mixed_list(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOpts(req1: 3, req2: 4, opt1: 5, opt2: 6) } } - ''') + """, + ) # noinspection PyMethodMayBeStatic class TestInvalidNonNullableValues(object): - def test_incorrect_value_type(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleOptsAndReq(req2: "two", req1: "one") } } - ''', [ - bad_value('req2', 'Int', '"two"', 4, 42), - bad_value('req1', 'Int', '"one"', 4, 55), - ]) + """, + [ + bad_value("req2", "Int", '"two"', 4, 42), + bad_value("req1", "Int", '"one"', 4, 55), + ], + ) def test_incorrect_value_and_missing_argument(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { multipleReqs(req1: "one") } } - ''', [ - bad_value('req1', 'Int', '"one"', 4, 36) - ]) + """, + [bad_value("req1", "Int", '"one"', 4, 36)], + ) # noinspection PyMethodMayBeStatic class TestValidInputObjectValue(object): - def test_optional_arg_despite_required_field_in_type(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField } } - ''') + """, + ) def test_partial_object_only_required(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { requiredField: true }) } } - ''') + """, + ) def test_partial_object_required_field_can_be_falsey(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { requiredField: false }) } } - ''') + """, + ) def test_partial_object_including_required(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { requiredField: false, intField: 4 }) } } - ''') + """, + ) def test_full_object(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { @@ -612,10 +743,13 @@ def test_full_object(self): }) } } - ''') + """, + ) def test_full_object_with_fields_in_different_order(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { @@ -627,27 +761,38 @@ def test_full_object_with_fields_in_different_order(self): }) } } - ''') + """, + ) # noinspection PyMethodMayBeStatic class TestInvalidInputObjectValue(object): - def test_partial_object_missing_required(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { intField: 4 }) } } - ''', [ - bad_value('complexArg', 'ComplexInput', '{intField: 4}', 4, 45, [ - 'In field "requiredField": Expected "Boolean!", found null.' - ]) - ]) + """, + [ + bad_value( + "complexArg", + "ComplexInput", + "{intField: 4}", + 4, + 45, + ['In field "requiredField": Expected "Boolean!", found null.'], + ) + ], + ) def test_partial_object_invalid_field_type(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { @@ -656,15 +801,25 @@ def test_partial_object_invalid_field_type(self): }) } } - ''', [ - bad_value('complexArg', 'ComplexInput', - '{stringListField: ["one", 2], requiredField: true}', 4, 45, [ - 'In field "stringListField": In element #1: Expected type "String", found 2.' - ]) - ]) + """, + [ + bad_value( + "complexArg", + "ComplexInput", + '{stringListField: ["one", 2], requiredField: true}', + 4, + 45, + [ + 'In field "stringListField": In element #1: Expected type "String", found 2.' + ], + ) + ], + ) def test_partial_object_unknown_field_arg(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { complicatedArgs { complexArgField(complexArg: { @@ -673,19 +828,26 @@ def test_partial_object_unknown_field_arg(self): }) } } - ''', [ - bad_value('complexArg', 'ComplexInput', - '{requiredField: true, unknownField: "value"}', 4, 45, [ - 'In field "unknownField": Unknown field.' - ]) - ]) + """, + [ + bad_value( + "complexArg", + "ComplexInput", + '{requiredField: true, unknownField: "value"}', + 4, + 45, + ['In field "unknownField": Unknown field.'], + ) + ], + ) # noinspection PyMethodMayBeStatic class TestDirectiveArguments(object): - def test_with_directives_of_valid_types(self): - expect_passes_rule(ArgumentsOfCorrectType, ''' + expect_passes_rule( + ArgumentsOfCorrectType, + """ { dog @include(if: true) { name @@ -694,16 +856,21 @@ def test_with_directives_of_valid_types(self): name } } - ''') + """, + ) def test_with_directive_with_incorrect_types(self): - expect_fails_rule(ArgumentsOfCorrectType, ''' + expect_fails_rule( + ArgumentsOfCorrectType, + """ { dog @include(if: "yes") { name @skip(if: ENUM) } } - ''', [ - bad_value('if', 'Boolean', '"yes"', 3, 30), - bad_value('if', 'Boolean', 'ENUM', 4, 32), - ]) + """, + [ + bad_value("if", "Boolean", '"yes"', 3, 30), + bad_value("if", "Boolean", "ENUM", 4, 32), + ], + ) diff --git a/graphql/validation/tests/test_default_values_of_correct_type.py b/graphql/validation/tests/test_default_values_of_correct_type.py index 25d2d55d..9ea0b439 100644 --- a/graphql/validation/tests/test_default_values_of_correct_type.py +++ b/graphql/validation/tests/test_default_values_of_correct_type.py @@ -6,41 +6,51 @@ def default_for_non_null_arg(var_name, type_name, guess_type_name, line, column): return { - 'message': DefaultValuesOfCorrectType.default_for_non_null_arg_message(var_name, type_name, guess_type_name), - 'locations': [SourceLocation(line, column)] + "message": DefaultValuesOfCorrectType.default_for_non_null_arg_message( + var_name, type_name, guess_type_name + ), + "locations": [SourceLocation(line, column)], } def bad_value(var_name, type_name, value, line, column, errors=None): if not errors: - errors = [ - 'Expected type "{}", found {}.'.format(type_name, value) - ] + errors = ['Expected type "{}", found {}.'.format(type_name, value)] return { - 'message': DefaultValuesOfCorrectType.bad_value_for_default_arg_message(var_name, type_name, value, errors), - 'locations': [SourceLocation(line, column)] + "message": DefaultValuesOfCorrectType.bad_value_for_default_arg_message( + var_name, type_name, value, errors + ), + "locations": [SourceLocation(line, column)], } def test_variables_with_no_default_values(): - return expect_passes_rule(DefaultValuesOfCorrectType, ''' + return expect_passes_rule( + DefaultValuesOfCorrectType, + """ query NullableValues($a: Int, $b: String, $c: ComplexInput) { dog { name } } - ''') + """, + ) def test_required_variables_without_default_values(): - expect_passes_rule(DefaultValuesOfCorrectType, ''' + expect_passes_rule( + DefaultValuesOfCorrectType, + """ query RequiredValues($a: Int!, $b: String!) { dog { name } } - ''') + """, + ) def test_variables_with_valid_default_values(): - expect_passes_rule(DefaultValuesOfCorrectType, ''' + expect_passes_rule( + DefaultValuesOfCorrectType, + """ query WithDefaultValues( $a: Int = 1, $b: String = "ok", @@ -48,22 +58,29 @@ def test_variables_with_valid_default_values(): ) { dog { name } } - ''') + """, + ) def test_no_required_variables_with_default_values(): - expect_fails_rule(DefaultValuesOfCorrectType, ''' + expect_fails_rule( + DefaultValuesOfCorrectType, + """ query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") { dog { name } } - ''', [ - default_for_non_null_arg('a', 'Int!', 'Int', 2, 47), - default_for_non_null_arg('b', 'String!', 'String', 2, 64) - ]) + """, + [ + default_for_non_null_arg("a", "Int!", "Int", 2, 47), + default_for_non_null_arg("b", "String!", "String", 2, 64), + ], + ) def test_variables_with_invalid_default_values(): - expect_fails_rule(DefaultValuesOfCorrectType, ''' + expect_fails_rule( + DefaultValuesOfCorrectType, + """ query InvalidDefaultValues( $a: Int = "one", $b: String = 4, @@ -71,34 +88,59 @@ def test_variables_with_invalid_default_values(): ) { dog { name } } - ''', [ - bad_value('a', 'Int', '"one"', 3, 19), - bad_value('b', 'String', '4', 4, 22), - bad_value('c', 'ComplexInput', '"notverycomplex"', 5, 28, [ - 'Expected "ComplexInput", found not an object.' - ]) - ]) + """, + [ + bad_value("a", "Int", '"one"', 3, 19), + bad_value("b", "String", "4", 4, 22), + bad_value( + "c", + "ComplexInput", + '"notverycomplex"', + 5, + 28, + ['Expected "ComplexInput", found not an object.'], + ), + ], + ) def test_variables_missing_required_field(): - expect_fails_rule(DefaultValuesOfCorrectType, ''' + expect_fails_rule( + DefaultValuesOfCorrectType, + """ query MissingRequiredField($a: ComplexInput = {intField: 3}) { dog { name } } - ''', [ - bad_value('a', 'ComplexInput', '{intField: 3}', 2, 51, [ - 'In field "requiredField": Expected "Boolean!", found null.' - ]) - ]) + """, + [ + bad_value( + "a", + "ComplexInput", + "{intField: 3}", + 2, + 51, + ['In field "requiredField": Expected "Boolean!", found null.'], + ) + ], + ) def test_list_variables_with_invalid_item(): - expect_fails_rule(DefaultValuesOfCorrectType, ''' + expect_fails_rule( + DefaultValuesOfCorrectType, + """ query invalidItem($a: [String] = ["one", 2]) { dog { name } } - ''', [ - bad_value('a', '[String]', '["one", 2]', 2, 38, [ - 'In element #1: Expected type "String", found 2.' - ]) - ]) + """, + [ + bad_value( + "a", + "[String]", + '["one", 2]', + 2, + 38, + ['In element #1: Expected type "String", found 2.'], + ) + ], + ) diff --git a/graphql/validation/tests/test_fields_on_correct_type.py b/graphql/validation/tests/test_fields_on_correct_type.py index da552ad3..20c1bcb5 100644 --- a/graphql/validation/tests/test_fields_on_correct_type.py +++ b/graphql/validation/tests/test_fields_on_correct_type.py @@ -1,70 +1,94 @@ from graphql.language.location import SourceLocation -from graphql.validation.rules.fields_on_correct_type import (FieldsOnCorrectType, - _undefined_field_message) +from graphql.validation.rules.fields_on_correct_type import ( + FieldsOnCorrectType, + _undefined_field_message, +) from .utils import expect_fails_rule, expect_passes_rule def undefined_field(field, gql_type, suggested_types, suggested_fields, line, column): return { - 'message': _undefined_field_message(field, gql_type, suggested_types, suggested_fields), - 'locations': [SourceLocation(line, column)] + "message": _undefined_field_message( + field, gql_type, suggested_types, suggested_fields + ), + "locations": [SourceLocation(line, column)], } def test_object_field_selection(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment objectFieldSelection on Dog { __typename name } - ''') + """, + ) def test_aliased_object_field_selection(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment aliasedObjectFieldSelection on Dog { tn : __typename otherName : name } - ''') + """, + ) def test_interface_field_selection(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment interfaceFieldSelection on Pet { __typename name } - ''') + """, + ) def test_aliased_interface_field_selection(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment interfaceFieldSelection on Pet { otherName : name } - ''') + """, + ) def test_lying_alias_selection(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment lyingAliasSelection on Dog { name : nickname } - ''') + """, + ) def test_ignores_fields_on_unknown_type(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment unknownSelection on UnknownType { unknownField } - ''') + """, + ) def test_reports_errors_when_type_is_known_again(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment typeKnownAgain on Pet { unknown_pet_field { ... on Cat { @@ -72,135 +96,159 @@ def test_reports_errors_when_type_is_known_again(): } } }, - ''', [ - undefined_field('unknown_pet_field', 'Pet', [], [], 3, 9), - undefined_field('unknown_cat_field', 'Cat', [], [], 5, 13) - ]) + """, + [ + undefined_field("unknown_pet_field", "Pet", [], [], 3, 9), + undefined_field("unknown_cat_field", "Cat", [], [], 5, 13), + ], + ) def test_field_not_defined_on_fragment(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment fieldNotDefined on Dog { meowVolume } - ''', [ - undefined_field('meowVolume', 'Dog', [], ['barkVolume'], 3, 9) - ]) + """, + [undefined_field("meowVolume", "Dog", [], ["barkVolume"], 3, 9)], + ) def test_ignores_deeply_unknown_field(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment deepFieldNotDefined on Dog { unknown_field { deeper_unknown_field } } - ''', [ - undefined_field('unknown_field', 'Dog', [], [], 3, 9) - ]) + """, + [undefined_field("unknown_field", "Dog", [], [], 3, 9)], + ) def test_sub_field_not_defined(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment subFieldNotDefined on Human { pets { unknown_field } } - ''', [ - undefined_field('unknown_field', 'Pet', [], [], 4, 11) - ]) + """, + [undefined_field("unknown_field", "Pet", [], [], 4, 11)], + ) def test_field_not_defined_on_inline_fragment(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment fieldNotDefined on Pet { ... on Dog { meowVolume } } - ''', [ - undefined_field('meowVolume', 'Dog', [], ['barkVolume'], 4, 11) - ]) + """, + [undefined_field("meowVolume", "Dog", [], ["barkVolume"], 4, 11)], + ) def test_aliased_field_target_not_defined(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment aliasedFieldTargetNotDefined on Dog { volume : mooVolume } - ''', [ - undefined_field('mooVolume', 'Dog', [], ['barkVolume'], 3, 9) - ]) + """, + [undefined_field("mooVolume", "Dog", [], ["barkVolume"], 3, 9)], + ) def test_aliased_lying_field_target_not_defined(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment aliasedLyingFieldTargetNotDefined on Dog { barkVolume : kawVolume } - ''', [ - undefined_field('kawVolume', 'Dog', [], ['barkVolume'], 3, 9) - ]) + """, + [undefined_field("kawVolume", "Dog", [], ["barkVolume"], 3, 9)], + ) def test_not_defined_on_interface(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment notDefinedOnInterface on Pet { tailLength } - ''', [ - undefined_field('tailLength', 'Pet', [], [], 3, 9) - ]) + """, + [undefined_field("tailLength", "Pet", [], [], 3, 9)], + ) def test_defined_on_implementors_but_not_on_interface(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment definedOnImplementorsButNotInterface on Pet { nickname } - ''', [ - undefined_field('nickname', 'Pet', ['Dog', 'Cat'], ['name'], 3, 9) - ]) + """, + [undefined_field("nickname", "Pet", ["Dog", "Cat"], ["name"], 3, 9)], + ) def test_meta_field_selection_on_union(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment directFieldSelectionOnUnion on CatOrDog { __typename } - ''') + """, + ) def test_direct_field_selection_on_union(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment directFieldSelectionOnUnion on CatOrDog { directField } - ''', [ - undefined_field('directField', 'CatOrDog', [], [], 3, 9) - ]) + """, + [undefined_field("directField", "CatOrDog", [], [], 3, 9)], + ) def test_defined_on_implementors_queried_on_union(): - expect_fails_rule(FieldsOnCorrectType, ''' + expect_fails_rule( + FieldsOnCorrectType, + """ fragment definedOnImplementorsQueriedOnUnion on CatOrDog { name } - ''', [ - undefined_field( - 'name', - 'CatOrDog', - ['Being', 'Pet', 'Canine', 'Dog', 'Cat'], - [], - 3, - 9 - ) - ]) + """, + [ + undefined_field( + "name", "CatOrDog", ["Being", "Pet", "Canine", "Dog", "Cat"], [], 3, 9 + ) + ], + ) def test_valid_field_in_inline_fragment(): - expect_passes_rule(FieldsOnCorrectType, ''' + expect_passes_rule( + FieldsOnCorrectType, + """ fragment objectFieldSelection on Pet { ... on Dog { name @@ -209,49 +257,49 @@ def test_valid_field_in_inline_fragment(): name } } - ''') + """, + ) def test_fields_correct_type_no_suggestion(): - message = _undefined_field_message('f', 'T', [], []) + message = _undefined_field_message("f", "T", [], []) assert message == 'Cannot query field "f" on type "T".' def test_works_with_no_small_numbers_of_type_suggestion(): - message = _undefined_field_message('f', 'T', ['A', 'B'], []) + message = _undefined_field_message("f", "T", ["A", "B"], []) assert message == ( - 'Cannot query field "f" on type "T". ' + - 'Did you mean to use an inline fragment on "A" or "B"?' + 'Cannot query field "f" on type "T". ' + + 'Did you mean to use an inline fragment on "A" or "B"?' ) def test_works_with_no_small_numbers_of_field_suggestion(): - message = _undefined_field_message('f', 'T', [], ['z', 'y']) + message = _undefined_field_message("f", "T", [], ["z", "y"]) assert message == ( - 'Cannot query field "f" on type "T". ' + - 'Did you mean "z" or "y"?' + 'Cannot query field "f" on type "T". ' + 'Did you mean "z" or "y"?' ) def test_only_shows_one_set_of_suggestions_at_a_time_preferring_types(): - message = _undefined_field_message('f', 'T', ['A', 'B'], ['z', 'y']) + message = _undefined_field_message("f", "T", ["A", "B"], ["z", "y"]) assert message == ( - 'Cannot query field "f" on type "T". ' + - 'Did you mean to use an inline fragment on "A" or "B"?' + 'Cannot query field "f" on type "T". ' + + 'Did you mean to use an inline fragment on "A" or "B"?' ) def test_limits_lots_of_type_suggestions(): - message = _undefined_field_message('f', 'T', ['A', 'B', 'C', 'D', 'E', 'F'], []) + message = _undefined_field_message("f", "T", ["A", "B", "C", "D", "E", "F"], []) assert message == ( - 'Cannot query field "f" on type "T". ' + - 'Did you mean to use an inline fragment on "A", "B", "C", "D" or "E"?' + 'Cannot query field "f" on type "T". ' + + 'Did you mean to use an inline fragment on "A", "B", "C", "D" or "E"?' ) def test_limits_lots_of_field_suggestions(): - message = _undefined_field_message('f', 'T', [], ['z', 'y', 'x', 'w', 'v', 'u']) + message = _undefined_field_message("f", "T", [], ["z", "y", "x", "w", "v", "u"]) assert message == ( - 'Cannot query field "f" on type "T". ' + - 'Did you mean "z", "y", "x", "w" or "v"?' + 'Cannot query field "f" on type "T". ' + + 'Did you mean "z", "y", "x", "w" or "v"?' ) diff --git a/graphql/validation/tests/test_fragments_on_composite_types.py b/graphql/validation/tests/test_fragments_on_composite_types.py index 531d74f4..0c4c4358 100644 --- a/graphql/validation/tests/test_fragments_on_composite_types.py +++ b/graphql/validation/tests/test_fragments_on_composite_types.py @@ -6,99 +6,126 @@ def fragment_on_non_composite_error(frag_name, type_name, line, column): return { - 'message': FragmentsOnCompositeTypes.fragment_on_non_composite_error_message(frag_name, type_name), - 'locations': [SourceLocation(line, column)] + "message": FragmentsOnCompositeTypes.fragment_on_non_composite_error_message( + frag_name, type_name + ), + "locations": [SourceLocation(line, column)], } def inline_fragment_on_non_composite_error(type_name, line, column): return { - 'message': FragmentsOnCompositeTypes.inline_fragment_on_non_composite_error_message(type_name), - 'locations': [SourceLocation(line, column)] + "message": FragmentsOnCompositeTypes.inline_fragment_on_non_composite_error_message( + type_name + ), + "locations": [SourceLocation(line, column)], } def test_object_is_valid_fragment_type(): - expect_passes_rule(FragmentsOnCompositeTypes, ''' + expect_passes_rule( + FragmentsOnCompositeTypes, + """ fragment validFragment on Dog { barks } - ''') + """, + ) def test_interface_is_valid_fragment_type(): - expect_passes_rule(FragmentsOnCompositeTypes, ''' + expect_passes_rule( + FragmentsOnCompositeTypes, + """ fragment validFragment on Pet { name } - ''') + """, + ) def test_object_is_valid_inline_fragment_type(): - expect_passes_rule(FragmentsOnCompositeTypes, ''' + expect_passes_rule( + FragmentsOnCompositeTypes, + """ fragment validFragment on Pet { ... on Dog { barks } } - ''') + """, + ) def test_inline_fragment_without_type_is_valid(): - expect_passes_rule(FragmentsOnCompositeTypes, ''' + expect_passes_rule( + FragmentsOnCompositeTypes, + """ fragment validFragment on Pet { ... { name } } - ''') + """, + ) def test_union_is_valid_fragment_type(): - expect_passes_rule(FragmentsOnCompositeTypes, ''' + expect_passes_rule( + FragmentsOnCompositeTypes, + """ fragment validFragment on CatOrDog { __typename } - ''') + """, + ) def test_scalar_is_invalid_fragment_type(): - expect_fails_rule(FragmentsOnCompositeTypes, ''' + expect_fails_rule( + FragmentsOnCompositeTypes, + """ fragment scalarFragment on Boolean { bad } - ''', [ - fragment_on_non_composite_error('scalarFragment', 'Boolean', 2, 34) - ]) + """, + [fragment_on_non_composite_error("scalarFragment", "Boolean", 2, 34)], + ) def test_enum_is_invalid_fragment_type(): - expect_fails_rule(FragmentsOnCompositeTypes, ''' + expect_fails_rule( + FragmentsOnCompositeTypes, + """ fragment scalarFragment on FurColor { bad } - ''', [ - fragment_on_non_composite_error('scalarFragment', 'FurColor', 2, 34) - ]) + """, + [fragment_on_non_composite_error("scalarFragment", "FurColor", 2, 34)], + ) def test_input_object_is_invalid_fragment_type(): - expect_fails_rule(FragmentsOnCompositeTypes, ''' + expect_fails_rule( + FragmentsOnCompositeTypes, + """ fragment inputFragment on ComplexInput { stringField } - ''', [ - fragment_on_non_composite_error('inputFragment', 'ComplexInput', 2, 33) - ]) + """, + [fragment_on_non_composite_error("inputFragment", "ComplexInput", 2, 33)], + ) def test_scalar_is_invalid_inline_fragment_type(): - expect_fails_rule(FragmentsOnCompositeTypes, ''' + expect_fails_rule( + FragmentsOnCompositeTypes, + """ fragment invalidFragment on Pet { ... on String { barks } } - ''', [ - inline_fragment_on_non_composite_error('String', 3, 16) - ]) + """, + [inline_fragment_on_non_composite_error("String", 3, 16)], + ) diff --git a/graphql/validation/tests/test_known_argument_names.py b/graphql/validation/tests/test_known_argument_names.py index 65630046..cbe6c053 100644 --- a/graphql/validation/tests/test_known_argument_names.py +++ b/graphql/validation/tests/test_known_argument_names.py @@ -1,67 +1,90 @@ from graphql.language.location import SourceLocation -from graphql.validation.rules.known_argument_names import (KnownArgumentNames, - _unknown_arg_message, - _unknown_directive_arg_message) +from graphql.validation.rules.known_argument_names import ( + KnownArgumentNames, + _unknown_arg_message, + _unknown_directive_arg_message, +) from .utils import expect_fails_rule, expect_passes_rule def unknown_arg(arg_name, field_name, type_name, suggested_args, line, column): return { - 'message': _unknown_arg_message(arg_name, field_name, type_name, suggested_args), - 'locations': [SourceLocation(line, column)] + "message": _unknown_arg_message( + arg_name, field_name, type_name, suggested_args + ), + "locations": [SourceLocation(line, column)], } def unknown_directive_arg(arg_name, directive_name, suggested_args, line, column): return { - 'message': _unknown_directive_arg_message(arg_name, directive_name, suggested_args), - 'locations': [SourceLocation(line, column)] + "message": _unknown_directive_arg_message( + arg_name, directive_name, suggested_args + ), + "locations": [SourceLocation(line, column)], } def test_single_arg_is_known(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ fragment argOnRequiredArg on Dog { doesKnowCommand(dogCommand: SIT) } - ''') + """, + ) def test_multiple_args_are_known(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ fragment multipleArgs on ComplicatedArgs { multipleReqs(req1: 1, req2: 2) } - ''') + """, + ) def test_ignore_args_of_unknown_fields(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ fragment argOnUnknownField on Dog { unknownField(unknownArg: SIT) } - ''') + """, + ) def test_multiple_args_in_reverse_order_are_known(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ fragment multipleArgsReverseOrder on ComplicatedArgs { multipleReqs(req2: 2, req1: 1) } - ''') + """, + ) def test_no_args_on_optional_arg(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ fragment noArgOnOptionalArg on Dog { isHousetrained } - ''') + """, + ) def test_args_are_known_deeply(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ { dog { doesKnowCommand(dogCommand: SIT) @@ -74,50 +97,64 @@ def test_args_are_known_deeply(): } } } - ''') + """, + ) def test_directive_args_are_known(): - expect_passes_rule(KnownArgumentNames, ''' + expect_passes_rule( + KnownArgumentNames, + """ { dog @skip(if: true) } - ''') + """, + ) def test_undirective_args_are_invalid(): - expect_fails_rule(KnownArgumentNames, ''' + expect_fails_rule( + KnownArgumentNames, + """ { dog @skip(unless: true) } - ''', [ - unknown_directive_arg('unless', 'skip', [], 3, 19) - ]) + """, + [unknown_directive_arg("unless", "skip", [], 3, 19)], + ) def test_invalid_arg_name(): - expect_fails_rule(KnownArgumentNames, ''' + expect_fails_rule( + KnownArgumentNames, + """ fragment invalidArgName on Dog { doesKnowCommand(unknown: true) } - ''', [ - unknown_arg('unknown', 'doesKnowCommand', 'Dog', [], 3, 25) - ]) + """, + [unknown_arg("unknown", "doesKnowCommand", "Dog", [], 3, 25)], + ) def test_unknown_args_amongst_known_args(): - expect_fails_rule(KnownArgumentNames, ''' + expect_fails_rule( + KnownArgumentNames, + """ fragment oneGoodArgOneInvalidArg on Dog { doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true) } - ''', [ - unknown_arg('whoknows', 'doesKnowCommand', 'Dog', [], 3, 25), - unknown_arg('unknown', 'doesKnowCommand', 'Dog', [], 3, 55) - ]) + """, + [ + unknown_arg("whoknows", "doesKnowCommand", "Dog", [], 3, 25), + unknown_arg("unknown", "doesKnowCommand", "Dog", [], 3, 55), + ], + ) def test_unknown_args_deeply(): - expect_fails_rule(KnownArgumentNames, ''' + expect_fails_rule( + KnownArgumentNames, + """ { dog { doesKnowCommand(unknown: true) @@ -130,7 +167,9 @@ def test_unknown_args_deeply(): } } } - ''', [ - unknown_arg('unknown', 'doesKnowCommand', 'Dog', [], 4, 27), - unknown_arg('unknown', 'doesKnowCommand', 'Dog', [], 9, 31) - ]) + """, + [ + unknown_arg("unknown", "doesKnowCommand", "Dog", [], 4, 27), + unknown_arg("unknown", "doesKnowCommand", "Dog", [], 9, 31), + ], + ) diff --git a/graphql/validation/tests/test_known_directives.py b/graphql/validation/tests/test_known_directives.py index bf27b773..2eb2a15a 100644 --- a/graphql/validation/tests/test_known_directives.py +++ b/graphql/validation/tests/test_known_directives.py @@ -6,20 +6,24 @@ def unknown_directive(directive_name, line, column): return { - 'message': KnownDirectives.unknown_directive_message(directive_name), - 'locations': [SourceLocation(line, column)] + "message": KnownDirectives.unknown_directive_message(directive_name), + "locations": [SourceLocation(line, column)], } def misplaced_directive(directive_name, placement, line, column): return { - 'message': KnownDirectives.misplaced_directive_message(directive_name, placement), - 'locations': [SourceLocation(line, column)] + "message": KnownDirectives.misplaced_directive_message( + directive_name, placement + ), + "locations": [SourceLocation(line, column)], } def test_with_no_directives(): - expect_passes_rule(KnownDirectives, ''' + expect_passes_rule( + KnownDirectives, + """ query Foo { name ...Frag @@ -28,11 +32,14 @@ def test_with_no_directives(): fragment Frag on Dog { name } - ''') + """, + ) def test_with_known_directives(): - expect_passes_rule(KnownDirectives, ''' + expect_passes_rule( + KnownDirectives, + """ { dog @include(if: true) { name @@ -41,23 +48,28 @@ def test_with_known_directives(): name } } - ''') + """, + ) def test_with_unknown_directive(): - expect_fails_rule(KnownDirectives, ''' + expect_fails_rule( + KnownDirectives, + """ { dog @unknown(directive: "value") { name } } - ''', [ - unknown_directive('unknown', 3, 13) - ]) + """, + [unknown_directive("unknown", 3, 13)], + ) def test_with_many_unknown_directives(): - expect_fails_rule(KnownDirectives, ''' + expect_fails_rule( + KnownDirectives, + """ { dog @unknown(directive: "value") { name @@ -69,15 +81,19 @@ def test_with_many_unknown_directives(): } } } - ''', [ - unknown_directive('unknown', 3, 13), - unknown_directive('unknown', 6, 15), - unknown_directive('unknown', 8, 16) - ]) + """, + [ + unknown_directive("unknown", 3, 13), + unknown_directive("unknown", 6, 15), + unknown_directive("unknown", 8, 16), + ], + ) def test_with_well_placed_directives(): - expect_passes_rule(KnownDirectives, ''' + expect_passes_rule( + KnownDirectives, + """ query Foo @onQuery{ name @include(if: true) ...Frag @include(if: true) @@ -88,11 +104,14 @@ def test_with_well_placed_directives(): mutation Bar @onMutation { someField } - ''') + """, + ) def test_with_misplaced_directives(): - expect_fails_rule(KnownDirectives, ''' + expect_fails_rule( + KnownDirectives, + """ query Foo @include(if: true) { name @onQuery ...Frag @onQuery @@ -101,19 +120,23 @@ def test_with_misplaced_directives(): mutation Bar @onQuery { someField } - ''', [ - misplaced_directive('include', 'QUERY', 2, 17), - misplaced_directive('onQuery', 'FIELD', 3, 14), - misplaced_directive('onQuery', 'FRAGMENT_SPREAD', 4, 17), - misplaced_directive('onQuery', 'MUTATION', 7, 20), - - ]) + """, + [ + misplaced_directive("include", "QUERY", 2, 17), + misplaced_directive("onQuery", "FIELD", 3, 14), + misplaced_directive("onQuery", "FRAGMENT_SPREAD", 4, 17), + misplaced_directive("onQuery", "MUTATION", 7, 20), + ], + ) # within schema language + def test_within_schema_language_with_well_placed_directives(): - expect_passes_rule(KnownDirectives, ''' + expect_passes_rule( + KnownDirectives, + """ type MyObj implements MyInterface @onObject { myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition } @@ -137,11 +160,14 @@ def test_within_schema_language_with_well_placed_directives(): schema @OnSchema { query: MyQuery } - ''') + """, + ) def test_within_schema_language_with_misplaced_directives(): - expect_fails_rule(KnownDirectives, ''' + expect_fails_rule( + KnownDirectives, + """ type MyObj implements MyInterface @onInterface { myField(myArg: Int @onInputFieldDefinition): String @onInputFieldDefinition } @@ -165,18 +191,22 @@ def test_within_schema_language_with_misplaced_directives(): schema @onObject { query: MyQuery } - ''', [ - misplaced_directive('onInterface', 'OBJECT', 2, 43), - misplaced_directive('onInputFieldDefinition', 'ARGUMENT_DEFINITION', 3, 30), - misplaced_directive('onInputFieldDefinition', 'FIELD_DEFINITION', 3, 63), - misplaced_directive('onEnum', 'SCALAR', 6, 25), - misplaced_directive('onObject', 'INTERFACE', 8, 31), - misplaced_directive('onInputFieldDefinition', 'ARGUMENT_DEFINITION', 9, 30), - misplaced_directive('onInputFieldDefinition', 'FIELD_DEFINITION', 9, 63), - misplaced_directive('onEnumValue', 'UNION', 12, 23), - misplaced_directive('onScalar', 'ENUM', 14, 21), - misplaced_directive('onUnion', 'ENUM_VALUE', 15, 20), - misplaced_directive('onEnum', 'INPUT_OBJECT', 18, 23), - misplaced_directive('onArgumentDefinition', 'INPUT_FIELD_DEFINITION', 19, 24), - misplaced_directive('onObject', 'SCHEMA', 22, 16), - ]) + """, + [ + misplaced_directive("onInterface", "OBJECT", 2, 43), + misplaced_directive("onInputFieldDefinition", "ARGUMENT_DEFINITION", 3, 30), + misplaced_directive("onInputFieldDefinition", "FIELD_DEFINITION", 3, 63), + misplaced_directive("onEnum", "SCALAR", 6, 25), + misplaced_directive("onObject", "INTERFACE", 8, 31), + misplaced_directive("onInputFieldDefinition", "ARGUMENT_DEFINITION", 9, 30), + misplaced_directive("onInputFieldDefinition", "FIELD_DEFINITION", 9, 63), + misplaced_directive("onEnumValue", "UNION", 12, 23), + misplaced_directive("onScalar", "ENUM", 14, 21), + misplaced_directive("onUnion", "ENUM_VALUE", 15, 20), + misplaced_directive("onEnum", "INPUT_OBJECT", 18, 23), + misplaced_directive( + "onArgumentDefinition", "INPUT_FIELD_DEFINITION", 19, 24 + ), + misplaced_directive("onObject", "SCHEMA", 22, 16), + ], + ) diff --git a/graphql/validation/tests/test_known_fragment_names.py b/graphql/validation/tests/test_known_fragment_names.py index 3364b2ee..e6940fbf 100644 --- a/graphql/validation/tests/test_known_fragment_names.py +++ b/graphql/validation/tests/test_known_fragment_names.py @@ -6,13 +6,15 @@ def undefined_fragment(fragment_name, line, column): return { - 'message': KnownFragmentNames.unknown_fragment_message(fragment_name), - 'locations': [SourceLocation(line, column)] + "message": KnownFragmentNames.unknown_fragment_message(fragment_name), + "locations": [SourceLocation(line, column)], } def test_known_fragment_names_are_valid(): - expect_passes_rule(KnownFragmentNames, ''' + expect_passes_rule( + KnownFragmentNames, + """ { human(id: 4) { ...HumanFields1 @@ -34,11 +36,14 @@ def test_known_fragment_names_are_valid(): fragment HumanFields3 on Human { name } - ''') + """, + ) def test_unknown_fragment_names_are_invalid(): - expect_fails_rule(KnownFragmentNames, ''' + expect_fails_rule( + KnownFragmentNames, + """ { human(id: 4) { ...UnknownFragment1 @@ -51,8 +56,10 @@ def test_unknown_fragment_names_are_invalid(): name ...UnknownFragment3 } - ''', [ - undefined_fragment('UnknownFragment1', 4, 16), - undefined_fragment('UnknownFragment2', 6, 20), - undefined_fragment('UnknownFragment3', 12, 12), - ]) + """, + [ + undefined_fragment("UnknownFragment1", 4, 16), + undefined_fragment("UnknownFragment2", 6, 20), + undefined_fragment("UnknownFragment3", 12, 12), + ], + ) diff --git a/graphql/validation/tests/test_known_type_names.py b/graphql/validation/tests/test_known_type_names.py index a9f40c19..a0353861 100644 --- a/graphql/validation/tests/test_known_type_names.py +++ b/graphql/validation/tests/test_known_type_names.py @@ -1,19 +1,23 @@ from graphql.language.location import SourceLocation -from graphql.validation.rules.known_type_names import (KnownTypeNames, - _unknown_type_message) +from graphql.validation.rules.known_type_names import ( + KnownTypeNames, + _unknown_type_message, +) from .utils import expect_fails_rule, expect_passes_rule def unknown_type(type_name, suggested_types, line, column): return { - 'message': _unknown_type_message(type_name, suggested_types), - 'locations': [SourceLocation(line, column)] + "message": _unknown_type_message(type_name, suggested_types), + "locations": [SourceLocation(line, column)], } def test_known_type_names_are_valid(): - expect_passes_rule(KnownTypeNames, ''' + expect_passes_rule( + KnownTypeNames, + """ query Foo($var: String, $required: [String!]!) { user(id: 4) { pets { ... on Pet { name }, ...PetFields, ... { name } } @@ -22,11 +26,14 @@ def test_known_type_names_are_valid(): fragment PetFields on Pet { name } - ''') + """, + ) def test_unknown_type_names_are_invalid(): - expect_fails_rule(KnownTypeNames, ''' + expect_fails_rule( + KnownTypeNames, + """ query Foo($var: JumbledUpLetters) { user(id: 4) { name @@ -36,15 +43,19 @@ def test_unknown_type_names_are_invalid(): fragment PetFields on Peettt { name } - ''', [ - unknown_type('JumbledUpLetters', [], 2, 23), - unknown_type('Badger', [], 5, 25), - unknown_type('Peettt', ['Pet'], 8, 29), - ]) + """, + [ + unknown_type("JumbledUpLetters", [], 2, 23), + unknown_type("Badger", [], 5, 25), + unknown_type("Peettt", ["Pet"], 8, 29), + ], + ) def test_ignores_type_definitions(): - expect_fails_rule(KnownTypeNames, ''' + expect_fails_rule( + KnownTypeNames, + """ type NotInTheSchema { field: FooBar } @@ -60,6 +71,6 @@ def test_ignores_type_definitions(): id } } - ''', [ - unknown_type('NotInTheSchema', [], 12, 23), - ]) + """, + [unknown_type("NotInTheSchema", [], 12, 23)], + ) diff --git a/graphql/validation/tests/test_lone_anonymous_operation.py b/graphql/validation/tests/test_lone_anonymous_operation.py index 67707580..0d1e493d 100644 --- a/graphql/validation/tests/test_lone_anonymous_operation.py +++ b/graphql/validation/tests/test_lone_anonymous_operation.py @@ -6,29 +6,37 @@ def anon_not_alone(line, column): return { - 'message': LoneAnonymousOperation.anonymous_operation_not_alone_message(), - 'locations': [SourceLocation(line, column)] + "message": LoneAnonymousOperation.anonymous_operation_not_alone_message(), + "locations": [SourceLocation(line, column)], } def test_no_operations(): - expect_passes_rule(LoneAnonymousOperation, ''' + expect_passes_rule( + LoneAnonymousOperation, + """ fragment fragA on Type { field } - ''') + """, + ) def test_one_anon_operation(): - expect_passes_rule(LoneAnonymousOperation, ''' + expect_passes_rule( + LoneAnonymousOperation, + """ { field } - ''') + """, + ) def test_multiple_named_operation(): - expect_passes_rule(LoneAnonymousOperation, ''' + expect_passes_rule( + LoneAnonymousOperation, + """ query Foo { field } @@ -36,55 +44,64 @@ def test_multiple_named_operation(): query Bar { field } - ''') + """, + ) def test_anon_operation_with_fragment(): - expect_passes_rule(LoneAnonymousOperation, ''' + expect_passes_rule( + LoneAnonymousOperation, + """ { ...Foo } fragment Foo on Type { field } - ''') + """, + ) def test_multiple_anon_operations(): - expect_fails_rule(LoneAnonymousOperation, ''' + expect_fails_rule( + LoneAnonymousOperation, + """ { fieldA } { fieldB } - ''', [ - anon_not_alone(2, 7), - anon_not_alone(5, 7), - ]) + """, + [anon_not_alone(2, 7), anon_not_alone(5, 7)], + ) def test_anon_operation_with_a_mutation(): - expect_fails_rule(LoneAnonymousOperation, ''' + expect_fails_rule( + LoneAnonymousOperation, + """ { fieldA } mutation Foo { fieldB } - ''', [ - anon_not_alone(2, 7) - ]) + """, + [anon_not_alone(2, 7)], + ) def test_anon_operation_with_a_subscription(): - expect_fails_rule(LoneAnonymousOperation, ''' + expect_fails_rule( + LoneAnonymousOperation, + """ { fieldA } subscription Foo { fieldB } - ''', [ - anon_not_alone(2, 7) - ]) + """, + [anon_not_alone(2, 7)], + ) diff --git a/graphql/validation/tests/test_no_fragment_cycles.py b/graphql/validation/tests/test_no_fragment_cycles.py index 4403a35e..93c3331c 100644 --- a/graphql/validation/tests/test_no_fragment_cycles.py +++ b/graphql/validation/tests/test_no_fragment_cycles.py @@ -6,35 +6,46 @@ def cycle_error_message(fragment_name, spread_names, *locations): return { - 'message': NoFragmentCycles.cycle_error_message(fragment_name, spread_names), - 'locations': list(locations) + "message": NoFragmentCycles.cycle_error_message(fragment_name, spread_names), + "locations": list(locations), } def test_single_reference_is_valid(): - expect_passes_rule(NoFragmentCycles, ''' + expect_passes_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB } fragment fragB on Dog { name } - ''') + """, + ) def test_spreading_twice_is_not_circular(): - expect_passes_rule(NoFragmentCycles, ''' + expect_passes_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB, ...fragB } fragment fragB on Dog { name } - ''') + """, + ) def test_spreading_twice_indirectly_is_not_circular(): - expect_passes_rule(NoFragmentCycles, ''' + expect_passes_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { name } - ''') + """, + ) def test_double_spread_within_abstract_types(): - expect_passes_rule(NoFragmentCycles, ''' + expect_passes_rule( + NoFragmentCycles, + """ fragment nameFragment on Pet { ... on Dog { name } ... on Cat { name } @@ -43,65 +54,81 @@ def test_double_spread_within_abstract_types(): ... on Dog { ...nameFragment } ... on Cat { ...nameFragment } } - ''') + """, + ) def test_does_not_raise_false_positive_on_unknown_fragment(): - expect_passes_rule(NoFragmentCycles, ''' + expect_passes_rule( + NoFragmentCycles, + """ fragment nameFragment on Pet { ...UnknownFragment } - ''') + """, + ) def test_spreading_recursively_within_field_fails(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Human { relatives { ...fragA } }, - ''', [ - cycle_error_message('fragA', [], L(2, 43)) - ]) + """, + [cycle_error_message("fragA", [], L(2, 43))], + ) def test_no_spreading_itself_directly(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragA } - ''', [ - cycle_error_message('fragA', [], L(2, 29)) - ]) + """, + [cycle_error_message("fragA", [], L(2, 29))], + ) def test_no_spreading_itself_directly_within_inline_fragment(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Pet { ... on Dog { ...fragA } } - ''', [ - cycle_error_message('fragA', [], L(4, 13)) - ]) + """, + [cycle_error_message("fragA", [], L(4, 13))], + ) def test_no_spreading_itself_indirectly(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragA } - ''', [ - cycle_error_message('fragA', ['fragB'], L(2, 29), L(3, 29)) - ]) + """, + [cycle_error_message("fragA", ["fragB"], L(2, 29), L(3, 29))], + ) def test_no_spreading_itself_indirectly_reports_opposite_order(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragB on Dog { ...fragA } fragment fragA on Dog { ...fragB } - ''', [ - cycle_error_message('fragB', ['fragA'], L(2, 29), L(3, 29)) - ]) + """, + [cycle_error_message("fragB", ["fragA"], L(2, 29), L(3, 29))], + ) def test_no_spreading_itself_indirectly_within_inline_fragment(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Pet { ... on Dog { ...fragB @@ -112,14 +139,15 @@ def test_no_spreading_itself_indirectly_within_inline_fragment(): ...fragA } } - ''', [ - cycle_error_message('fragA', ['fragB'], L(4, 13), L(9, 13)) - ]) + """, + [cycle_error_message("fragA", ["fragB"], L(4, 13), L(9, 13))], + ) def test_no_spreading_itself_deeply(): expect_fails_rule( - NoFragmentCycles, ''' + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragO } @@ -128,53 +156,73 @@ def test_no_spreading_itself_deeply(): fragment fragZ on Dog { ...fragO } fragment fragO on Dog { ...fragP } fragment fragP on Dog { ...fragA, ...fragX } - ''', [ + """, + [ cycle_error_message( - 'fragA', [ - 'fragB', 'fragC', 'fragO', 'fragP'], L( - 2, 29), L( - 3, 29), L( - 4, 29), L( - 8, 29), L( - 9, 29)), cycle_error_message( - 'fragO', [ - 'fragP', 'fragX', 'fragY', 'fragZ'], L( - 8, 29), L( - 9, 39), L( - 5, 29), L( - 6, 29), L( - 7, 29))]) + "fragA", + ["fragB", "fragC", "fragO", "fragP"], + L(2, 29), + L(3, 29), + L(4, 29), + L(8, 29), + L(9, 29), + ), + cycle_error_message( + "fragO", + ["fragP", "fragX", "fragY", "fragZ"], + L(8, 29), + L(9, 39), + L(5, 29), + L(6, 29), + L(7, 29), + ), + ], + ) def test_no_spreading_itself_deeply_two_paths(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragA } fragment fragC on Dog { ...fragA } - ''', [ - cycle_error_message('fragA', ['fragB'], L(2, 29), L(3, 29)), - cycle_error_message('fragA', ['fragC'], L(2, 39), L(4, 29)) - ]) + """, + [ + cycle_error_message("fragA", ["fragB"], L(2, 29), L(3, 29)), + cycle_error_message("fragA", ["fragC"], L(2, 39), L(4, 29)), + ], + ) def test_no_spreading_itself_deeply_two_paths_alt_reverse_order(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragA, ...fragB } - ''', [ - cycle_error_message('fragA', ['fragC'], L(2, 29), L(4, 29)), - cycle_error_message('fragC', ['fragB'], L(4, 39), L(3, 29)) - ]) + """, + [ + cycle_error_message("fragA", ["fragC"], L(2, 29), L(4, 29)), + cycle_error_message("fragC", ["fragB"], L(4, 39), L(3, 29)), + ], + ) def test_no_spreading_itself_deeply_and_immediately(): - expect_fails_rule(NoFragmentCycles, ''' + expect_fails_rule( + NoFragmentCycles, + """ fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragB, ...fragC } fragment fragC on Dog { ...fragA, ...fragB } - ''', [ - cycle_error_message('fragB', [], L(3, 29)), - cycle_error_message('fragA', ['fragB', 'fragC'], L(2, 29), L(3, 39), L(4, 29)), - cycle_error_message('fragB', ['fragC'], L(3, 39), L(4, 39)) - ]) + """, + [ + cycle_error_message("fragB", [], L(3, 29)), + cycle_error_message( + "fragA", ["fragB", "fragC"], L(2, 29), L(3, 39), L(4, 29) + ), + cycle_error_message("fragB", ["fragC"], L(3, 39), L(4, 39)), + ], + ) diff --git a/graphql/validation/tests/test_no_undefined_variables.py b/graphql/validation/tests/test_no_undefined_variables.py index 11e566b7..12116a36 100644 --- a/graphql/validation/tests/test_no_undefined_variables.py +++ b/graphql/validation/tests/test_no_undefined_variables.py @@ -6,24 +6,26 @@ def undefined_var(var_name, l1, c1, op_name, l2, c2): return { - 'message': NoUndefinedVariables.undefined_var_message(var_name, op_name), - 'locations': [ - SourceLocation(l1, c1), - SourceLocation(l2, c2), - ] + "message": NoUndefinedVariables.undefined_var_message(var_name, op_name), + "locations": [SourceLocation(l1, c1), SourceLocation(l2, c2)], } def test_all_varriables_defined(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } - ''') + """, + ) def test_all_variables_deeply_defined(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -31,11 +33,14 @@ def test_all_variables_deeply_defined(): } } } - ''') + """, + ) def test_all_variables_deeply_in_inline_fragments_defined(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { @@ -47,11 +52,14 @@ def test_all_variables_deeply_in_inline_fragments_defined(): } } } - ''') + """, + ) def test_all_variables_in_fragments_deeply_defined(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -68,11 +76,14 @@ def test_all_variables_in_fragments_deeply_defined(): fragment FragC on Type { field(c: $c) } - ''') + """, + ) def test_variable_within_single_fragment_defined_in_multiple_operations(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String) { ...FragA } @@ -82,11 +93,14 @@ def test_variable_within_single_fragment_defined_in_multiple_operations(): fragment FragA on Type { field(a: $a) } - ''') + """, + ) def test_variable_within_fragments_defined_in_operations(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String) { ...FragA } @@ -99,11 +113,14 @@ def test_variable_within_fragments_defined_in_operations(): fragment FragB on Type { field(b: $b) } - ''') + """, + ) def test_variable_within_recursive_fragment_defined(): - expect_passes_rule(NoUndefinedVariables, ''' + expect_passes_rule( + NoUndefinedVariables, + """ query Foo($a: String) { ...FragA } @@ -112,55 +129,68 @@ def test_variable_within_recursive_fragment_defined(): ...FragA } } - ''') + """, + ) def test_variable_not_defined(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c, d: $d) } - ''', [ - undefined_var('d', 3, 39, 'Foo', 2, 7) - ]) + """, + [undefined_var("d", 3, 39, "Foo", 2, 7)], + ) def variable_not_defined_by_unnamed_query(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ { field(a: $a) } - ''', [ - undefined_var('a', 3, 18, '', 2, 7) - ]) + """, + [undefined_var("a", 3, 18, "", 2, 7)], + ) def test_multiple_variables_not_defined(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($b: String) { field(a: $a, b: $b, c: $c) } - ''', [ - undefined_var('a', 3, 18, 'Foo', 2, 7), - undefined_var('c', 3, 32, 'Foo', 2, 7) - ]) + """, + [ + undefined_var("a", 3, 18, "Foo", 2, 7), + undefined_var("c", 3, 32, "Foo", 2, 7), + ], + ) def test_variable_in_fragment_not_defined_by_unnamed_query(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ { ...FragA } fragment FragA on Type { field(a: $a) } - ''', [ - undefined_var('a', 6, 18, '', 2, 7) - ]) + """, + [undefined_var("a", 6, 18, "", 2, 7)], + ) def test_variable_in_fragment_not_defined_by_operation(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($a: String, $b: String) { ...FragA } @@ -177,13 +207,15 @@ def test_variable_in_fragment_not_defined_by_operation(): fragment FragC on Type { field(c: $c) } - ''', [ - undefined_var('c', 16, 18, 'Foo', 2, 7) - ]) + """, + [undefined_var("c", 16, 18, "Foo", 2, 7)], + ) def test_multiple_variables_in_fragments_not_defined(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($b: String) { ...FragA } @@ -200,14 +232,18 @@ def test_multiple_variables_in_fragments_not_defined(): fragment FragC on Type { field(c: $c) } - ''', [ - undefined_var('a', 6, 18, 'Foo', 2, 7), - undefined_var('c', 16, 18, 'Foo', 2, 7) - ]) + """, + [ + undefined_var("a", 6, 18, "Foo", 2, 7), + undefined_var("c", 16, 18, "Foo", 2, 7), + ], + ) def test_single_variable_in_fragment_not_defined_by_multiple_operations(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($a: String) { ...FragAB } @@ -217,14 +253,18 @@ def test_single_variable_in_fragment_not_defined_by_multiple_operations(): fragment FragAB on Type { field(a: $a, b: $b) } - ''', [ - undefined_var('b', 9, 25, 'Foo', 2, 7), - undefined_var('b', 9, 25, 'Bar', 5, 7) - ]) + """, + [ + undefined_var("b", 9, 25, "Foo", 2, 7), + undefined_var("b", 9, 25, "Bar", 5, 7), + ], + ) def test_variables_in_fragment_not_defined_by_multiple_operations(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($b: String) { ...FragAB } @@ -234,14 +274,18 @@ def test_variables_in_fragment_not_defined_by_multiple_operations(): fragment FragAB on Type { field(a: $a, b: $b) } - ''', [ - undefined_var('a', 9, 18, 'Foo', 2, 7), - undefined_var('b', 9, 25, 'Bar', 5, 7) - ]) + """, + [ + undefined_var("a", 9, 18, "Foo", 2, 7), + undefined_var("b", 9, 25, "Bar", 5, 7), + ], + ) def test_variable_in_fragment_used_by_other_operation(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($b: String) { ...FragA } @@ -254,14 +298,18 @@ def test_variable_in_fragment_used_by_other_operation(): fragment FragB on Type { field(b: $b) } - ''', [ - undefined_var('a', 9, 18, 'Foo', 2, 7), - undefined_var('b', 12, 18, 'Bar', 5, 7) - ]) + """, + [ + undefined_var("a", 9, 18, "Foo", 2, 7), + undefined_var("b", 12, 18, "Bar", 5, 7), + ], + ) def test_multiple_undefined_variables_produce_multiple_errors(): - expect_fails_rule(NoUndefinedVariables, ''' + expect_fails_rule( + NoUndefinedVariables, + """ query Foo($b: String) { ...FragAB } @@ -276,11 +324,13 @@ def test_multiple_undefined_variables_produce_multiple_errors(): fragment FragC on Type { field2(c: $c) } - ''', [ - undefined_var('a', 9, 19, 'Foo', 2, 7), - undefined_var('a', 11, 19, 'Foo', 2, 7), - undefined_var('c', 14, 19, 'Foo', 2, 7), - undefined_var('b', 9, 26, 'Bar', 5, 7), - undefined_var('b', 11, 26, 'Bar', 5, 7), - undefined_var('c', 14, 19, 'Bar', 5, 7), - ]) + """, + [ + undefined_var("a", 9, 19, "Foo", 2, 7), + undefined_var("a", 11, 19, "Foo", 2, 7), + undefined_var("c", 14, 19, "Foo", 2, 7), + undefined_var("b", 9, 26, "Bar", 5, 7), + undefined_var("b", 11, 26, "Bar", 5, 7), + undefined_var("c", 14, 19, "Bar", 5, 7), + ], + ) diff --git a/graphql/validation/tests/test_no_unused_fragments.py b/graphql/validation/tests/test_no_unused_fragments.py index a27df046..9cbb0581 100644 --- a/graphql/validation/tests/test_no_unused_fragments.py +++ b/graphql/validation/tests/test_no_unused_fragments.py @@ -6,13 +6,15 @@ def unused_fragment(fragment_name, line, column): return { - 'message': NoUnusedFragments.unused_fragment_message(fragment_name), - 'locations': [SourceLocation(line, column)] + "message": NoUnusedFragments.unused_fragment_message(fragment_name), + "locations": [SourceLocation(line, column)], } def test_all_fragment_names_are_used(): - expect_passes_rule(NoUnusedFragments, ''' + expect_passes_rule( + NoUnusedFragments, + """ { human(id: 4) { ...HumanFields1 @@ -31,11 +33,14 @@ def test_all_fragment_names_are_used(): fragment HumanFields3 on Human { name } - ''') + """, + ) def test_all_fragment_names_are_used_by_multiple_operations(): - expect_passes_rule(NoUnusedFragments, ''' + expect_passes_rule( + NoUnusedFragments, + """ query Foo { human(id: 4) { ...HumanFields1 @@ -56,11 +61,14 @@ def test_all_fragment_names_are_used_by_multiple_operations(): fragment HumanFields3 on Human { name } - ''') + """, + ) def test_contains_unknown_fragments(): - expect_fails_rule(NoUnusedFragments, ''' + expect_fails_rule( + NoUnusedFragments, + """ query Foo { human(id: 4) { ...HumanFields1 @@ -87,14 +95,15 @@ def test_contains_unknown_fragments(): fragment Unused2 on Human { name } - ''', [ - unused_fragment('Unused1', 22, 7), - unused_fragment('Unused2', 25, 7), - ]) + """, + [unused_fragment("Unused1", 22, 7), unused_fragment("Unused2", 25, 7)], + ) def test_contains_unknown_fragments_with_ref_cycle(): - expect_fails_rule(NoUnusedFragments, ''' + expect_fails_rule( + NoUnusedFragments, + """ query Foo { human(id: 4) { ...HumanFields1 @@ -123,14 +132,15 @@ def test_contains_unknown_fragments_with_ref_cycle(): name ...Unused1 } - ''', [ - unused_fragment('Unused1', 22, 7), - unused_fragment('Unused2', 26, 7), - ]) + """, + [unused_fragment("Unused1", 22, 7), unused_fragment("Unused2", 26, 7)], + ) def test_contains_unknown_and_undefined_fragments(): - expect_fails_rule(NoUnusedFragments, ''' + expect_fails_rule( + NoUnusedFragments, + """ query Foo { human(id: 4) { ...bar @@ -139,6 +149,6 @@ def test_contains_unknown_and_undefined_fragments(): fragment foo on Human { name } - ''', [ - unused_fragment('foo', 7, 7) - ]) + """, + [unused_fragment("foo", 7, 7)], + ) diff --git a/graphql/validation/tests/test_no_unused_variables.py b/graphql/validation/tests/test_no_unused_variables.py index 3060b102..b877c3da 100644 --- a/graphql/validation/tests/test_no_unused_variables.py +++ b/graphql/validation/tests/test_no_unused_variables.py @@ -6,21 +6,26 @@ def unused_variable(variable_name, op_name, line, column): return { - 'message': NoUnusedVariables.unused_variable_message(variable_name, op_name), - 'locations': [SourceLocation(line, column)] + "message": NoUnusedVariables.unused_variable_message(variable_name, op_name), + "locations": [SourceLocation(line, column)], } def test_uses_all_variables(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query ($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } - ''') + """, + ) def test_uses_all_variables_deeply(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -28,11 +33,14 @@ def test_uses_all_variables_deeply(): } } } - ''') + """, + ) def test_uses_all_variables_deeply_in_inline_fragments(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { @@ -44,11 +52,14 @@ def test_uses_all_variables_deeply_in_inline_fragments(): } } } - ''') + """, + ) def test_uses_all_variables_in_fragment(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -65,11 +76,14 @@ def test_uses_all_variables_in_fragment(): fragment FragC on Type { field(c: $c) } - ''') + """, + ) def test_variable_used_by_fragment_in_multiple_operations(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query Foo($a: String) { ...FragA } @@ -82,11 +96,14 @@ def test_variable_used_by_fragment_in_multiple_operations(): fragment FragB on Type { field(b: $b) } - ''') + """, + ) def test_variable_used_by_recursive_fragment(): - expect_passes_rule(NoUnusedVariables, ''' + expect_passes_rule( + NoUnusedVariables, + """ query Foo($a: String) { ...FragA } @@ -95,32 +112,38 @@ def test_variable_used_by_recursive_fragment(): ...FragA } } - ''') + """, + ) def test_variable_not_used(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query ($a: String, $b: String, $c: String) { field(a: $a, b: $b) } - ''', [ - unused_variable('c', None, 2, 38) - ]) + """, + [unused_variable("c", None, 2, 38)], + ) def test_multiple_variables_not_used(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { field(b: $b) } - ''', [ - unused_variable('a', 'Foo', 2, 17), - unused_variable('c', 'Foo', 2, 41) - ]) + """, + [unused_variable("a", "Foo", 2, 17), unused_variable("c", "Foo", 2, 41)], + ) def test_variable_not_used_in_fragments(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -137,13 +160,15 @@ def test_variable_not_used_in_fragments(): fragment FragC on Type { field } - ''', [ - unused_variable('c', 'Foo', 2, 41) - ]) + """, + [unused_variable("c", "Foo", 2, 41)], + ) def test_multiple_variables_not_used_in_fragments(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -160,14 +185,15 @@ def test_multiple_variables_not_used_in_fragments(): fragment FragC on Type { field } - ''', [ - unused_variable('a', 'Foo', 2, 17), - unused_variable('c', 'Foo', 2, 41) - ]) + """, + [unused_variable("a", "Foo", 2, 17), unused_variable("c", "Foo", 2, 41)], + ) def test_variable_not_used_by_unreferenced_fragment(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query Foo($b: String) { ...FragA } @@ -177,13 +203,15 @@ def test_variable_not_used_by_unreferenced_fragment(): fragment FragB on Type { field(b: $b) } - ''', [ - unused_variable('b', 'Foo', 2, 17), - ]) + """, + [unused_variable("b", "Foo", 2, 17)], + ) def test_variable_not_used_by_fragment_used_by_other_operation(): - expect_fails_rule(NoUnusedVariables, ''' + expect_fails_rule( + NoUnusedVariables, + """ query Foo($b: String) { ...FragA } @@ -196,7 +224,6 @@ def test_variable_not_used_by_fragment_used_by_other_operation(): fragment FragB on Type { field(b: $b) } - ''', [ - unused_variable('b', 'Foo', 2, 17), - unused_variable('a', 'Bar', 5, 17), - ]) + """, + [unused_variable("b", "Foo", 2, 17), unused_variable("a", "Bar", 5, 17)], + ) diff --git a/graphql/validation/tests/test_overlapping_fields_can_be_merged.py b/graphql/validation/tests/test_overlapping_fields_can_be_merged.py index 4e1cfb46..55a2b8c2 100644 --- a/graphql/validation/tests/test_overlapping_fields_can_be_merged.py +++ b/graphql/validation/tests/test_overlapping_fields_can_be_merged.py @@ -1,98 +1,139 @@ from graphql.language.location import SourceLocation as L -from graphql.type.definition import (GraphQLArgument, GraphQLField, - GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType) +from graphql.type.definition import ( + GraphQLArgument, + GraphQLField, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, +) from graphql.type.scalars import GraphQLID, GraphQLInt, GraphQLString from graphql.type.schema import GraphQLSchema from graphql.validation.rules import OverlappingFieldsCanBeMerged -from .utils import (expect_fails_rule, expect_fails_rule_with_schema, - expect_passes_rule, expect_passes_rule_with_schema) +from .utils import ( + expect_fails_rule, + expect_fails_rule_with_schema, + expect_passes_rule, + expect_passes_rule_with_schema, +) def fields_conflict(reason_name, reason, *locations): return { - 'message': OverlappingFieldsCanBeMerged.fields_conflict_message(reason_name, reason), - 'locations': list(locations) + "message": OverlappingFieldsCanBeMerged.fields_conflict_message( + reason_name, reason + ), + "locations": list(locations), } def test_unique_fields(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment uniqueFields on Dog { name nickname } - ''') + """, + ) def test_identical_fields(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment mergeIdenticalFields on Dog { name name } - ''') + """, + ) def test_identical_fields_with_identical_args(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment mergeIdenticalFieldsWithIdenticalArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT) } - ''') + """, + ) def test_identical_fields_with_identical_directives(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment mergeSameFieldsWithSameDirectives on Dog { name @include(if: true) name @include(if: true) } - ''') + """, + ) def test_different_args_with_different_aliases(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment differentArgsWithDifferentAliases on Dog { knowsSit: doesKnowCommand(dogCommand: SIT) knowsDown: doesKnowCommand(dogCommand: DOWN) } - ''') + """, + ) def test_different_directives_with_different_aliases(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment differentDirectivesWithDifferentAliases on Dog { nameIfTrue: name @include(if: true) nameIfFalse: name @include(if: false) } - ''') + """, + ) def test_different_skip_or_include_directives_accepted(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment differentDirectivesWithDifferentAliases on Dog { name @include(if: true) name @include(if: false) } - ''') + """, + ) def test_same_aliases_with_different_field_targets(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ fragment sameAliasesWithDifferentFieldTargets on Dog { fido: name fido: nickname } - ''', [ - fields_conflict('fido', 'name and nickname are different fields', L(3, 9), L(4, 9)) - ], sort_list=False) + """, + [ + fields_conflict( + "fido", "name and nickname are different fields", L(3, 9), L(4, 9) + ) + ], + sort_list=False, + ) def test_same_aliases_allowed_on_nonoverlapping_fields(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment sameAliasesWithDifferentFieldTargets on Pet { ... on Dog { name @@ -101,55 +142,86 @@ def test_same_aliases_allowed_on_nonoverlapping_fields(): name: nickname } } - ''') + """, + ) def test_alias_masking_direct_field_access(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ fragment aliasMaskingDirectFieldAccess on Dog { name: nickname name } - ''', [ - fields_conflict('name', 'nickname and name are different fields', L(3, 9), L(4, 9)) - ], sort_list=False) + """, + [ + fields_conflict( + "name", "nickname and name are different fields", L(3, 9), L(4, 9) + ) + ], + sort_list=False, + ) def test_diferent_args_second_adds_an_argument(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ fragment conflictingArgs on Dog { doesKnowCommand doesKnowCommand(dogCommand: HEEL) } - ''', [ - fields_conflict('doesKnowCommand', 'they have differing arguments', L(3, 9), L(4, 9)) - ], sort_list=False) + """, + [ + fields_conflict( + "doesKnowCommand", "they have differing arguments", L(3, 9), L(4, 9) + ) + ], + sort_list=False, + ) def test_diferent_args_second_missing_an_argument(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand } - ''', [ - fields_conflict('doesKnowCommand', 'they have differing arguments', L(3, 9), L(4, 9)) - ], sort_list=False) + """, + [ + fields_conflict( + "doesKnowCommand", "they have differing arguments", L(3, 9), L(4, 9) + ) + ], + sort_list=False, + ) def test_conflicting_args(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: HEEL) } - ''', [ - fields_conflict('doesKnowCommand', 'they have differing arguments', L(3, 9), L(4, 9)) - ], sort_list=False) + """, + [ + fields_conflict( + "doesKnowCommand", "they have differing arguments", L(3, 9), L(4, 9) + ) + ], + sort_list=False, + ) def test_allows_different_args_where_no_conflict_is_possible(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ fragment conflictingArgs on Pet { ... on Dog { name(surname: true) @@ -158,11 +230,14 @@ def test_allows_different_args_where_no_conflict_is_possible(): name } } - ''') + """, + ) def test_encounters_conflict_in_fragments(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { ...A ...B @@ -173,13 +248,16 @@ def test_encounters_conflict_in_fragments(): fragment B on Type { x: b } - ''', [ - fields_conflict('x', 'a and b are different fields', L(7, 9), L(10, 9)) - ], sort_list=False) + """, + [fields_conflict("x", "a and b are different fields", L(7, 9), L(10, 9))], + sort_list=False, + ) def test_reports_each_conflict_once(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { f1 { ...A @@ -201,15 +279,20 @@ def test_reports_each_conflict_once(): fragment B on Type { x: b } - ''', [ - fields_conflict('x', 'a and b are different fields', L(18, 9), L(21, 9)), - fields_conflict('x', 'c and a are different fields', L(14, 11), L(18, 9)), - fields_conflict('x', 'c and b are different fields', L(14, 11), L(21, 9)) - ], sort_list=False) + """, + [ + fields_conflict("x", "a and b are different fields", L(18, 9), L(21, 9)), + fields_conflict("x", "c and a are different fields", L(14, 11), L(18, 9)), + fields_conflict("x", "c and b are different fields", L(14, 11), L(21, 9)), + ], + sort_list=False, + ) def test_deep_conflict(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { x: a @@ -218,15 +301,25 @@ def test_deep_conflict(): x: b } } - ''', [ - fields_conflict( - 'field', [('x', 'a and b are different fields')], - L(3, 9), L(4, 13), L(6, 9), L(7, 13)) - ], sort_list=False) + """, + [ + fields_conflict( + "field", + [("x", "a and b are different fields")], + L(3, 9), + L(4, 13), + L(6, 9), + L(7, 13), + ) + ], + sort_list=False, + ) def test_deep_conflict_with_multiple_issues(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { x: a @@ -237,16 +330,30 @@ def test_deep_conflict_with_multiple_issues(): y: d } } - ''', [ - fields_conflict( - 'field', [('x', 'a and b are different fields'), ('y', 'c and d are different fields')], - L(3, 9), L(4, 11), L(5, 11), L(7, 9), L(8, 11), L(9, 11) - ) - ], sort_list=False) + """, + [ + fields_conflict( + "field", + [ + ("x", "a and b are different fields"), + ("y", "c and d are different fields"), + ], + L(3, 9), + L(4, 11), + L(5, 11), + L(7, 9), + L(8, 11), + L(9, 11), + ) + ], + sort_list=False, + ) def test_very_deep_conflict(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { deepField { @@ -259,16 +366,27 @@ def test_very_deep_conflict(): } } } - ''', [ - fields_conflict( - 'field', [['deepField', [['x', 'a and b are different fields']]]], - L(3, 9), L(4, 13), L(5, 17), L(8, 9), L(9, 13), L(10, 17) - ) - ], sort_list=False) + """, + [ + fields_conflict( + "field", + [["deepField", [["x", "a and b are different fields"]]]], + L(3, 9), + L(4, 13), + L(5, 17), + L(8, 9), + L(9, 13), + L(10, 17), + ) + ], + sort_list=False, + ) def test_reports_deep_conflict_to_nearest_common_ancestor(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { deepField { @@ -284,16 +402,25 @@ def test_reports_deep_conflict_to_nearest_common_ancestor(): } } } - ''', [ - fields_conflict( - 'deepField', [('x', 'a and b are different fields')], - L(4, 13), L(5, 17), L(7, 13), L(8, 17) - ) - ], sort_list=False) + """, + [ + fields_conflict( + "deepField", + [("x", "a and b are different fields")], + L(4, 13), + L(5, 17), + L(7, 13), + L(8, 17), + ) + ], + sort_list=False, + ) def test_reports_deep_conflict_to_nearest_common_ancestor_in_fragments(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { ...F @@ -317,16 +444,25 @@ def test_reports_deep_conflict_to_nearest_common_ancestor_in_fragments(): } } } - ''', [ - fields_conflict( - 'deeperField', [('x', 'a and b are different fields')], - L(12, 11), L(13, 13), L(15, 11), L(16, 13) - ) - ], sort_list=False) + """, + [ + fields_conflict( + "deeperField", + [("x", "a and b are different fields")], + L(12, 11), + L(13, 13), + L(15, 11), + L(16, 13), + ) + ], + sort_list=False, + ) def test_reports_deep_conflict_in_nested_fragments(): - expect_fails_rule(OverlappingFieldsCanBeMerged, ''' + expect_fails_rule( + OverlappingFieldsCanBeMerged, + """ { field { ...F @@ -349,17 +485,30 @@ def test_reports_deep_conflict_in_nested_fragments(): fragment J on T { x: b } - ''', [ - fields_conflict( - 'field', [('x', 'a and b are different fields'), - ('y', 'c and d are different fields')], - L(3, 9), L(11, 9), L(15, 9), L(6, 9), L(22, 9), L(18, 9) - ) - ], sort_list=False) + """, + [ + fields_conflict( + "field", + [ + ("x", "a and b are different fields"), + ("y", "c and d are different fields"), + ], + L(3, 9), + L(11, 9), + L(15, 9), + L(6, 9), + L(22, 9), + L(18, 9), + ) + ], + sort_list=False, + ) def test_ignores_unknown_fragments(): - expect_passes_rule(OverlappingFieldsCanBeMerged, ''' + expect_passes_rule( + OverlappingFieldsCanBeMerged, + """ { field ...Unknown @@ -370,84 +519,115 @@ def test_ignores_unknown_fragments(): field ...OtherUnknown } - ''') + """, + ) SomeBox = GraphQLInterfaceType( - 'SomeBox', + "SomeBox", fields=lambda: { - 'deepBox': GraphQLField(SomeBox), - 'unrelatedField': GraphQLField(GraphQLString) + "deepBox": GraphQLField(SomeBox), + "unrelatedField": GraphQLField(GraphQLString), }, - resolve_type=lambda *_: StringBox + resolve_type=lambda *_: StringBox, ) StringBox = GraphQLObjectType( - 'StringBox', + "StringBox", fields=lambda: { - 'scalar': GraphQLField(GraphQLString), - 'deepBox': GraphQLField(StringBox), - 'unrelatedField': GraphQLField(GraphQLString), - 'listStringBox': GraphQLField(GraphQLList(StringBox)), - 'stringBox': GraphQLField(StringBox), - 'intBox': GraphQLField(IntBox), + "scalar": GraphQLField(GraphQLString), + "deepBox": GraphQLField(StringBox), + "unrelatedField": GraphQLField(GraphQLString), + "listStringBox": GraphQLField(GraphQLList(StringBox)), + "stringBox": GraphQLField(StringBox), + "intBox": GraphQLField(IntBox), }, - interfaces=[SomeBox] + interfaces=[SomeBox], ) IntBox = GraphQLObjectType( - 'IntBox', + "IntBox", fields=lambda: { - 'scalar': GraphQLField(GraphQLInt), - 'deepBox': GraphQLField(IntBox), - 'unrelatedField': GraphQLField(GraphQLString), - 'listStringBox': GraphQLField(GraphQLList(StringBox)), - 'stringBox': GraphQLField(StringBox), - 'intBox': GraphQLField(IntBox), + "scalar": GraphQLField(GraphQLInt), + "deepBox": GraphQLField(IntBox), + "unrelatedField": GraphQLField(GraphQLString), + "listStringBox": GraphQLField(GraphQLList(StringBox)), + "stringBox": GraphQLField(StringBox), + "intBox": GraphQLField(IntBox), }, - interfaces=[SomeBox] + interfaces=[SomeBox], +) + +NonNullStringBox1 = GraphQLInterfaceType( + "NonNullStringBox1", + {"scalar": GraphQLField(GraphQLNonNull(GraphQLString))}, + resolve_type=lambda *_: StringBox, ) -NonNullStringBox1 = GraphQLInterfaceType('NonNullStringBox1', { - 'scalar': GraphQLField(GraphQLNonNull(GraphQLString)), -}, resolve_type=lambda *_: StringBox) - -NonNullStringBox1Impl = GraphQLObjectType('NonNullStringBox1Impl', { - 'scalar': GraphQLField(GraphQLNonNull(GraphQLString)), - 'deepBox': GraphQLField(StringBox), - 'unrelatedField': GraphQLField(GraphQLString) -}, interfaces=[SomeBox, NonNullStringBox1]) - -NonNullStringBox2 = GraphQLInterfaceType('NonNullStringBox2', { - 'scalar': GraphQLField(GraphQLNonNull(GraphQLString)) -}, resolve_type=lambda *_: StringBox) - -NonNullStringBox2Impl = GraphQLObjectType('NonNullStringBox2Impl', { - 'scalar': GraphQLField(GraphQLNonNull(GraphQLString)), - 'unrelatedField': GraphQLField(GraphQLString), - 'deepBox': GraphQLField(StringBox), -}, interfaces=[SomeBox, NonNullStringBox2]) - -Connection = GraphQLObjectType('Connection', { - 'edges': GraphQLField(GraphQLList(GraphQLObjectType('Edge', { - 'node': GraphQLField(GraphQLObjectType('Node', { - 'id': GraphQLField(GraphQLID), - 'name': GraphQLField(GraphQLString) - })) - }))) -}) +NonNullStringBox1Impl = GraphQLObjectType( + "NonNullStringBox1Impl", + { + "scalar": GraphQLField(GraphQLNonNull(GraphQLString)), + "deepBox": GraphQLField(StringBox), + "unrelatedField": GraphQLField(GraphQLString), + }, + interfaces=[SomeBox, NonNullStringBox1], +) + +NonNullStringBox2 = GraphQLInterfaceType( + "NonNullStringBox2", + {"scalar": GraphQLField(GraphQLNonNull(GraphQLString))}, + resolve_type=lambda *_: StringBox, +) + +NonNullStringBox2Impl = GraphQLObjectType( + "NonNullStringBox2Impl", + { + "scalar": GraphQLField(GraphQLNonNull(GraphQLString)), + "unrelatedField": GraphQLField(GraphQLString), + "deepBox": GraphQLField(StringBox), + }, + interfaces=[SomeBox, NonNullStringBox2], +) + +Connection = GraphQLObjectType( + "Connection", + { + "edges": GraphQLField( + GraphQLList( + GraphQLObjectType( + "Edge", + { + "node": GraphQLField( + GraphQLObjectType( + "Node", + { + "id": GraphQLField(GraphQLID), + "name": GraphQLField(GraphQLString), + }, + ) + ) + }, + ) + ) + ) + }, +) schema = GraphQLSchema( - GraphQLObjectType('QueryRoot', { - 'someBox': GraphQLField(SomeBox), - 'connection': GraphQLField(Connection), - }), - types=[IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl] + GraphQLObjectType( + "QueryRoot", + {"someBox": GraphQLField(SomeBox), "connection": GraphQLField(Connection)}, + ), + types=[IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl], ) def test_conflicting_return_types_which_potentially_overlap(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ...on IntBox { @@ -459,16 +639,27 @@ def test_conflicting_return_types_which_potentially_overlap(): } } - ''', [ - fields_conflict('scalar', 'they return conflicting types Int and String!', L(5, 17), L(8, 17)) - ], sort_list=False) + """, + [ + fields_conflict( + "scalar", + "they return conflicting types Int and String!", + L(5, 17), + L(8, 17), + ) + ], + sort_list=False, + ) def test_compatible_return_shapes_on_different_return_types(): # In this case `deepBox` returns `SomeBox` in the first usage, and # `StringBox` in the second usage. These return types are not the same! # however this is valid because the return *shapes* are compatible. - expect_passes_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_passes_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on SomeBox { @@ -483,11 +674,15 @@ def test_compatible_return_shapes_on_different_return_types(): } } } - ''') + """, + ) def test_disallows_differing_return_types_despite_no_overlap(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -498,16 +693,24 @@ def test_disallows_differing_return_types_despite_no_overlap(): } } } - ''', [ - fields_conflict( - 'scalar', 'they return conflicting types Int and String', - L(5, 15), L(8, 15), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "scalar", + "they return conflicting types Int and String", + L(5, 15), + L(8, 15), + ) + ], + sort_list=False, + ) def test_reports_correctly_when_a_non_exclusive_follows_an_exclusive(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -550,17 +753,26 @@ def test_reports_correctly_when_a_non_exclusive_follows_an_exclusive(): fragment Y on SomeBox { scalar: unrelatedField } - ''', [ - fields_conflict( - 'other', - [('scalar', 'scalar and unrelatedField are different fields')], - L(31, 11), L(39, 11), L(34, 11), L(42, 11), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "other", + [("scalar", "scalar and unrelatedField are different fields")], + L(31, 11), + L(39, 11), + L(34, 11), + L(42, 11), + ) + ], + sort_list=False, + ) def test_disallows_differing_return_type_nullability_despite_no_overlap(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on NonNullStringBox1 { @@ -571,17 +783,24 @@ def test_disallows_differing_return_type_nullability_despite_no_overlap(): } } } - ''', [ - fields_conflict( - 'scalar', - 'they return conflicting types String! and String', - L(5, 15), L(8, 15), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "scalar", + "they return conflicting types String! and String", + L(5, 15), + L(8, 15), + ) + ], + sort_list=False, + ) def test_disallows_differing_return_type_list_despite_no_overlap_1(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -596,18 +815,24 @@ def test_disallows_differing_return_type_list_despite_no_overlap_1(): } } } - ''', [ - fields_conflict( - 'box', - 'they return conflicting types [StringBox] and StringBox', - L(5, 15), - L(10, 15), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "box", + "they return conflicting types [StringBox] and StringBox", + L(5, 15), + L(10, 15), + ) + ], + sort_list=False, + ) def test_disallows_differing_return_type_list_despite_no_overlap_2(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -622,17 +847,24 @@ def test_disallows_differing_return_type_list_despite_no_overlap_2(): } } } - ''', [ - fields_conflict( - 'box', - 'they return conflicting types StringBox and [StringBox]', - L(5, 15), L(10, 15), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "box", + "they return conflicting types StringBox and [StringBox]", + L(5, 15), + L(10, 15), + ) + ], + sort_list=False, + ) def test_disallows_differing_subfields(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -648,17 +880,24 @@ def test_disallows_differing_subfields(): } } } - ''', [ - fields_conflict( - 'val', - 'scalar and unrelatedField are different fields', - L(6, 17), L(7, 17), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "val", + "scalar and unrelatedField are different fields", + L(6, 17), + L(7, 17), + ) + ], + sort_list=False, + ) def test_disallows_differing_deep_return_types_despite_no_overlap(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -673,20 +912,26 @@ def test_disallows_differing_deep_return_types_despite_no_overlap(): } } } - ''', [ - fields_conflict( - 'box', - [['scalar', 'they return conflicting types String and Int']], - L(5, 15), - L(6, 17), - L(10, 15), - L(11, 17), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "box", + [["scalar", "they return conflicting types String and Int"]], + L(5, 15), + L(6, 17), + L(10, 15), + L(11, 17), + ) + ], + sort_list=False, + ) def test_allows_non_conflicting_overlaping_types(): - expect_passes_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_passes_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ... on IntBox { @@ -697,11 +942,15 @@ def test_allows_non_conflicting_overlaping_types(): } } } - ''') + """, + ) def test_same_wrapped_scalar_return_types(): - expect_passes_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_passes_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { someBox { ...on NonNullStringBox1 { @@ -712,22 +961,30 @@ def test_same_wrapped_scalar_return_types(): } } } - ''') + """, + ) def test_allows_inline_typeless_fragments(): - expect_passes_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_passes_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { a ... { a } } - ''') + """, + ) def test_compares_deep_types_including_list(): - expect_fails_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_fails_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { connection { ...edgeID @@ -746,18 +1003,28 @@ def test_compares_deep_types_including_list(): } } } - ''', [ - fields_conflict( - 'edges', [['node', [['id', 'name and id are different fields']]]], - L(5, 13), L(6, 17), - L(7, 21), L(14, 9), - L(15, 13), L(16, 17), - ) - ], sort_list=False) + """, + [ + fields_conflict( + "edges", + [["node", [["id", "name and id are different fields"]]]], + L(5, 13), + L(6, 17), + L(7, 21), + L(14, 9), + L(15, 13), + L(16, 17), + ) + ], + sort_list=False, + ) def test_ignores_unknown_types(): - expect_passes_rule_with_schema(schema, OverlappingFieldsCanBeMerged, ''' + expect_passes_rule_with_schema( + schema, + OverlappingFieldsCanBeMerged, + """ { boxUnion { ...on UnknownType { @@ -768,14 +1035,17 @@ def test_ignores_unknown_types(): } } } - ''') + """, + ) def test_error_message_contains_hint_for_alias_conflict(): - error = OverlappingFieldsCanBeMerged.fields_conflict_message('x', 'a and b are different fields') + error = OverlappingFieldsCanBeMerged.fields_conflict_message( + "x", "a and b are different fields" + ) hint = ( 'Fields "x" conflict because a and b are different fields. ' - 'Use different aliases on the fields to fetch both ' - 'if this was intentional.' + "Use different aliases on the fields to fetch both " + "if this was intentional." ) assert error == hint diff --git a/graphql/validation/tests/test_possible_fragment_spreads.py b/graphql/validation/tests/test_possible_fragment_spreads.py index d236372e..2bac5b1d 100644 --- a/graphql/validation/tests/test_possible_fragment_spreads.py +++ b/graphql/validation/tests/test_possible_fragment_spreads.py @@ -6,169 +6,250 @@ def error(frag_name, parent_type, frag_type, line, column): return { - 'message': PossibleFragmentSpreads.type_incompatible_spread_message(frag_name, parent_type, frag_type), - 'locations': [SourceLocation(line, column)] + "message": PossibleFragmentSpreads.type_incompatible_spread_message( + frag_name, parent_type, frag_type + ), + "locations": [SourceLocation(line, column)], } def error_anon(parent_type, frag_type, line, column): return { - 'message': PossibleFragmentSpreads.type_incompatible_anon_spread_message(parent_type, frag_type), - 'locations': [SourceLocation(line, column)] + "message": PossibleFragmentSpreads.type_incompatible_anon_spread_message( + parent_type, frag_type + ), + "locations": [SourceLocation(line, column)], } def test_same_object(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment objectWithinObject on Dog { ...dogFragment } fragment dogFragment on Dog { barkVolume } - ''') + """, + ) def test_same_object_inline_frag(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } } - ''') + """, + ) def test_object_into_implemented_interface(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment objectWithinInterface on Pet { ...dogFragment } fragment dogFragment on Dog { barkVolume } - ''') + """, + ) def test_object_into_containing_union(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment dogFragment on Dog { barkVolume } - ''') + """, + ) def test_union_into_contained_object(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment unionWithinObject on Dog { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - ''') + """, + ) def test_union_into_overlapping_interface(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment unionWithinInterface on Pet { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - ''') + """, + ) def test_union_into_overlapping_union(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - ''') + """, + ) def test_interface_into_implemented_object(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment interfaceWithinObject on Dog { ...petFragment } fragment petFragment on Pet { name } - ''') + """, + ) def test_interface_into_overlapping_interface(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment interfaceWithinInterface on Pet { ...beingFragment } fragment beingFragment on Being { name } - ''') + """, + ) def test_interface_into_overlapping_interface_in_inline_fragment(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment interfaceWithinInterface on Pet { ... on Being { name } } - ''') + """, + ) def test_interface_into_overlapping_union(): - expect_passes_rule(PossibleFragmentSpreads, ''' + expect_passes_rule( + PossibleFragmentSpreads, + """ fragment interfaceWithinUnion on CatOrDog { ...petFragment } fragment petFragment on Pet { name } - ''') + """, + ) def test_different_object_into_object(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidObjectWithinObject on Cat { ...dogFragment } fragment dogFragment on Dog { barkVolume } - ''', [error('dogFragment', 'Cat', 'Dog', 2, 51)]) + """, + [error("dogFragment", "Cat", "Dog", 2, 51)], + ) def test_different_object_into_object_in_inline_fragment(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidObjectWithinObjectAnon on Cat { ... on Dog { barkVolume } } - ''', [error_anon('Cat', 'Dog', 3, 9)]) + """, + [error_anon("Cat", "Dog", 3, 9)], + ) def test_object_into_not_implementing_interface(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidObjectWithinInterface on Pet { ...humanFragment } fragment humanFragment on Human { pets { name } } - ''', [error('humanFragment', 'Pet', 'Human', 2, 54)]) + """, + [error("humanFragment", "Pet", "Human", 2, 54)], + ) def test_object_into_not_containing_union(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment } fragment humanFragment on Human { pets { name } } - ''', [error('humanFragment', 'CatOrDog', 'Human', 2, 55)]) + """, + [error("humanFragment", "CatOrDog", "Human", 2, 55)], + ) def test_union_into_not_contained_object(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidUnionWithinObject on Human { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - ''', [error('catOrDogFragment', 'Human', 'CatOrDog', 2, 52)]) + """, + [error("catOrDogFragment", "Human", "CatOrDog", 2, 52)], + ) def test_union_into_non_overlapping_interface(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } - ''', [error('humanOrAlienFragment', 'Pet', 'HumanOrAlien', 2, 53)]) + """, + [error("humanOrAlienFragment", "Pet", "HumanOrAlien", 2, 53)], + ) def test_union_into_non_overlapping_union(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } - ''', [error('humanOrAlienFragment', 'CatOrDog', 'HumanOrAlien', 2, 54)]) + """, + [error("humanOrAlienFragment", "CatOrDog", "HumanOrAlien", 2, 54)], + ) def test_interface_into_non_implementing_object(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } - ''', [error('intelligentFragment', 'Cat', 'Intelligent', 2, 54)]) + """, + [error("intelligentFragment", "Cat", "Intelligent", 2, 54)], + ) def test_interface_into_non_overlapping_interface(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidInterfaceWithinInterface on Pet { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } - ''', [error('intelligentFragment', 'Pet', 'Intelligent', 3, 9)]) + """, + [error("intelligentFragment", "Pet", "Intelligent", 3, 9)], + ) def test_interface_into_non_overlapping_interface_in_inline_fragment(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidInterfaceWithinInterfaceAnon on Pet { ...on Intelligent { iq } } - ''', [error_anon('Pet', 'Intelligent', 3, 9)]) + """, + [error_anon("Pet", "Intelligent", 3, 9)], + ) def test_interface_into_non_overlapping_union(): - expect_fails_rule(PossibleFragmentSpreads, ''' + expect_fails_rule( + PossibleFragmentSpreads, + """ fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment } fragment petFragment on Pet { name } - ''', [error('petFragment', 'HumanOrAlien', 'Pet', 2, 62)]) + """, + [error("petFragment", "HumanOrAlien", "Pet", 2, 62)], + ) diff --git a/graphql/validation/tests/test_provided_non_null_arguments.py b/graphql/validation/tests/test_provided_non_null_arguments.py index 35a8a502..2727207d 100644 --- a/graphql/validation/tests/test_provided_non_null_arguments.py +++ b/graphql/validation/tests/test_provided_non_null_arguments.py @@ -6,172 +6,222 @@ def missing_field_arg(field_name, arg_name, type_name, line, column): return { - 'message': ProvidedNonNullArguments.missing_field_arg_message(field_name, arg_name, type_name), - 'locations': [SourceLocation(line, column)] + "message": ProvidedNonNullArguments.missing_field_arg_message( + field_name, arg_name, type_name + ), + "locations": [SourceLocation(line, column)], } def missing_directive_arg(directive_name, arg_name, type_name, line, column): return { - 'message': ProvidedNonNullArguments.missing_directive_arg_message(directive_name, arg_name, type_name), - 'locations': [SourceLocation(line, column)] + "message": ProvidedNonNullArguments.missing_directive_arg_message( + directive_name, arg_name, type_name + ), + "locations": [SourceLocation(line, column)], } def test_ignores_unknown_arguments(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { dog { isHousetrained(unknownArgument: true) } - }''') + }""", + ) def test_arg_on_optional_arg(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { dog { isHousetrained(atOtherHomes: true) } - }''') + }""", + ) def test_no_arg_on_optional_arg(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { dog { isHousetrained } - }''') + }""", + ) def test_multiple_args(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } - ''') + """, + ) def test_multiple_args_reverse_order(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } - ''') + """, + ) def test_no_args_on_multiple_optional(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOpts } } - ''') + """, + ) def test_one_arg_on_multiple_optional(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOpts(opt1: 1) } } - ''') + """, + ) def test_second_arg_on_multiple_optional(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOpts(opt2: 1) } } - ''') + """, + ) def test_multiple_reqs_on_mixed_list(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4) } } - ''') + """, + ) def test_multiple_reqs_and_one_opt_on_mixed_list(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5) } } - ''') + """, + ) def test_all_reqs_and_opts_on_mixed_list(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) } } - ''') + """, + ) def test_missing_one_non_nullable_argument(): - expect_fails_rule(ProvidedNonNullArguments, ''' + expect_fails_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleReqs(req2: 2) } } - ''', [ - missing_field_arg('multipleReqs', 'req1', 'Int!', 4, 13) - ]) + """, + [missing_field_arg("multipleReqs", "req1", "Int!", 4, 13)], + ) def test_missing_multiple_non_nullable_arguments(): - expect_fails_rule(ProvidedNonNullArguments, ''' + expect_fails_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleReqs } } - ''', [ - missing_field_arg('multipleReqs', 'req1', 'Int!', 4, 13), - missing_field_arg('multipleReqs', 'req2', 'Int!', 4, 13) - ]) + """, + [ + missing_field_arg("multipleReqs", "req1", "Int!", 4, 13), + missing_field_arg("multipleReqs", "req2", "Int!", 4, 13), + ], + ) def test_incorrect_value_and_missing_argument(): - expect_fails_rule(ProvidedNonNullArguments, ''' + expect_fails_rule( + ProvidedNonNullArguments, + """ { complicatedArgs { multipleReqs(req1: "one") } } - ''', [ - missing_field_arg('multipleReqs', 'req2', 'Int!', 4, 13) - ]) + """, + [missing_field_arg("multipleReqs", "req2", "Int!", 4, 13)], + ) def test_ignore_unknown_directives(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { dog @unknown } - ''') + """, + ) def test_with_directives_of_valid_type(): - expect_passes_rule(ProvidedNonNullArguments, ''' + expect_passes_rule( + ProvidedNonNullArguments, + """ { dog @include(if: true) { name @@ -180,17 +230,22 @@ def test_with_directives_of_valid_type(): name } } - ''') + """, + ) def test_with_directive_with_missing_types(): - expect_fails_rule(ProvidedNonNullArguments, ''' + expect_fails_rule( + ProvidedNonNullArguments, + """ { dog @include { name @skip } } - ''', [ - missing_directive_arg('include', 'if', 'Boolean!', 3, 13), - missing_directive_arg('skip', 'if', 'Boolean!', 4, 18), - ]) + """, + [ + missing_directive_arg("include", "if", "Boolean!", 3, 13), + missing_directive_arg("skip", "if", "Boolean!", 4, 18), + ], + ) diff --git a/graphql/validation/tests/test_scalar_leafs.py b/graphql/validation/tests/test_scalar_leafs.py index af10abe8..f381c73f 100644 --- a/graphql/validation/tests/test_scalar_leafs.py +++ b/graphql/validation/tests/test_scalar_leafs.py @@ -6,99 +6,119 @@ def no_scalar_subselection(field, type, line, column): return { - 'message': ScalarLeafs.no_subselection_allowed_message(field, type), - 'locations': [SourceLocation(line, column)] + "message": ScalarLeafs.no_subselection_allowed_message(field, type), + "locations": [SourceLocation(line, column)], } def missing_obj_subselection(field, type, line, column): return { - 'message': ScalarLeafs.required_subselection_message(field, type), - 'locations': [SourceLocation(line, column)] + "message": ScalarLeafs.required_subselection_message(field, type), + "locations": [SourceLocation(line, column)], } def test_valid_scalar_selection(): - expect_passes_rule(ScalarLeafs, ''' + expect_passes_rule( + ScalarLeafs, + """ fragment scalarSelection on Dog { barks } - ''') + """, + ) def test_object_type_missing_selection(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ query directQueryOnObjectWithoutSubFields { human } - ''', [ - missing_obj_subselection('human', 'Human', 3, 9) - ]) + """, + [missing_obj_subselection("human", "Human", 3, 9)], + ) def test_interface_type_missing_selection(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ { human { pets } } - ''', [ - missing_obj_subselection('pets', '[Pet]', 3, 17) - ]) + """, + [missing_obj_subselection("pets", "[Pet]", 3, 17)], + ) def test_valid_scalar_selection_with_args(): - expect_passes_rule(ScalarLeafs, ''' + expect_passes_rule( + ScalarLeafs, + """ fragment scalarSelectionWithArgs on Dog { doesKnowCommand(dogCommand: SIT) } - ''') + """, + ) def test_scalar_selection_not_allowed_on_boolean(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ fragment scalarSelectionsNotAllowedOnBoolean on Dog { barks { sinceWhen } } - ''', [ - no_scalar_subselection('barks', 'Boolean', 3, 15) - ]) + """, + [no_scalar_subselection("barks", "Boolean", 3, 15)], + ) def test_scalar_selection_not_allowed_on_enum(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ fragment scalarSelectionsNotAllowedOnEnum on Cat { furColor { inHexdec } } - ''', [ - no_scalar_subselection('furColor', 'FurColor', 3, 18) - ]) + """, + [no_scalar_subselection("furColor", "FurColor", 3, 18)], + ) def test_scalar_selection_not_allowed_with_args(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ fragment scalarSelectionsNotAllowedWithArgs on Dog { doesKnowCommand(dogCommand: SIT) { sinceWhen } } - ''', [ - no_scalar_subselection('doesKnowCommand', 'Boolean', 3, 42) - ]) + """, + [no_scalar_subselection("doesKnowCommand", "Boolean", 3, 42)], + ) def test_scalar_selection_not_allowed_with_directives(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ fragment scalarSelectionsNotAllowedWithDirectives on Dog { name @include(if: true) { isAlsoHumanName } } - ''', [ - no_scalar_subselection('name', 'String', 3, 33) - ]) + """, + [no_scalar_subselection("name", "String", 3, 33)], + ) def test_scalar_selection_not_allowed_with_directives_and_args(): - expect_fails_rule(ScalarLeafs, ''' + expect_fails_rule( + ScalarLeafs, + """ fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog { doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen } } - ''', [ - no_scalar_subselection('doesKnowCommand', 'Boolean', 3, 61) - ]) + """, + [no_scalar_subselection("doesKnowCommand", "Boolean", 3, 61)], + ) diff --git a/graphql/validation/tests/test_unique_argument_names.py b/graphql/validation/tests/test_unique_argument_names.py index fb38a99f..57b18153 100644 --- a/graphql/validation/tests/test_unique_argument_names.py +++ b/graphql/validation/tests/test_unique_argument_names.py @@ -6,122 +6,154 @@ def duplicate_arg(arg_name, l1, c1, l2, c2): return { - 'message': UniqueArgumentNames.duplicate_arg_message(arg_name), - 'locations': [SourceLocation(l1, c1), SourceLocation(l2, c2)] + "message": UniqueArgumentNames.duplicate_arg_message(arg_name), + "locations": [SourceLocation(l1, c1), SourceLocation(l2, c2)], } def test_no_arguments_on_field(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field } - ''') + """, + ) def test_no_arguments_on_directive(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field } - ''') + """, + ) def test_argument_on_field(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field(arg: "value") } - ''') + """, + ) def test_argument_on_directive(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field @directive(arg: "value") } - ''') + """, + ) def test_same_field_two_arguments(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { one: field(arg: "value") two: field(arg: "value") } - ''') + """, + ) def test_same_argument_on_field_and_directive(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field(arg: "value") @directive(arg: "value") } - ''') + """, + ) def test_same_argument_two_directives(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field @directive1(arg: "value") @directive2(arg: "value") } - ''') + """, + ) def test_multiple_field_arguments(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field(arg1: "value", arg2: "value", arg3: "value") } - ''') + """, + ) def test_multiple_directive_arguments(): - expect_passes_rule(UniqueArgumentNames, ''' + expect_passes_rule( + UniqueArgumentNames, + """ { field @directive(arg1: "value", arg2: "value", arg3: "value") } - ''') + """, + ) def test_duplicate_field_arguments(): - expect_fails_rule(UniqueArgumentNames, ''' + expect_fails_rule( + UniqueArgumentNames, + """ { field(arg1: "value", arg1: "value") } - ''', [ - duplicate_arg('arg1', 3, 13, 3, 28) - ]) + """, + [duplicate_arg("arg1", 3, 13, 3, 28)], + ) def test_many_duplicate_field_arguments(): - expect_fails_rule(UniqueArgumentNames, ''' + expect_fails_rule( + UniqueArgumentNames, + """ { field(arg1: "value", arg1: "value", arg1: "value") } - ''', [ - duplicate_arg('arg1', 3, 13, 3, 28), - duplicate_arg('arg1', 3, 13, 3, 43) - ]) + """, + [duplicate_arg("arg1", 3, 13, 3, 28), duplicate_arg("arg1", 3, 13, 3, 43)], + ) def test_duplicate_directive_arguments(): - expect_fails_rule(UniqueArgumentNames, ''' + expect_fails_rule( + UniqueArgumentNames, + """ { field @directive(arg1: "value", arg1: "value") } - ''', [ - duplicate_arg('arg1', 3, 24, 3, 39) - ] + """, + [duplicate_arg("arg1", 3, 24, 3, 39)], ) def test_many_duplicate_directive_arguments(): - expect_fails_rule(UniqueArgumentNames, ''' + expect_fails_rule( + UniqueArgumentNames, + """ { field @directive(arg1: "value", arg1: "value", arg1: "value") } - ''', [ - duplicate_arg('arg1', 3, 24, 3, 39), - duplicate_arg('arg1', 3, 24, 3, 54) - ]) + """, + [duplicate_arg("arg1", 3, 24, 3, 39), duplicate_arg("arg1", 3, 24, 3, 54)], + ) diff --git a/graphql/validation/tests/test_unique_fragment_names.py b/graphql/validation/tests/test_unique_fragment_names.py index c7c9e63f..04cfdbbd 100644 --- a/graphql/validation/tests/test_unique_fragment_names.py +++ b/graphql/validation/tests/test_unique_fragment_names.py @@ -6,32 +6,40 @@ def duplicate_fragment(fragment_name, l1, c1, l2, c2): return { - 'message': UniqueFragmentNames.duplicate_fragment_name_message(fragment_name), - 'locations': [SourceLocation(l1, c1), SourceLocation(l2, c2)] + "message": UniqueFragmentNames.duplicate_fragment_name_message(fragment_name), + "locations": [SourceLocation(l1, c1), SourceLocation(l2, c2)], } def test_no_fragments(): - expect_passes_rule(UniqueFragmentNames, ''' + expect_passes_rule( + UniqueFragmentNames, + """ { field } - ''') + """, + ) def test_one_fragment(): - expect_passes_rule(UniqueFragmentNames, ''' + expect_passes_rule( + UniqueFragmentNames, + """ { ...fragA } fragment fragA on Type { field } - ''') + """, + ) def test_many_fragments(): - expect_passes_rule(UniqueFragmentNames, ''' + expect_passes_rule( + UniqueFragmentNames, + """ { ...fragA ...fragB @@ -46,11 +54,14 @@ def test_many_fragments(): fragment fragC on Type { fieldC } - ''') + """, + ) def test_inline_fragments(): - expect_passes_rule(UniqueFragmentNames, ''' + expect_passes_rule( + UniqueFragmentNames, + """ { ...on Type { fieldA @@ -59,22 +70,28 @@ def test_inline_fragments(): fieldB } } - ''') + """, + ) def test_fragment_operation_same_name(): - expect_passes_rule(UniqueFragmentNames, ''' + expect_passes_rule( + UniqueFragmentNames, + """ query Foo { ...Foo } fragment Foo on Type { field } - ''') + """, + ) def test_fragments_same_name(): - expect_fails_rule(UniqueFragmentNames, ''' + expect_fails_rule( + UniqueFragmentNames, + """ { ...fragA } @@ -84,19 +101,21 @@ def test_fragments_same_name(): fragment fragA on Type { fieldB } - ''', [ - duplicate_fragment('fragA', 5, 18, 8, 18) - ]) + """, + [duplicate_fragment("fragA", 5, 18, 8, 18)], + ) def test_fragments_same_name_no_ref(): - expect_fails_rule(UniqueFragmentNames, ''' + expect_fails_rule( + UniqueFragmentNames, + """ fragment fragA on Type { fieldA } fragment fragA on Type { fieldB } - ''', [ - duplicate_fragment('fragA', 2, 18, 5, 18) - ]) + """, + [duplicate_fragment("fragA", 2, 18, 5, 18)], + ) diff --git a/graphql/validation/tests/test_unique_input_field_names.py b/graphql/validation/tests/test_unique_input_field_names.py index f7af59ee..6587ed09 100644 --- a/graphql/validation/tests/test_unique_input_field_names.py +++ b/graphql/validation/tests/test_unique_input_field_names.py @@ -6,37 +6,48 @@ def duplicate_field(name, l1, l2): return { - 'message': UniqueInputFieldNames.duplicate_input_field_message(name), - 'locations': [l1, l2] + "message": UniqueInputFieldNames.duplicate_input_field_message(name), + "locations": [l1, l2], } def test_input_object_with_fields(): - expect_passes_rule(UniqueInputFieldNames, ''' + expect_passes_rule( + UniqueInputFieldNames, + """ { field(arg: { f: true }) } - ''') + """, + ) def test_same_input_object_within_two_args(): - expect_passes_rule(UniqueInputFieldNames, ''' + expect_passes_rule( + UniqueInputFieldNames, + """ { field(arg1: { f: true }, arg2: { f: true }) } - ''') + """, + ) def test_multiple_input_object_fields(): - expect_passes_rule(UniqueInputFieldNames, ''' + expect_passes_rule( + UniqueInputFieldNames, + """ { field(arg: { f1: "value", f2: "value", f3: "value" }) } - ''') + """, + ) def test_it_allows_for_nested_input_objects_with_similar_fields(): - expect_passes_rule(UniqueInputFieldNames, ''' + expect_passes_rule( + UniqueInputFieldNames, + """ { field(arg: { deep: { @@ -48,25 +59,32 @@ def test_it_allows_for_nested_input_objects_with_similar_fields(): id: 1 }) } - ''') + """, + ) def test_duplicate_input_object_fields(): - expect_fails_rule(UniqueInputFieldNames, ''' + expect_fails_rule( + UniqueInputFieldNames, + """ { field(arg: { f1: "value", f1: "value" }) } - ''', [ - duplicate_field("f1", L(3, 22), L(3, 35)) - ]) + """, + [duplicate_field("f1", L(3, 22), L(3, 35))], + ) def test_many_duplicate_input_object_fields(): - expect_fails_rule(UniqueInputFieldNames, ''' + expect_fails_rule( + UniqueInputFieldNames, + """ { field(arg: { f1: "value", f1: "value", f1: "value" }) } - ''', [ - duplicate_field('f1', L(3, 22), L(3, 35)), - duplicate_field('f1', L(3, 22), L(3, 48)) - ]) + """, + [ + duplicate_field("f1", L(3, 22), L(3, 35)), + duplicate_field("f1", L(3, 22), L(3, 48)), + ], + ) diff --git a/graphql/validation/tests/test_unique_operation_names.py b/graphql/validation/tests/test_unique_operation_names.py index e222c7c9..9eac02b3 100644 --- a/graphql/validation/tests/test_unique_operation_names.py +++ b/graphql/validation/tests/test_unique_operation_names.py @@ -6,37 +6,48 @@ def duplicate_op(op_name, l1, c1, l2, c2): return { - 'message': UniqueOperationNames.duplicate_operation_name_message(op_name), - 'locations': [SourceLocation(l1, c1), SourceLocation(l2, c2)] + "message": UniqueOperationNames.duplicate_operation_name_message(op_name), + "locations": [SourceLocation(l1, c1), SourceLocation(l2, c2)], } def test_no_operations(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ fragment fragA on Type { field } - ''') + """, + ) def test_one_anon_operation(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ { field } - ''') + """, + ) def test_one_named_operation(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ query Foo { field } - ''') + """, + ) def test_multiple_operations(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ query Foo { field } @@ -44,11 +55,14 @@ def test_multiple_operations(): query Bar { field } - ''') + """, + ) def test_multiple_operations_of_different_types(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ query Foo { field } @@ -60,54 +74,64 @@ def test_multiple_operations_of_different_types(): subscription Baz { field } - ''') + """, + ) def test_fragment_and_operation_named_the_same(): - expect_passes_rule(UniqueOperationNames, ''' + expect_passes_rule( + UniqueOperationNames, + """ query Foo { ...Foo } fragment Foo on Type { field } - ''') + """, + ) def test_multiple_operations_of_same_name(): - expect_fails_rule(UniqueOperationNames, ''' + expect_fails_rule( + UniqueOperationNames, + """ query Foo { fieldA } query Foo { fieldB } - ''', [ - duplicate_op('Foo', 2, 13, 5, 13), - ]) + """, + [duplicate_op("Foo", 2, 13, 5, 13)], + ) def test_multiple_ops_of_same_name_of_different_types_mutation(): - expect_fails_rule(UniqueOperationNames, ''' + expect_fails_rule( + UniqueOperationNames, + """ query Foo { fieldA } mutation Foo { fieldB } - ''', [ - duplicate_op('Foo', 2, 13, 5, 16), - ]) + """, + [duplicate_op("Foo", 2, 13, 5, 16)], + ) def test_multiple_ops_of_same_name_of_different_types_subscription(): - expect_fails_rule(UniqueOperationNames, ''' + expect_fails_rule( + UniqueOperationNames, + """ query Foo { fieldA } subscription Foo { fieldB } - ''', [ - duplicate_op('Foo', 2, 13, 5, 20), - ]) + """, + [duplicate_op("Foo", 2, 13, 5, 20)], + ) diff --git a/graphql/validation/tests/test_unique_variable_names.py b/graphql/validation/tests/test_unique_variable_names.py index b0276079..c8e14afe 100644 --- a/graphql/validation/tests/test_unique_variable_names.py +++ b/graphql/validation/tests/test_unique_variable_names.py @@ -6,26 +6,33 @@ def duplicate_var(op_name, l1, c1, l2, c2): return { - 'message': UniqueVariableNames.duplicate_variable_message(op_name), - 'locations': [SourceLocation(l1, c1), SourceLocation(l2, c2)] + "message": UniqueVariableNames.duplicate_variable_message(op_name), + "locations": [SourceLocation(l1, c1), SourceLocation(l2, c2)], } def test_unique_variable_names(): - expect_passes_rule(UniqueVariableNames, ''' + expect_passes_rule( + UniqueVariableNames, + """ query A($x: Int, $y: String) { __typename } query B($x: String, $y: Int) { __typename } - ''') + """, + ) def test_duplicate_variable_names(): - expect_fails_rule(UniqueVariableNames, ''' + expect_fails_rule( + UniqueVariableNames, + """ query A($x: Int, $x: Int, $x: String) { __typename } query B($x: String, $x: Int) { __typename } query C($x: Int, $x: Int) { __typename } - ''', [ - duplicate_var('x', 2, 16, 2, 25), - duplicate_var('x', 2, 16, 2, 34), - duplicate_var('x', 3, 16, 3, 28), - duplicate_var('x', 4, 16, 4, 25), - ]) + """, + [ + duplicate_var("x", 2, 16, 2, 25), + duplicate_var("x", 2, 16, 2, 34), + duplicate_var("x", 3, 16, 3, 28), + duplicate_var("x", 4, 16, 4, 25), + ], + ) diff --git a/graphql/validation/tests/test_validation.py b/graphql/validation/tests/test_validation.py index a637d69a..22f9607c 100644 --- a/graphql/validation/tests/test_validation.py +++ b/graphql/validation/tests/test_validation.py @@ -12,7 +12,9 @@ def expect_valid(schema, query_string): def test_it_validates_queries(): - expect_valid(test_schema, ''' + expect_valid( + test_schema, + """ query { catOrDog { ... on Cat { @@ -23,13 +25,15 @@ def test_it_validates_queries(): } } } - ''') + """, + ) def test_validates_using_a_custom_type_info(): type_info = TypeInfo(test_schema, lambda *_: None) - ast = parse(''' + ast = parse( + """ query { catOrDog { ... on Cat { @@ -40,16 +44,21 @@ def test_validates_using_a_custom_type_info(): } } } - ''') - - errors = visit_using_rules( - test_schema, - type_info, - ast, - specified_rules + """ ) + errors = visit_using_rules(test_schema, type_info, ast, specified_rules) + assert len(errors) == 3 - assert errors[0].message == 'Cannot query field "catOrDog" on type "QueryRoot". Did you mean "catOrDog"?' - assert errors[1].message == 'Cannot query field "furColor" on type "Cat". Did you mean "furColor"?' - assert errors[2].message == 'Cannot query field "isHousetrained" on type "Dog". Did you mean "isHousetrained"?' + assert ( + errors[0].message + == 'Cannot query field "catOrDog" on type "QueryRoot". Did you mean "catOrDog"?' + ) + assert ( + errors[1].message + == 'Cannot query field "furColor" on type "Cat". Did you mean "furColor"?' + ) + assert ( + errors[2].message + == 'Cannot query field "isHousetrained" on type "Dog". Did you mean "isHousetrained"?' + ) diff --git a/graphql/validation/tests/test_variables_are_input_types.py b/graphql/validation/tests/test_variables_are_input_types.py index 2810fed9..a9daea35 100644 --- a/graphql/validation/tests/test_variables_are_input_types.py +++ b/graphql/validation/tests/test_variables_are_input_types.py @@ -6,26 +6,35 @@ def non_input_type_on_variable(variable_name, type_name, line, col): return { - 'message': VariablesAreInputTypes.non_input_type_on_variable_message(variable_name, type_name), - 'locations': [SourceLocation(line, col)] + "message": VariablesAreInputTypes.non_input_type_on_variable_message( + variable_name, type_name + ), + "locations": [SourceLocation(line, col)], } def test_input_types_are_valid(): - expect_passes_rule(VariablesAreInputTypes, ''' + expect_passes_rule( + VariablesAreInputTypes, + """ query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { field(a: $a, b: $b, c: $c) } - ''') + """, + ) def test_output_types_are_invalid(): - expect_fails_rule(VariablesAreInputTypes, ''' + expect_fails_rule( + VariablesAreInputTypes, + """ query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) { field(a: $a, b: $b, c: $c) } - ''', [ - non_input_type_on_variable('a', 'Dog', 2, 21), - non_input_type_on_variable('b', '[[CatOrDog!]]!', 2, 30), - non_input_type_on_variable('c', 'Pet', 2, 50), - ]) + """, + [ + non_input_type_on_variable("a", "Dog", 2, 21), + non_input_type_on_variable("b", "[[CatOrDog!]]!", 2, 30), + non_input_type_on_variable("c", "Pet", 2, 50), + ], + ) diff --git a/graphql/validation/tests/test_variables_in_allowed_position.py b/graphql/validation/tests/test_variables_in_allowed_position.py index 716938d7..ffcb0ffb 100644 --- a/graphql/validation/tests/test_variables_in_allowed_position.py +++ b/graphql/validation/tests/test_variables_in_allowed_position.py @@ -5,18 +5,23 @@ def test_boolean_boolean(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($booleanArg: Boolean) { complicatedArgs { booleanArgField(booleanArg: $booleanArg) } } - ''') + """, + ) def test_boolean_boolean_in_fragment(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } @@ -27,9 +32,12 @@ def test_boolean_boolean_in_fragment(): ...booleanArgFrag } } - ''') + """, + ) - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($booleanArg: Boolean) { complicatedArgs { @@ -39,22 +47,28 @@ def test_boolean_boolean_in_fragment(): fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } - ''') + """, + ) def test_non_null_boolean_boolean(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($nonNullBooleanArg: Boolean!) { complicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } } - ''') + """, + ) def test_non_null_boolean_to_boolean_within_fragment(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } @@ -64,119 +78,157 @@ def test_non_null_boolean_to_boolean_within_fragment(): ...booleanArgFrag } } - ''') + """, + ) def test_int_non_null_int_with_default(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($intArg: Int = 1) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } } - ''') + """, + ) def test_string_string(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($stringListVar: [String]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } - ''') + """, + ) def test_non_null_string_string(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($stringListVar: [String!]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } - ''') + """, + ) def test_string_string_item_position(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } - ''') + """, + ) def test_non_null_string_string_item_positiion(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($stringVar: String!) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } - ''') + """, + ) def test_complex_input_complex_input(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($complexVar: ComplexInput) { complicatedArgs { complexArgField(complexArg: $complexVar) } } - ''') + """, + ) def test_complex_input_complex_input_in_field_position(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($boolVar: Boolean = false) { complicatedArgs { complexArgField(complexArg: {requiredArg: $boolVar}) } } - ''') + """, + ) def test_boolean_non_null_boolean_in_directive(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($boolVar: Boolean!) { dog @include(if: $boolVar) } - ''') + """, + ) def test_boolean_non_null_boolean_in_directive_with_default(): - expect_passes_rule(VariablesInAllowedPosition, ''' + expect_passes_rule( + VariablesInAllowedPosition, + """ query Query($boolVar: Boolean = false) { dog @include(if: $boolVar) } - ''') + """, + ) def test_int_non_null_int(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ query Query($intArg: Int) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('intArg', 'Int', 'Int!'), - 'locations': [SourceLocation(4, 45), SourceLocation(2, 19)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "intArg", "Int", "Int!" + ), + "locations": [SourceLocation(4, 45), SourceLocation(2, 19)], + } + ], + ) def test_int_non_null_int_within_fragment(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ fragment nonNullIntArgFieldFrag on ComplicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } @@ -185,14 +237,22 @@ def test_int_non_null_int_within_fragment(): ...nonNullIntArgFieldFrag } } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('intArg', 'Int', 'Int!'), - 'locations': [SourceLocation(5, 19), SourceLocation(3, 43)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "intArg", "Int", "Int!" + ), + "locations": [SourceLocation(5, 19), SourceLocation(3, 43)], + } + ], + ) def test_int_non_null_int_within_nested_fragment(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ fragment outerFrag on ComplicatedArgs { ...nonNullIntArgFieldFrag } @@ -204,55 +264,93 @@ def test_int_non_null_int_within_nested_fragment(): ...outerFrag } } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('intArg', 'Int', 'Int!'), - 'locations': [SourceLocation(8, 19), SourceLocation(6, 43)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "intArg", "Int", "Int!" + ), + "locations": [SourceLocation(8, 19), SourceLocation(6, 43)], + } + ], + ) def test_string_over_boolean(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ query Query($stringVar: String) { complicatedArgs { booleanArgField(booleanArg: $stringVar) } } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('stringVar', 'String', 'Boolean'), - 'locations': [SourceLocation(2, 19), SourceLocation(4, 39)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "stringVar", "String", "Boolean" + ), + "locations": [SourceLocation(2, 19), SourceLocation(4, 39)], + } + ], + ) def test_string_string_fail(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: $stringVar) } } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('stringVar', 'String', '[String]'), - 'locations': [SourceLocation(2, 19), SourceLocation(4, 45)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "stringVar", "String", "[String]" + ), + "locations": [SourceLocation(2, 19), SourceLocation(4, 45)], + } + ], + ) def test_boolean_non_null_boolean_in_directive(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ query Query($boolVar: Boolean) { dog @include(if: $boolVar) } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('boolVar', 'Boolean', 'Boolean!'), - 'locations': [SourceLocation(2, 19), SourceLocation(3, 26)] - }]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "boolVar", "Boolean", "Boolean!" + ), + "locations": [SourceLocation(2, 19), SourceLocation(3, 26)], + } + ], + ) def test_string_non_null_boolean_in_directive(): - expect_fails_rule(VariablesInAllowedPosition, ''' + expect_fails_rule( + VariablesInAllowedPosition, + """ query Query($stringVar: String) { dog @include(if: $stringVar) } - ''', [ - {'message': VariablesInAllowedPosition.bad_var_pos_message('stringVar', 'String', 'Boolean!'), - 'locations': [SourceLocation(2, 19), SourceLocation(3, 26)]} - ]) + """, + [ + { + "message": VariablesInAllowedPosition.bad_var_pos_message( + "stringVar", "String", "Boolean!" + ), + "locations": [SourceLocation(2, 19), SourceLocation(3, 26)], + } + ], + ) diff --git a/graphql/validation/tests/utils.py b/graphql/validation/tests/utils.py index 0044e012..7bec2763 100644 --- a/graphql/validation/tests/utils.py +++ b/graphql/validation/tests/utils.py @@ -1,212 +1,270 @@ from graphql.error import format_error from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLBoolean, GraphQLEnumType, - GraphQLEnumValue, GraphQLField, GraphQLFloat, - GraphQLID, GraphQLInputObjectField, - GraphQLInputObjectType, GraphQLInt, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLSchema, GraphQLString, - GraphQLUnionType) -from graphql.type.directives import (DirectiveLocation, GraphQLDirective, - GraphQLIncludeDirective, - GraphQLSkipDirective) +from graphql.type import ( + GraphQLArgument, + GraphQLBoolean, + GraphQLEnumType, + GraphQLEnumValue, + GraphQLField, + GraphQLFloat, + GraphQLID, + GraphQLInputObjectField, + GraphQLInputObjectType, + GraphQLInt, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLUnionType, +) +from graphql.type.directives import ( + DirectiveLocation, + GraphQLDirective, + GraphQLIncludeDirective, + GraphQLSkipDirective, +) from graphql.validation import validate -Being = GraphQLInterfaceType('Being', { - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }) -}) - -Pet = GraphQLInterfaceType('Pet', { - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), -}) - -Canine = GraphQLInterfaceType('Canine', { - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), -}) - -DogCommand = GraphQLEnumType('DogCommand', { - 'SIT': GraphQLEnumValue(0), - 'HEEL': GraphQLEnumValue(1), - 'DOWN': GraphQLEnumValue(2), -}) - -Dog = GraphQLObjectType('Dog', { - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), - 'nickname': GraphQLField(GraphQLString), - 'barkVolume': GraphQLField(GraphQLInt), - 'barks': GraphQLField(GraphQLBoolean), - 'doesKnowCommand': GraphQLField(GraphQLBoolean, { - 'dogCommand': GraphQLArgument(DogCommand) - }), - 'isHousetrained': GraphQLField( - GraphQLBoolean, - args={ - 'atOtherHomes': GraphQLArgument(GraphQLBoolean, default_value=True) - } - ), - 'isAtLocation': GraphQLField( - GraphQLBoolean, - args={ - 'x': GraphQLArgument(GraphQLInt), - 'y': GraphQLArgument(GraphQLInt) - } - ) -}, interfaces=[Being, Pet, Canine], is_type_of=lambda: None) - -Cat = GraphQLObjectType('Cat', lambda: { - 'furColor': GraphQLField(FurColor), - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), - 'nickname': GraphQLField(GraphQLString), -}, interfaces=[Being, Pet], is_type_of=lambda: None) - -CatOrDog = GraphQLUnionType('CatOrDog', [Dog, Cat]) - -Intelligent = GraphQLInterfaceType('Intelligent', { - 'iq': GraphQLField(GraphQLInt), -}) +Being = GraphQLInterfaceType( + "Being", + {"name": GraphQLField(GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)})}, +) + +Pet = GraphQLInterfaceType( + "Pet", + {"name": GraphQLField(GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)})}, +) + +Canine = GraphQLInterfaceType( + "Canine", + {"name": GraphQLField(GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)})}, +) + +DogCommand = GraphQLEnumType( + "DogCommand", + { + "SIT": GraphQLEnumValue(0), + "HEEL": GraphQLEnumValue(1), + "DOWN": GraphQLEnumValue(2), + }, +) + +Dog = GraphQLObjectType( + "Dog", + { + "name": GraphQLField( + GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)} + ), + "nickname": GraphQLField(GraphQLString), + "barkVolume": GraphQLField(GraphQLInt), + "barks": GraphQLField(GraphQLBoolean), + "doesKnowCommand": GraphQLField( + GraphQLBoolean, {"dogCommand": GraphQLArgument(DogCommand)} + ), + "isHousetrained": GraphQLField( + GraphQLBoolean, + args={"atOtherHomes": GraphQLArgument(GraphQLBoolean, default_value=True)}, + ), + "isAtLocation": GraphQLField( + GraphQLBoolean, + args={"x": GraphQLArgument(GraphQLInt), "y": GraphQLArgument(GraphQLInt)}, + ), + }, + interfaces=[Being, Pet, Canine], + is_type_of=lambda: None, +) + +Cat = GraphQLObjectType( + "Cat", + lambda: { + "furColor": GraphQLField(FurColor), + "name": GraphQLField( + GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)} + ), + "nickname": GraphQLField(GraphQLString), + }, + interfaces=[Being, Pet], + is_type_of=lambda: None, +) + +CatOrDog = GraphQLUnionType("CatOrDog", [Dog, Cat]) + +Intelligent = GraphQLInterfaceType("Intelligent", {"iq": GraphQLField(GraphQLInt)}) Human = GraphQLObjectType( - name='Human', + name="Human", interfaces=[Being, Intelligent], is_type_of=lambda: None, fields={ - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), - 'pets': GraphQLField(GraphQLList(Pet)), - 'iq': GraphQLField(GraphQLInt), + "name": GraphQLField( + GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)} + ), + "pets": GraphQLField(GraphQLList(Pet)), + "iq": GraphQLField(GraphQLInt), }, ) Alien = GraphQLObjectType( - name='Alien', + name="Alien", is_type_of=lambda *args: True, interfaces=[Being, Intelligent], fields={ - 'iq': GraphQLField(GraphQLInt), - 'name': GraphQLField(GraphQLString, { - 'surname': GraphQLArgument(GraphQLBoolean), - }), - 'numEyes': GraphQLField(GraphQLInt), + "iq": GraphQLField(GraphQLInt), + "name": GraphQLField( + GraphQLString, {"surname": GraphQLArgument(GraphQLBoolean)} + ), + "numEyes": GraphQLField(GraphQLInt), + }, +) + +DogOrHuman = GraphQLUnionType("DogOrHuman", [Dog, Human]) + +HumanOrAlien = GraphQLUnionType("HumanOrAlien", [Human, Alien]) + +FurColor = GraphQLEnumType( + "FurColor", + { + "BROWN": GraphQLEnumValue(0), + "BLACK": GraphQLEnumValue(1), + "TAN": GraphQLEnumValue(2), + "SPOTTED": GraphQLEnumValue(3), }, ) -DogOrHuman = GraphQLUnionType('DogOrHuman', [Dog, Human]) - -HumanOrAlien = GraphQLUnionType('HumanOrAlien', [Human, Alien]) - -FurColor = GraphQLEnumType('FurColor', { - 'BROWN': GraphQLEnumValue(0), - 'BLACK': GraphQLEnumValue(1), - 'TAN': GraphQLEnumValue(2), - 'SPOTTED': GraphQLEnumValue(3), -}) - -ComplexInput = GraphQLInputObjectType('ComplexInput', { - 'requiredField': GraphQLInputObjectField(GraphQLNonNull(GraphQLBoolean)), - 'intField': GraphQLInputObjectField(GraphQLInt), - 'stringField': GraphQLInputObjectField(GraphQLString), - 'booleanField': GraphQLInputObjectField(GraphQLBoolean), - 'stringListField': GraphQLInputObjectField(GraphQLList(GraphQLString)), -}) - -ComplicatedArgs = GraphQLObjectType('ComplicatedArgs', { - 'intArgField': GraphQLField(GraphQLString, { - 'intArg': GraphQLArgument(GraphQLInt) - }), - 'nonNullIntArgField': GraphQLField(GraphQLString, { - 'nonNullIntArg': GraphQLArgument(GraphQLNonNull(GraphQLInt)) - }), - 'stringArgField': GraphQLField(GraphQLString, { - 'stringArg': GraphQLArgument(GraphQLString) - }), - 'booleanArgField': GraphQLField(GraphQLString, { - 'booleanArg': GraphQLArgument(GraphQLBoolean) - }), - 'enumArgField': GraphQLField(GraphQLString, { - 'enumArg': GraphQLArgument(FurColor) - }), - 'floatArgField': GraphQLField(GraphQLString, { - 'floatArg': GraphQLArgument(GraphQLFloat) - }), - 'idArgField': GraphQLField(GraphQLString, { - 'idArg': GraphQLArgument(GraphQLID) - }), - 'stringListArgField': GraphQLField(GraphQLString, { - 'stringListArg': GraphQLArgument(GraphQLList(GraphQLString)) - }), - 'complexArgField': GraphQLField(GraphQLString, { - 'complexArg': GraphQLArgument(ComplexInput) - }), - 'multipleReqs': GraphQLField(GraphQLString, { - 'req1': GraphQLArgument(GraphQLNonNull(GraphQLInt)), - 'req2': GraphQLArgument(GraphQLNonNull(GraphQLInt)), - }), - 'multipleOpts': GraphQLField(GraphQLString, { - 'opt1': GraphQLArgument(GraphQLInt, 0), - 'opt2': GraphQLArgument(GraphQLInt, 0) - }), - 'multipleOptsAndReq': GraphQLField(GraphQLString, { - 'req1': GraphQLArgument(GraphQLNonNull(GraphQLInt)), - 'req2': GraphQLArgument(GraphQLNonNull(GraphQLInt)), - 'opt1': GraphQLArgument(GraphQLInt, 0), - 'opt2': GraphQLArgument(GraphQLInt, 0) - }) -}) - -QueryRoot = GraphQLObjectType('QueryRoot', { - 'human': GraphQLField(Human, { - 'id': GraphQLArgument(GraphQLID), - }), - 'dog': GraphQLField(Dog), - 'pet': GraphQLField(Pet), - 'alien': GraphQLField(Alien), - 'catOrDog': GraphQLField(CatOrDog), - 'humanOrAlien': GraphQLField(HumanOrAlien), - 'complicatedArgs': GraphQLField(ComplicatedArgs), -}) +ComplexInput = GraphQLInputObjectType( + "ComplexInput", + { + "requiredField": GraphQLInputObjectField(GraphQLNonNull(GraphQLBoolean)), + "intField": GraphQLInputObjectField(GraphQLInt), + "stringField": GraphQLInputObjectField(GraphQLString), + "booleanField": GraphQLInputObjectField(GraphQLBoolean), + "stringListField": GraphQLInputObjectField(GraphQLList(GraphQLString)), + }, +) + +ComplicatedArgs = GraphQLObjectType( + "ComplicatedArgs", + { + "intArgField": GraphQLField( + GraphQLString, {"intArg": GraphQLArgument(GraphQLInt)} + ), + "nonNullIntArgField": GraphQLField( + GraphQLString, + {"nonNullIntArg": GraphQLArgument(GraphQLNonNull(GraphQLInt))}, + ), + "stringArgField": GraphQLField( + GraphQLString, {"stringArg": GraphQLArgument(GraphQLString)} + ), + "booleanArgField": GraphQLField( + GraphQLString, {"booleanArg": GraphQLArgument(GraphQLBoolean)} + ), + "enumArgField": GraphQLField( + GraphQLString, {"enumArg": GraphQLArgument(FurColor)} + ), + "floatArgField": GraphQLField( + GraphQLString, {"floatArg": GraphQLArgument(GraphQLFloat)} + ), + "idArgField": GraphQLField( + GraphQLString, {"idArg": GraphQLArgument(GraphQLID)} + ), + "stringListArgField": GraphQLField( + GraphQLString, + {"stringListArg": GraphQLArgument(GraphQLList(GraphQLString))}, + ), + "complexArgField": GraphQLField( + GraphQLString, {"complexArg": GraphQLArgument(ComplexInput)} + ), + "multipleReqs": GraphQLField( + GraphQLString, + { + "req1": GraphQLArgument(GraphQLNonNull(GraphQLInt)), + "req2": GraphQLArgument(GraphQLNonNull(GraphQLInt)), + }, + ), + "multipleOpts": GraphQLField( + GraphQLString, + { + "opt1": GraphQLArgument(GraphQLInt, 0), + "opt2": GraphQLArgument(GraphQLInt, 0), + }, + ), + "multipleOptsAndReq": GraphQLField( + GraphQLString, + { + "req1": GraphQLArgument(GraphQLNonNull(GraphQLInt)), + "req2": GraphQLArgument(GraphQLNonNull(GraphQLInt)), + "opt1": GraphQLArgument(GraphQLInt, 0), + "opt2": GraphQLArgument(GraphQLInt, 0), + }, + ), + }, +) + +QueryRoot = GraphQLObjectType( + "QueryRoot", + { + "human": GraphQLField(Human, {"id": GraphQLArgument(GraphQLID)}), + "dog": GraphQLField(Dog), + "pet": GraphQLField(Pet), + "alien": GraphQLField(Alien), + "catOrDog": GraphQLField(CatOrDog), + "humanOrAlien": GraphQLField(HumanOrAlien), + "complicatedArgs": GraphQLField(ComplicatedArgs), + }, +) test_schema = GraphQLSchema( query=QueryRoot, directives=[ GraphQLIncludeDirective, GraphQLSkipDirective, - GraphQLDirective(name='onQuery', locations=[DirectiveLocation.QUERY]), - GraphQLDirective(name='onMutation', locations=[DirectiveLocation.MUTATION]), - GraphQLDirective(name='onSubscription', locations=[DirectiveLocation.SUBSCRIPTION]), - GraphQLDirective(name='onField', locations=[DirectiveLocation.FIELD]), - GraphQLDirective(name='onFragmentDefinition', locations=[DirectiveLocation.FRAGMENT_DEFINITION]), - GraphQLDirective(name='onFragmentSpread', locations=[DirectiveLocation.FRAGMENT_SPREAD]), - GraphQLDirective(name='onInlineFragment', locations=[DirectiveLocation.INLINE_FRAGMENT]), - GraphQLDirective(name='OnSchema', locations=[DirectiveLocation.SCHEMA]), - GraphQLDirective(name='onScalar', locations=[DirectiveLocation.SCALAR]), - GraphQLDirective(name='onObject', locations=[DirectiveLocation.OBJECT]), - GraphQLDirective(name='onFieldDefinition', locations=[DirectiveLocation.FIELD_DEFINITION]), - GraphQLDirective(name='onArgumentDefinition', locations=[DirectiveLocation.ARGUMENT_DEFINITION]), - GraphQLDirective(name='onInterface', locations=[DirectiveLocation.INTERFACE]), - GraphQLDirective(name='onUnion', locations=[DirectiveLocation.UNION]), - GraphQLDirective(name='onEnum', locations=[DirectiveLocation.ENUM]), - GraphQLDirective(name='onEnumValue', locations=[DirectiveLocation.ENUM_VALUE]), - GraphQLDirective(name='onInputObject', locations=[DirectiveLocation.INPUT_OBJECT]), - GraphQLDirective(name='onInputFieldDefinition', locations=[DirectiveLocation.INPUT_FIELD_DEFINITION]), + GraphQLDirective(name="onQuery", locations=[DirectiveLocation.QUERY]), + GraphQLDirective(name="onMutation", locations=[DirectiveLocation.MUTATION]), + GraphQLDirective( + name="onSubscription", locations=[DirectiveLocation.SUBSCRIPTION] + ), + GraphQLDirective(name="onField", locations=[DirectiveLocation.FIELD]), + GraphQLDirective( + name="onFragmentDefinition", + locations=[DirectiveLocation.FRAGMENT_DEFINITION], + ), + GraphQLDirective( + name="onFragmentSpread", locations=[DirectiveLocation.FRAGMENT_SPREAD] + ), + GraphQLDirective( + name="onInlineFragment", locations=[DirectiveLocation.INLINE_FRAGMENT] + ), + GraphQLDirective(name="OnSchema", locations=[DirectiveLocation.SCHEMA]), + GraphQLDirective(name="onScalar", locations=[DirectiveLocation.SCALAR]), + GraphQLDirective(name="onObject", locations=[DirectiveLocation.OBJECT]), + GraphQLDirective( + name="onFieldDefinition", locations=[DirectiveLocation.FIELD_DEFINITION] + ), + GraphQLDirective( + name="onArgumentDefinition", + locations=[DirectiveLocation.ARGUMENT_DEFINITION], + ), + GraphQLDirective(name="onInterface", locations=[DirectiveLocation.INTERFACE]), + GraphQLDirective(name="onUnion", locations=[DirectiveLocation.UNION]), + GraphQLDirective(name="onEnum", locations=[DirectiveLocation.ENUM]), + GraphQLDirective(name="onEnumValue", locations=[DirectiveLocation.ENUM_VALUE]), + GraphQLDirective( + name="onInputObject", locations=[DirectiveLocation.INPUT_OBJECT] + ), + GraphQLDirective( + name="onInputFieldDefinition", + locations=[DirectiveLocation.INPUT_FIELD_DEFINITION], + ), ], - types=[Cat, Dog, Human, Alien] + types=[Cat, Dog, Human, Alien], ) def expect_valid(schema, rules, query): errors = validate(schema, parse(query), rules) - assert errors == [], 'Error: %s, Should validate' % errors + assert errors == [], "Error: %s, Should validate" % errors def sort_lists(value): @@ -222,15 +280,16 @@ def sort_lists(value): def expect_invalid(schema, rules, query, expected_errors, sort_list=True): errors = validate(schema, parse(query), rules) - assert errors, 'Should not validate' + assert errors, "Should not validate" for error in expected_errors: - error['locations'] = [ - {'line': loc.line, 'column': loc.column} - for loc in error['locations'] + error["locations"] = [ + {"line": loc.line, "column": loc.column} for loc in error["locations"] ] if sort_list: - assert sort_lists(list(map(format_error, errors))) == sort_lists(expected_errors) + assert sort_lists(list(map(format_error, errors))) == sort_lists( + expected_errors + ) else: assert list(map(format_error, errors)) == expected_errors From 51192d543652f0ff7537a914b6096d81891e707b Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sat, 23 Jun 2018 12:18:12 -0700 Subject: [PATCH 03/12] Fixed tests --- graphql/error/tests/test_base.py | 13 +++++++------ graphql/execution/tests/test_mutations.py | 5 ++--- graphql/execution/tests/test_nonnull.py | 14 +++++--------- graphql/execution/tests/test_subscribe.py | 18 ++++++------------ 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index 1f905fae..740e0023 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -4,10 +4,11 @@ from graphql.execution import execute from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -from graphql.execution.base import ResolveInfo -from mypy_extensions import NoReturn -from typing import Any -from typing import Optional + +if False: + from graphql.execution.base import ResolveInfo + from typing import Any + from typing import Optional def test_raise(): @@ -15,7 +16,7 @@ def test_raise(): ast = parse("query Example { a }") def resolver(context, *_): - # type: (Optional[Any], *ResolveInfo) -> NoReturn + # type: (Optional[Any], *ResolveInfo) -> None raise Exception("Failed") Type = GraphQLObjectType( @@ -31,7 +32,7 @@ def test_reraise(): ast = parse("query Example { a }") def resolver(context, *_): - # type: (Optional[Any], *ResolveInfo) -> NoReturn + # type: (Optional[Any], *ResolveInfo) -> None raise Exception("Failed") Type = GraphQLObjectType( diff --git a/graphql/execution/tests/test_mutations.py b/graphql/execution/tests/test_mutations.py index d7ef530b..d7ec17bc 100644 --- a/graphql/execution/tests/test_mutations.py +++ b/graphql/execution/tests/test_mutations.py @@ -10,7 +10,6 @@ GraphQLSchema, GraphQLString, ) -from mypy_extensions import NoReturn # from graphql.execution.executors.asyncio import AsyncioExecutor # from graphql.execution.executors.thread import ThreadExecutor @@ -39,11 +38,11 @@ def promise_to_change_the_number(self, n): return self.immediately_change_the_number(n) def fail_to_change_the_number(self, n): - # type: (int) -> NoReturn + # type: (int) -> None raise Exception("Cannot change the number") def promise_and_fail_to_change_the_number(self, n): - # type: (int) -> NoReturn + # type: (int) -> None # TODO: async self.fail_to_change_the_number(n) diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py index f880886f..8a44fa9e 100644 --- a/graphql/execution/tests/test_nonnull.py +++ b/graphql/execution/tests/test_nonnull.py @@ -12,13 +12,9 @@ from .utils import rejected, resolved -# from mypy_extensions import NoReturn -# from promise.promise import Promise -# from typing import Any -# from typing import Optional -# from typing import Dict -# from typing import Tuple -# from typing import Union +if False: + from promise import Promise + from typing import Any, Optional, Dict, Tuple, Union sync_error = Exception("sync") non_null_sync_error = Exception("nonNullSync") @@ -28,11 +24,11 @@ class ThrowingData(object): def sync(self): - # type: () -> NoReturn + # type: () -> None raise sync_error def nonNullSync(self): - # type: () -> NoReturn + # type: () -> None raise non_null_sync_error def promise(self): diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py index 6175dc80..a03f37ba 100644 --- a/graphql/execution/tests/test_subscribe.py +++ b/graphql/execution/tests/test_subscribe.py @@ -15,17 +15,11 @@ subscribe, ) -# from graphql.execution.base import ResolveInfo -# from rx.core.anonymousobservable import AnonymousObservable -# from rx.subjects.subject import Subject -# from typing import Optional -# from typing import Union -# from mypy_extensions import NoReturn -# from typing import Any -# from typing import Callable -# from graphql.type.schema import GraphQLSchema -# from graphql.execution.base import ExecutionResult -# from typing import Tuple +if False: + from graphql.execution.base import ResolveInfo + from rx.core.anonymousobservable import AnonymousObservable + from typing import Optional, Union, Any, Callable, Tuple + from graphql.execution.base import ExecutionResult Email = namedtuple("Email", "from_,subject,message,unread") @@ -277,7 +271,7 @@ def test_returns_an_error_if_subscribe_function_returns_error(): exc = Exception("Throw!") def thrower(root, info): - # type: (Optional[Any], ResolveInfo) -> NoReturn + # type: (Optional[Any], ResolveInfo) -> None raise exc erroring_email_schema = email_schema_with_resolvers(thrower) From 29e1456b6f19b65bdb566b312a637b37a13e056a Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sat, 23 Jun 2018 12:19:44 -0700 Subject: [PATCH 04/12] Changed anonymous observbable static type imports --- graphql/backend/core.py | 4 ++-- graphql/execution/executor.py | 12 ++++++------ graphql/execution/tests/test_subscribe.py | 6 +++--- graphql/graphql.py | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/graphql/backend/core.py b/graphql/backend/core.py index 53796fa7..e5118426 100644 --- a/graphql/backend/core.py +++ b/graphql/backend/core.py @@ -14,7 +14,7 @@ from ..language.ast import Document from ..type.schema import GraphQLSchema from ..execution.base import ExecutionResult - from rx.core.anonymousobservable import AnonymousObservable + from rx import Observable def execute_and_validate( @@ -23,7 +23,7 @@ def execute_and_validate( *args, # type: Any **kwargs # type: Any ): - # type: (...) -> Union[ExecutionResult, AnonymousObservable] + # type: (...) -> Union[ExecutionResult, Observable] do_validation = kwargs.get("validate", True) if do_validation: validation_errors = validate(schema, document_ast) diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index f35043be..f759055c 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -37,7 +37,7 @@ if False: from typing import Any, Optional, Union, Dict, List, Callable - from rx.core.anonymousobservable import AnonymousObservable + from rx import Observable from ..type.schema import GraphQLSchema from ..language.ast import Document, OperationDefinition, Field @@ -45,7 +45,7 @@ def subscribe(*args, **kwargs): - # type: (*Any, **Any) -> Union[ExecutionResult, AnonymousObservable] + # type: (*Any, **Any) -> Union[ExecutionResult, Observable] allow_subscriptions = kwargs.pop("allow_subscriptions", True) return execute(*args, allow_subscriptions=allow_subscriptions, **kwargs) @@ -117,7 +117,7 @@ def execute( ) def executor(v): - # type: (Optional[Any]) -> Union[OrderedDict, Promise, AnonymousObservable] + # type: (Optional[Any]) -> Union[OrderedDict, Promise, Observable] return execute_operation(exe_context, exe_context.operation, root) def on_rejected(error): @@ -126,7 +126,7 @@ def on_rejected(error): return None def on_resolve(data): - # type: (Union[None, OrderedDict, AnonymousObservable]) -> Union[ExecutionResult, AnonymousObservable] + # type: (Union[None, OrderedDict, Observable]) -> Union[ExecutionResult, Observable] if isinstance(data, Observable): return data @@ -260,7 +260,7 @@ def subscribe_fields( source_value, # type: Union[None, Data, type] fields, # type: DefaultOrderedDict ): - # type: (...) -> AnonymousObservable + # type: (...) -> Observable exe_context = SubscriberExecutionContext(exe_context) def on_error(error): @@ -364,7 +364,7 @@ def subscribe_field( field_asts, # type: List[Field] path, # type: List[str] ): - # type: (...) -> AnonymousObservable + # type: (...) -> Observable field_ast = field_asts[0] field_name = field_ast.name.value diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py index a03f37ba..661113f0 100644 --- a/graphql/execution/tests/test_subscribe.py +++ b/graphql/execution/tests/test_subscribe.py @@ -17,7 +17,7 @@ if False: from graphql.execution.base import ResolveInfo - from rx.core.anonymousobservable import AnonymousObservable + from rx import Observable from typing import Optional, Union, Any, Callable, Tuple from graphql.execution.base import ExecutionResult @@ -84,7 +84,7 @@ def get_unbound_function(func): def email_schema_with_resolvers(resolve_fn=None): # type: (Callable) -> GraphQLSchema def default_resolver(root, info): - # type: (Any, ResolveInfo) -> Union[AnonymousObservable, Subject] + # type: (Any, ResolveInfo) -> Union[Observable, Subject] func = getattr(root, "importantEmail", None) if func: func = get_unbound_function(func) @@ -129,7 +129,7 @@ def create_subscription( ast=None, # type: Optional[Any] vars=None, # type: Optional[Any] ): - # type: (...) -> Tuple[Callable, Union[ExecutionResult, AnonymousObservable]] + # type: (...) -> Tuple[Callable, Union[ExecutionResult, Observable]] class Root(object): class inbox(object): emails = [ diff --git a/graphql/graphql.py b/graphql/graphql.py index be5b6119..ef695bad 100644 --- a/graphql/graphql.py +++ b/graphql/graphql.py @@ -4,7 +4,7 @@ from promise import promisify if False: - from rx.core.anonymousobservable import AnonymousObservable + from rx import Observable from typing import Any, Union, Optional from .language.ast import Document from .type.schema import GraphQLSchema @@ -34,7 +34,7 @@ def graphql(*args, **kwargs): - # type: (*Any, **Any) -> Union[ExecutionResult, AnonymousObservable] + # type: (*Any, **Any) -> Union[ExecutionResult, Observable] return_promise = kwargs.get("return_promise", False) if return_promise: return execute_graphql_as_promise(*args, **kwargs) @@ -53,7 +53,7 @@ def execute_graphql( backend=None, # type: Optional[Any] **execute_options # type: Any ): - # type: (...) -> Union[ExecutionResult, AnonymousObservable] + # type: (...) -> Union[ExecutionResult, Observable] try: if backend is None: backend = get_default_backend() From b2111afe18d8395f1d9caec4c30b6ce9c9f6a2b0 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sat, 23 Jun 2018 12:35:16 -0700 Subject: [PATCH 05/12] Fixed flake8 issues --- graphql/backend/__init__.py | 2 +- graphql/backend/base.py | 2 +- graphql/backend/cache.py | 2 +- graphql/backend/compiled.py | 2 +- graphql/backend/core.py | 2 +- graphql/backend/decider.py | 2 +- graphql/error/base.py | 2 +- graphql/error/format_error.py | 2 +- graphql/error/located_error.py | 2 +- graphql/error/syntax_error.py | 2 +- graphql/error/tests/test_base.py | 2 +- graphql/execution/base.py | 2 +- graphql/execution/executor.py | 2 +- graphql/execution/executors/asyncio.py | 2 +- graphql/execution/executors/sync.py | 2 +- graphql/execution/executors/thread.py | 2 +- graphql/execution/executors/utils.py | 2 +- graphql/execution/middleware.py | 2 +- graphql/execution/tests/test_nonnull.py | 2 +- graphql/execution/tests/test_subscribe.py | 2 +- graphql/execution/utils.py | 2 +- graphql/execution/values.py | 2 +- graphql/graphql.py | 2 +- graphql/language/ast.py | 2 +- graphql/language/lexer.py | 2 +- graphql/language/location.py | 2 +- graphql/language/parser.py | 2 +- graphql/language/printer.py | 2 +- graphql/language/visitor.py | 2 +- graphql/pyutils/cached_property.py | 2 +- graphql/pyutils/contain_subset.py | 2 +- graphql/pyutils/default_ordered_dict.py | 2 +- graphql/pyutils/pair_set.py | 2 +- graphql/type/definition.py | 2 +- graphql/type/introspection.py | 2 +- graphql/type/scalars.py | 2 +- graphql/type/schema.py | 2 +- graphql/type/typemap.py | 2 +- graphql/utils/ast_to_code.py | 2 +- graphql/utils/concat_ast.py | 2 +- graphql/utils/get_field_def.py | 2 +- graphql/utils/get_operation_ast.py | 2 +- graphql/utils/is_valid_literal_value.py | 2 +- graphql/utils/is_valid_value.py | 2 +- graphql/utils/quoted_or_list.py | 2 +- graphql/utils/schema_printer.py | 2 +- graphql/utils/type_comparators.py | 2 +- graphql/utils/type_from_ast.py | 2 +- graphql/utils/type_info.py | 2 +- graphql/utils/value_from_ast.py | 2 +- graphql/validation/rules/arguments_of_correct_type.py | 2 +- graphql/validation/rules/base.py | 2 +- graphql/validation/rules/default_values_of_correct_type.py | 2 +- graphql/validation/rules/fields_on_correct_type.py | 2 +- graphql/validation/rules/fragments_on_composite_types.py | 2 +- graphql/validation/rules/known_argument_names.py | 2 +- graphql/validation/rules/known_type_names.py | 2 +- graphql/validation/rules/lone_anonymous_operation.py | 2 +- graphql/validation/rules/no_fragment_cycles.py | 2 +- graphql/validation/rules/no_undefined_variables.py | 2 +- graphql/validation/rules/no_unused_fragments.py | 2 +- graphql/validation/rules/no_unused_variables.py | 2 +- graphql/validation/rules/overlapping_fields_can_be_merged.py | 2 +- graphql/validation/rules/possible_fragment_spreads.py | 2 +- graphql/validation/rules/provided_non_null_arguments.py | 2 +- graphql/validation/rules/scalar_leafs.py | 2 +- graphql/validation/rules/unique_argument_names.py | 2 +- graphql/validation/rules/unique_fragment_names.py | 2 +- graphql/validation/rules/unique_input_field_names.py | 2 +- graphql/validation/rules/unique_operation_names.py | 2 +- graphql/validation/rules/unique_variable_names.py | 2 +- graphql/validation/rules/variables_in_allowed_position.py | 2 +- graphql/validation/validation.py | 2 +- setup.cfg | 2 +- 74 files changed, 74 insertions(+), 74 deletions(-) diff --git a/graphql/backend/__init__.py b/graphql/backend/__init__.py index b3d714f0..87e9493e 100644 --- a/graphql/backend/__init__.py +++ b/graphql/backend/__init__.py @@ -9,7 +9,7 @@ from .decider import GraphQLDeciderBackend from .cache import GraphQLCachedBackend -if False: +if False: # flake8: noqa from typing import Union _default_backend = None diff --git a/graphql/backend/base.py b/graphql/backend/base.py index 909942ac..ee6c143e 100644 --- a/graphql/backend/base.py +++ b/graphql/backend/base.py @@ -4,7 +4,7 @@ from abc import ABCMeta, abstractmethod import six -if False: +if False: # flake8: noqa from typing import Dict, Optional, Union, Callable from ..language.ast import Document from ..type.schema import GraphQLSchema diff --git a/graphql/backend/cache.py b/graphql/backend/cache.py index 683d976e..1ecd1267 100644 --- a/graphql/backend/cache.py +++ b/graphql/backend/cache.py @@ -4,7 +4,7 @@ from .base import GraphQLBackend -if False: +if False: # flake8: noqa from typing import Any, Dict, Optional, Union, Tuple, Hashable from .base import GraphQLDocument diff --git a/graphql/backend/compiled.py b/graphql/backend/compiled.py index d7950bc9..7dc88e50 100644 --- a/graphql/backend/compiled.py +++ b/graphql/backend/compiled.py @@ -1,7 +1,7 @@ from six import string_types from .base import GraphQLDocument -if False: +if False: # flake8: noqa from ..type.schema import GraphQLSchema from typing import Any, Optional, Dict, Callable, Union diff --git a/graphql/backend/core.py b/graphql/backend/core.py index e5118426..9368c7de 100644 --- a/graphql/backend/core.py +++ b/graphql/backend/core.py @@ -8,7 +8,7 @@ from .base import GraphQLBackend, GraphQLDocument -if False: +if False: # flake8: noqa from typing import Any, Optional, Union from .base import GraphQLDocument from ..language.ast import Document diff --git a/graphql/backend/decider.py b/graphql/backend/decider.py index c4d1b3b4..6019393c 100644 --- a/graphql/backend/decider.py +++ b/graphql/backend/decider.py @@ -1,6 +1,6 @@ from .base import GraphQLBackend, GraphQLDocument -if False: +if False: # flake8: noqa from typing import List, Union, Any, Optional from ..type.schema import GraphQLSchema diff --git a/graphql/error/base.py b/graphql/error/base.py index d1310acd..f84482f2 100644 --- a/graphql/error/base.py +++ b/graphql/error/base.py @@ -1,7 +1,7 @@ import six from ..language.location import get_location -if False: +if False: # flake8: noqa from ..language.source import Source from ..language.location import SourceLocation from types import TracebackType diff --git a/graphql/error/format_error.py b/graphql/error/format_error.py index 4592e850..f7c9cb52 100644 --- a/graphql/error/format_error.py +++ b/graphql/error/format_error.py @@ -2,7 +2,7 @@ from .base import GraphQLError -if False: +if False: # flake8: noqa from .base import GraphQLError from .located_error import GraphQLLocatedError from typing import Any, Dict, Union diff --git a/graphql/error/located_error.py b/graphql/error/located_error.py index ea4284d4..3bf70c98 100644 --- a/graphql/error/located_error.py +++ b/graphql/error/located_error.py @@ -2,7 +2,7 @@ from .base import GraphQLError -if False: +if False: # flake8: noqa from ..language.ast import Field from typing import List, Union diff --git a/graphql/error/syntax_error.py b/graphql/error/syntax_error.py index 480c1fb7..4be4a4b4 100644 --- a/graphql/error/syntax_error.py +++ b/graphql/error/syntax_error.py @@ -1,7 +1,7 @@ from ..language.location import get_location from .base import GraphQLError -if False: +if False: # flake8: noqa from ..language.source import Source from ..language.location import SourceLocation diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index 740e0023..28d8e2a3 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -5,7 +5,7 @@ from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -if False: +if False: # flake8: noqa from graphql.execution.base import ResolveInfo from typing import Any from typing import Optional diff --git a/graphql/execution/base.py b/graphql/execution/base.py index 985c24c3..36c42428 100644 --- a/graphql/execution/base.py +++ b/graphql/execution/base.py @@ -12,7 +12,7 @@ ) from ..error.format_error import format_error as default_format_error -if False: +if False: # flake8: noqa from typing import Any, Optional, Dict, List, Union from ..language.ast import Field, OperationDefinition from ..type.definition import GraphQLList, GraphQLObjectType, GraphQLScalarType diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index f759055c..f23f59c4 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -35,7 +35,7 @@ from .executors.sync import SyncExecutor from .middleware import MiddlewareManager -if False: +if False: # flake8: noqa from typing import Any, Optional, Union, Dict, List, Callable from rx import Observable from ..type.schema import GraphQLSchema diff --git a/graphql/execution/executors/asyncio.py b/graphql/execution/executors/asyncio.py index afb8a968..27637c23 100644 --- a/graphql/execution/executors/asyncio.py +++ b/graphql/execution/executors/asyncio.py @@ -4,7 +4,7 @@ from promise import Promise -if False: +if False: # flake8: noqa from asyncio.unix_events import _UnixSelectorEventLoop from typing import Optional, Any, Callable diff --git a/graphql/execution/executors/sync.py b/graphql/execution/executors/sync.py index 58295d1a..df8aabb6 100644 --- a/graphql/execution/executors/sync.py +++ b/graphql/execution/executors/sync.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from typing import Any, Callable diff --git a/graphql/execution/executors/thread.py b/graphql/execution/executors/thread.py index 9d682b64..35210d99 100644 --- a/graphql/execution/executors/thread.py +++ b/graphql/execution/executors/thread.py @@ -4,7 +4,7 @@ from promise import Promise from .utils import process -if False: +if False: # flake8: noqa from typing import Any, Callable diff --git a/graphql/execution/executors/utils.py b/graphql/execution/executors/utils.py index 1cab3ff4..41cd29d1 100644 --- a/graphql/execution/executors/utils.py +++ b/graphql/execution/executors/utils.py @@ -1,6 +1,6 @@ from sys import exc_info -if False: +if False: # flake8: noqa from ..base import ResolveInfo from promise import Promise from typing import Callable, Dict, Tuple, Union diff --git a/graphql/execution/middleware.py b/graphql/execution/middleware.py index 0c7f82d3..0880858b 100644 --- a/graphql/execution/middleware.py +++ b/graphql/execution/middleware.py @@ -4,7 +4,7 @@ from promise import Promise -if False: +if False: # flake8: noqa from .base import ResolveInfo from typing import Any, Callable, Iterator, Tuple, Union, List, Dict diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py index 8a44fa9e..ebd1e844 100644 --- a/graphql/execution/tests/test_nonnull.py +++ b/graphql/execution/tests/test_nonnull.py @@ -12,7 +12,7 @@ from .utils import rejected, resolved -if False: +if False: # flake8: noqa from promise import Promise from typing import Any, Optional, Dict, Tuple, Union diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py index 661113f0..f6ad3f34 100644 --- a/graphql/execution/tests/test_subscribe.py +++ b/graphql/execution/tests/test_subscribe.py @@ -15,7 +15,7 @@ subscribe, ) -if False: +if False: # flake8: noqa from graphql.execution.base import ResolveInfo from rx import Observable from typing import Optional, Union, Any, Callable, Tuple diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py index 6229eb1b..bbab86c3 100644 --- a/graphql/execution/utils.py +++ b/graphql/execution/utils.py @@ -15,7 +15,7 @@ from ..utils.type_from_ast import type_from_ast from .values import get_argument_values, get_variable_values -if False: +if False: # flake8: noqa from ..type.definition import GraphQLObjectType, GraphQLField from ..type.schema import GraphQLSchema from ..language.ast import ( diff --git a/graphql/execution/values.py b/graphql/execution/values.py index 289273ab..a0568321 100644 --- a/graphql/execution/values.py +++ b/graphql/execution/values.py @@ -18,7 +18,7 @@ from ..utils.type_from_ast import type_from_ast from ..utils.value_from_ast import value_from_ast -if False: +if False: # flake8: noqa from ..language.ast import VariableDefinition, Argument from ..type.schema import GraphQLSchema from ..type.definition import GraphQLArgument diff --git a/graphql/graphql.py b/graphql/graphql.py index ef695bad..f7c394b7 100644 --- a/graphql/graphql.py +++ b/graphql/graphql.py @@ -3,7 +3,7 @@ from promise import promisify -if False: +if False: # flake8: noqa from rx import Observable from typing import Any, Union, Optional from .language.ast import Document diff --git a/graphql/language/ast.py b/graphql/language/ast.py index e9cb307c..7a31e453 100644 --- a/graphql/language/ast.py +++ b/graphql/language/ast.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from .parser import Loc from typing import Any, Optional, Union, List, Tuple, Iterable diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py index dbc11401..a41c4976 100644 --- a/graphql/language/lexer.py +++ b/graphql/language/lexer.py @@ -4,7 +4,7 @@ from ..error import GraphQLSyntaxError -if False: +if False: # flake8: noqa from typing import Optional from .source import Source diff --git a/graphql/language/location.py b/graphql/language/location.py index 973743b0..6cf48f50 100644 --- a/graphql/language/location.py +++ b/graphql/language/location.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from .source import Source from typing import Any diff --git a/graphql/language/parser.py b/graphql/language/parser.py index fd7e5494..f8a20b84 100644 --- a/graphql/language/parser.py +++ b/graphql/language/parser.py @@ -5,7 +5,7 @@ from .lexer import Lexer, TokenKind, get_token_desc, get_token_kind_desc from .source import Source -if False: +if False: # flake8: noqa from typing import Dict, Union, Any, Optional, Callable, List from ..error.syntax_error import GraphQLSyntaxError from .source import Source diff --git a/graphql/language/printer.py b/graphql/language/printer.py index 3c6c1f7d..68bb0e4d 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -2,7 +2,7 @@ from .visitor import Visitor, visit -if False: +if False: # flake8: noqa from typing import Any, List, Optional, Union from graphql.language.ast import ( Node, diff --git a/graphql/language/visitor.py b/graphql/language/visitor.py index d5eda74e..4314b28f 100644 --- a/graphql/language/visitor.py +++ b/graphql/language/visitor.py @@ -5,7 +5,7 @@ from . import ast from .visitor_meta import QUERY_DOCUMENT_KEYS, VisitorMeta -if False: +if False: # flake8: noqa from typing import Any, List, Optional, Union, Tuple, Dict from ..utils.type_info import TypeInfo from ..validation.validation import UsageVisitor diff --git a/graphql/pyutils/cached_property.py b/graphql/pyutils/cached_property.py index e1e0fc75..119b9e2a 100644 --- a/graphql/pyutils/cached_property.py +++ b/graphql/pyutils/cached_property.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from typing import Any diff --git a/graphql/pyutils/contain_subset.py b/graphql/pyutils/contain_subset.py index 5b8f3f58..da3aea78 100644 --- a/graphql/pyutils/contain_subset.py +++ b/graphql/pyutils/contain_subset.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from typing import Any, Dict obj = (dict, list, tuple) diff --git a/graphql/pyutils/default_ordered_dict.py b/graphql/pyutils/default_ordered_dict.py index 273e62fd..83a0b307 100644 --- a/graphql/pyutils/default_ordered_dict.py +++ b/graphql/pyutils/default_ordered_dict.py @@ -1,7 +1,7 @@ import copy from collections import OrderedDict -if False: +if False: # flake8: noqa from typing import Any, List diff --git a/graphql/pyutils/pair_set.py b/graphql/pyutils/pair_set.py index f880ec3b..9b369a4c 100644 --- a/graphql/pyutils/pair_set.py +++ b/graphql/pyutils/pair_set.py @@ -1,4 +1,4 @@ -if False: +if False: # flake8: noqa from typing import Dict, Any diff --git a/graphql/type/definition.py b/graphql/type/definition.py index ec23d3dc..f7e0e7ba 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -7,7 +7,7 @@ from ..utils.assert_valid_name import assert_valid_name from ..utils.undefined import Undefined -if False: +if False: # flake8: noqa from typing import List, Dict, Any, Callable, Optional, Union, Type diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index c80170e1..1dafd80d 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -18,7 +18,7 @@ from .directives import DirectiveLocation from .scalars import GraphQLBoolean, GraphQLString -if False: +if False: # flake8: noqa from ..execution.base import ResolveInfo from typing import Union, List, Optional, Any diff --git a/graphql/type/scalars.py b/graphql/type/scalars.py index 4578023c..0169e825 100644 --- a/graphql/type/scalars.py +++ b/graphql/type/scalars.py @@ -3,7 +3,7 @@ from ..language.ast import BooleanValue, FloatValue, IntValue, StringValue from .definition import GraphQLScalarType -if False: +if False: # flake8: noqa from typing import Any, Optional, Union # As per the GraphQL Spec, Integers are only treated as valid when a valid diff --git a/graphql/type/schema.py b/graphql/type/schema.py index 0905749d..06cf5be6 100644 --- a/graphql/type/schema.py +++ b/graphql/type/schema.py @@ -5,7 +5,7 @@ from .introspection import IntrospectionSchema from .typemap import GraphQLTypeMap -if False: +if False: # flake8: noqa from .definition import GraphQLInterfaceType, GraphQLUnionType, GraphQLType from typing import Dict, Union, Any, List, Optional diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index f8eab077..aebff6f0 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -15,7 +15,7 @@ is_output_type, ) -if False: +if False: # flake8: noqa from typing import Any, List, Optional, Union diff --git a/graphql/utils/ast_to_code.py b/graphql/utils/ast_to_code.py index 659562c3..2db01b35 100644 --- a/graphql/utils/ast_to_code.py +++ b/graphql/utils/ast_to_code.py @@ -1,7 +1,7 @@ from ..language.ast import Node from ..language.parser import Loc -if False: +if False: # flake8: noqa from typing import Any diff --git a/graphql/utils/concat_ast.py b/graphql/utils/concat_ast.py index 41401829..8685bbc0 100644 --- a/graphql/utils/concat_ast.py +++ b/graphql/utils/concat_ast.py @@ -2,7 +2,7 @@ from ..language.ast import Document -if False: +if False: # flake8: noqa from typing import Iterable diff --git a/graphql/utils/get_field_def.py b/graphql/utils/get_field_def.py index c7efca75..5b06973f 100644 --- a/graphql/utils/get_field_def.py +++ b/graphql/utils/get_field_def.py @@ -5,7 +5,7 @@ TypeNameMetaFieldDef, ) -if False: +if False: # flake8: noqa from ..language.ast import Field from ..type.definition import GraphQLField, GraphQLInterfaceType, GraphQLObjectType from ..type.schema import GraphQLSchema diff --git a/graphql/utils/get_operation_ast.py b/graphql/utils/get_operation_ast.py index 74fd5a2c..56dccd4e 100644 --- a/graphql/utils/get_operation_ast.py +++ b/graphql/utils/get_operation_ast.py @@ -1,6 +1,6 @@ from ..language import ast -if False: +if False: # flake8: noqa from ..language.ast import Document, OperationDefinition from typing import Optional diff --git a/graphql/utils/is_valid_literal_value.py b/graphql/utils/is_valid_literal_value.py index f91c842b..47d7c13a 100644 --- a/graphql/utils/is_valid_literal_value.py +++ b/graphql/utils/is_valid_literal_value.py @@ -8,7 +8,7 @@ GraphQLScalarType, ) -if False: +if False: # flake8: noqa from ..language.ast import ObjectValue, StringValue from ..type.definition import GraphQLInputObjectType, GraphQLScalarType from typing import Union, Any, List diff --git a/graphql/utils/is_valid_value.py b/graphql/utils/is_valid_value.py index 857b724a..2dd83bfc 100644 --- a/graphql/utils/is_valid_value.py +++ b/graphql/utils/is_valid_value.py @@ -15,7 +15,7 @@ GraphQLScalarType, ) -if False: +if False: # flake8: noqa from typing import Any, List _empty_list = [] # type: List diff --git a/graphql/utils/quoted_or_list.py b/graphql/utils/quoted_or_list.py index 22d6aa48..c968b73f 100644 --- a/graphql/utils/quoted_or_list.py +++ b/graphql/utils/quoted_or_list.py @@ -1,6 +1,6 @@ import functools -if False: +if False: # flake8: noqa from typing import List diff --git a/graphql/utils/schema_printer.py b/graphql/utils/schema_printer.py index 13146d10..5fe2df68 100644 --- a/graphql/utils/schema_printer.py +++ b/graphql/utils/schema_printer.py @@ -11,7 +11,7 @@ from .ast_from_value import ast_from_value -if False: +if False: # flake8: noqa from ..type.definition import ( GraphQLArgument, GraphQLType, diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index 90388fd5..2e6b2bbc 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -7,7 +7,7 @@ is_abstract_type, ) -if False: +if False: # flake8: noqa from ..type.typemap import GraphQLTypeMap from ..type.definition import ( GraphQLScalarType, diff --git a/graphql/utils/type_from_ast.py b/graphql/utils/type_from_ast.py index 58719c41..c3a0d411 100644 --- a/graphql/utils/type_from_ast.py +++ b/graphql/utils/type_from_ast.py @@ -1,7 +1,7 @@ from ..language import ast from ..type.definition import GraphQLList, GraphQLNonNull -if False: +if False: # flake8: noqa from ..language.ast import ListType, NamedType, NonNullType from ..type.schema import GraphQLSchema from typing import Any, Union diff --git a/graphql/utils/type_info.py b/graphql/utils/type_info.py index de07ddb7..9f87f7c4 100644 --- a/graphql/utils/type_info.py +++ b/graphql/utils/type_info.py @@ -11,7 +11,7 @@ from .get_field_def import get_field_def from .type_from_ast import type_from_ast -if False: +if False: # flake8: noqa from ..type.schema import GraphQLSchema from ..type.definition import ( GraphQLType, diff --git a/graphql/utils/value_from_ast.py b/graphql/utils/value_from_ast.py index f7a730f0..f8a78c70 100644 --- a/graphql/utils/value_from_ast.py +++ b/graphql/utils/value_from_ast.py @@ -7,7 +7,7 @@ GraphQLScalarType, ) -if False: +if False: # flake8: noqa from ..language.ast import Node from ..type.definition import GraphQLType from typing import Any, Dict, Union, Optional, List diff --git a/graphql/validation/rules/arguments_of_correct_type.py b/graphql/validation/rules/arguments_of_correct_type.py index 416e36bd..d9d7d950 100644 --- a/graphql/validation/rules/arguments_of_correct_type.py +++ b/graphql/validation/rules/arguments_of_correct_type.py @@ -3,7 +3,7 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Argument from typing import Any, List, Union diff --git a/graphql/validation/rules/base.py b/graphql/validation/rules/base.py index 368dc168..821dd747 100644 --- a/graphql/validation/rules/base.py +++ b/graphql/validation/rules/base.py @@ -1,6 +1,6 @@ from ...language.visitor import Visitor -if False: +if False: # flake8: noqa from ..validation import ValidationContext diff --git a/graphql/validation/rules/default_values_of_correct_type.py b/graphql/validation/rules/default_values_of_correct_type.py index 3b2f52f8..d09500c4 100644 --- a/graphql/validation/rules/default_values_of_correct_type.py +++ b/graphql/validation/rules/default_values_of_correct_type.py @@ -4,7 +4,7 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Document, OperationDefinition, SelectionSet from typing import List, Union diff --git a/graphql/validation/rules/fields_on_correct_type.py b/graphql/validation/rules/fields_on_correct_type.py index 4ce057eb..f6446471 100644 --- a/graphql/validation/rules/fields_on_correct_type.py +++ b/graphql/validation/rules/fields_on_correct_type.py @@ -7,7 +7,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/fragments_on_composite_types.py b/graphql/validation/rules/fragments_on_composite_types.py index 1873ac5f..e775b700 100644 --- a/graphql/validation/rules/fragments_on_composite_types.py +++ b/graphql/validation/rules/fragments_on_composite_types.py @@ -3,7 +3,7 @@ from ...type.definition import is_composite_type from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/known_argument_names.py b/graphql/validation/rules/known_argument_names.py index b9a7b1fd..e7b4839a 100644 --- a/graphql/validation/rules/known_argument_names.py +++ b/graphql/validation/rules/known_argument_names.py @@ -4,7 +4,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Argument from typing import Any, List, Union diff --git a/graphql/validation/rules/known_type_names.py b/graphql/validation/rules/known_type_names.py index 7f147a98..b0a95aeb 100644 --- a/graphql/validation/rules/known_type_names.py +++ b/graphql/validation/rules/known_type_names.py @@ -3,7 +3,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import NamedType from typing import Any diff --git a/graphql/validation/rules/lone_anonymous_operation.py b/graphql/validation/rules/lone_anonymous_operation.py index 2699f759..89c480f6 100644 --- a/graphql/validation/rules/lone_anonymous_operation.py +++ b/graphql/validation/rules/lone_anonymous_operation.py @@ -2,7 +2,7 @@ from ...language import ast from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import Any, List, Optional, Union diff --git a/graphql/validation/rules/no_fragment_cycles.py b/graphql/validation/rules/no_fragment_cycles.py index ccd9f8f3..6dfdf46b 100644 --- a/graphql/validation/rules/no_fragment_cycles.py +++ b/graphql/validation/rules/no_fragment_cycles.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/rules/no_undefined_variables.py b/graphql/validation/rules/no_undefined_variables.py index afa0db1b..77f3eb6e 100644 --- a/graphql/validation/rules/no_undefined_variables.py +++ b/graphql/validation/rules/no_undefined_variables.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/rules/no_unused_fragments.py b/graphql/validation/rules/no_unused_fragments.py index b4ba428a..76f8f35a 100644 --- a/graphql/validation/rules/no_unused_fragments.py +++ b/graphql/validation/rules/no_unused_fragments.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union, Any, Optional diff --git a/graphql/validation/rules/no_unused_variables.py b/graphql/validation/rules/no_unused_variables.py index ed7b77fc..baca2daa 100644 --- a/graphql/validation/rules/no_unused_variables.py +++ b/graphql/validation/rules/no_unused_variables.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index 74a1e188..834acf50 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -17,7 +17,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import OperationDefinition, Field, InlineFragment, SelectionSet from ...type.definition import GraphQLUnionType, GraphQLField, GraphQLScalarType diff --git a/graphql/validation/rules/possible_fragment_spreads.py b/graphql/validation/rules/possible_fragment_spreads.py index 3cd8f1aa..d6b916c0 100644 --- a/graphql/validation/rules/possible_fragment_spreads.py +++ b/graphql/validation/rules/possible_fragment_spreads.py @@ -3,7 +3,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule -if False: +if False: # flake8: noqa from ..language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/provided_non_null_arguments.py b/graphql/validation/rules/provided_non_null_arguments.py index 190e9d03..1d727a0d 100644 --- a/graphql/validation/rules/provided_non_null_arguments.py +++ b/graphql/validation/rules/provided_non_null_arguments.py @@ -2,7 +2,7 @@ from ...type.definition import GraphQLNonNull from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Optional, Union diff --git a/graphql/validation/rules/scalar_leafs.py b/graphql/validation/rules/scalar_leafs.py index 97755de0..76d25a24 100644 --- a/graphql/validation/rules/scalar_leafs.py +++ b/graphql/validation/rules/scalar_leafs.py @@ -2,7 +2,7 @@ from ...type.definition import get_named_type, is_leaf_type from .base import ValidationRule -if False: +if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/unique_argument_names.py b/graphql/validation/rules/unique_argument_names.py index b0f0adfb..60dfb2e6 100644 --- a/graphql/validation/rules/unique_argument_names.py +++ b/graphql/validation/rules/unique_argument_names.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Field, InlineFragment, Argument from typing import Any, List, Union diff --git a/graphql/validation/rules/unique_fragment_names.py b/graphql/validation/rules/unique_fragment_names.py index ff1003f8..fe2141e7 100644 --- a/graphql/validation/rules/unique_fragment_names.py +++ b/graphql/validation/rules/unique_fragment_names.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/rules/unique_input_field_names.py b/graphql/validation/rules/unique_input_field_names.py index f5afbeb1..78a89a50 100644 --- a/graphql/validation/rules/unique_input_field_names.py +++ b/graphql/validation/rules/unique_input_field_names.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Argument, ObjectValue, ObjectField from typing import Any, List, Union diff --git a/graphql/validation/rules/unique_operation_names.py b/graphql/validation/rules/unique_operation_names.py index da097447..6bfe70d5 100644 --- a/graphql/validation/rules/unique_operation_names.py +++ b/graphql/validation/rules/unique_operation_names.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import Any, List, Optional, Union diff --git a/graphql/validation/rules/unique_variable_names.py b/graphql/validation/rules/unique_variable_names.py index 8d2ce3d3..2d966152 100644 --- a/graphql/validation/rules/unique_variable_names.py +++ b/graphql/validation/rules/unique_variable_names.py @@ -1,7 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/rules/variables_in_allowed_position.py b/graphql/validation/rules/variables_in_allowed_position.py index 6c62f449..8bcf1c52 100644 --- a/graphql/validation/rules/variables_in_allowed_position.py +++ b/graphql/validation/rules/variables_in_allowed_position.py @@ -4,7 +4,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule -if False: +if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition from typing import List, Union diff --git a/graphql/validation/validation.py b/graphql/validation/validation.py index 70596a34..b708f6a3 100644 --- a/graphql/validation/validation.py +++ b/graphql/validation/validation.py @@ -4,7 +4,7 @@ from ..utils.type_info import TypeInfo from .rules import specified_rules -if False: +if False: # flake8: noqa from typing import List, Union from ..language.ast import Document, OperationDefinition, SelectionSet from ..language.visitor_meta import VisitorMeta diff --git a/setup.cfg b/setup.cfg index 722f81b1..fef65f01 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [flake8] -exclude = tests,scripts,setup.py,docs,graphql/execution/executors/asyncio_utils.py +exclude = tests,scripts,setup.py,docs,graphql/execution/executors/asyncio_utils.py,conftest.py max-line-length = 200 [coverage:run] From 8e1092596879e17798c7d5438a9e4e24da8d0ae6 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 27 Jun 2018 20:54:52 -0700 Subject: [PATCH 06/12] Added pluggable python options --- graphql/backend/quiver_cloud.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/graphql/backend/quiver_cloud.py b/graphql/backend/quiver_cloud.py index d8eb7c45..280f23d9 100644 --- a/graphql/backend/quiver_cloud.py +++ b/graphql/backend/quiver_cloud.py @@ -14,14 +14,12 @@ from six.moves.urllib.parse import urlparse GRAPHQL_QUERY = """ -mutation($schemaDsl: String!, $query: String!) { +mutation($schemaDsl: String!, $query: String!, $pythonOptions: PythonOptions) { generateCode( schemaDsl: $schemaDsl query: $query, language: PYTHON, - pythonOptions: { - asyncFramework: PROMISE - } + pythonOptions: $pythonOptions ) { code compilationTime @@ -56,7 +54,7 @@ def __init__(self, dsn, python_options=None, **options): self.secret_key = url.password self.extra_namespace = {} if python_options is None: - python_options = {} + python_options = {"asyncFramework": "PROMISE"} wait_for_promises = python_options.pop("wait_for_promises", None) if wait_for_promises: assert callable(wait_for_promises), "wait_for_promises must be callable." @@ -70,7 +68,11 @@ def make_post_request(self, url, auth, json_payload): return response.json() def generate_source(self, schema, query): - variables = {"schemaDsl": print_schema(schema), "query": query} + variables = { + "schemaDsl": print_schema(schema), + "query": query, + "pythonOptions": self.python_options, + } json_response = self.make_post_request( "{}/graphql".format(self.api_url), From 9b7e374eec40de8660bf0a63b1fa95060c04cafe Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 27 Jun 2018 20:55:13 -0700 Subject: [PATCH 07/12] Changed max-line-length for black --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index fef65f01..a65570f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [flake8] exclude = tests,scripts,setup.py,docs,graphql/execution/executors/asyncio_utils.py,conftest.py -max-line-length = 200 +max-line-length = 160 [coverage:run] omit=graphql/backend/quiver_cloud.py,tests,*/tests/* From 697ce7653c447bc6e6f74919339b5043a0165d8e Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 27 Jun 2018 22:31:37 -0700 Subject: [PATCH 08/12] Improved typing --- graphql/error/format_error.py | 2 +- graphql/error/located_error.py | 7 +- graphql/language/ast.py | 5 +- graphql/language/lexer.py | 78 ++++---- graphql/language/printer.py | 6 +- graphql/language/tests/test_ast.py | 2 +- graphql/language/tests/test_visitor.py | 2 +- graphql/language/visitor.py | 53 +++--- graphql/type/definition.py | 57 +++--- graphql/type/tests/test_validation.py | 2 +- graphql/utils/is_valid_literal_value.py | 2 +- graphql/utils/type_comparators.py | 5 +- graphql/utils/type_from_ast.py | 3 +- graphql/utils/type_info.py | 20 +- graphql/validation/rules/__init__.py | 7 +- .../rules/fields_on_correct_type.py | 2 +- .../validation/rules/no_fragment_cycles.py | 13 +- .../rules/no_undefined_variables.py | 4 +- .../validation/rules/no_unused_fragments.py | 6 +- .../validation/rules/no_unused_variables.py | 4 +- .../rules/overlapping_fields_can_be_merged.py | 172 +++++++++++------- .../rules/possible_fragment_spreads.py | 6 +- .../rules/provided_non_null_arguments.py | 1 + .../validation/rules/unique_argument_names.py | 6 +- .../validation/rules/unique_fragment_names.py | 6 +- .../rules/unique_input_field_names.py | 8 +- .../rules/unique_operation_names.py | 8 +- .../validation/rules/unique_variable_names.py | 4 +- .../rules/variables_in_allowed_position.py | 16 +- graphql/validation/validation.py | 45 +++-- 30 files changed, 316 insertions(+), 236 deletions(-) diff --git a/graphql/error/format_error.py b/graphql/error/format_error.py index f7c9cb52..e60b6f1b 100644 --- a/graphql/error/format_error.py +++ b/graphql/error/format_error.py @@ -10,7 +10,7 @@ def format_error(error): # type: (Union[GraphQLError, GraphQLLocatedError]) -> Dict[str, Any] - formatted_error = {"message": text_type(error)} + formatted_error = {"message": text_type(error)} # type: Dict[str, Any] if isinstance(error, GraphQLError): if error.locations is not None: formatted_error["locations"] = [ diff --git a/graphql/error/located_error.py b/graphql/error/located_error.py index 3bf70c98..06bcccea 100644 --- a/graphql/error/located_error.py +++ b/graphql/error/located_error.py @@ -21,13 +21,12 @@ def __init__( try: message = str(original_error) except UnicodeEncodeError: - message = original_error.message.encode("utf-8") + message = original_error.message.encode("utf-8") # type: ignore else: message = "An unknown error occurred." - if hasattr(original_error, "stack"): - stack = original_error.stack - else: + stack = original_error and getattr(original_error, "stack", None) + if not stack: stack = sys.exc_info()[2] super(GraphQLLocatedError, self).__init__( diff --git a/graphql/language/ast.py b/graphql/language/ast.py index 7a31e453..a05072d3 100644 --- a/graphql/language/ast.py +++ b/graphql/language/ast.py @@ -462,9 +462,8 @@ def __eq__(self, other): # type: (Any) -> bool return self is other or ( isinstance(other, Variable) - and - # self.loc == other.loc and - self.name == other.name + and self.name == other.name + # and self.loc == other.loc ) def __repr__(self): diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py index a41c4976..ce4f3179 100644 --- a/graphql/language/lexer.py +++ b/graphql/language/lexer.py @@ -5,7 +5,7 @@ from ..error import GraphQLSyntaxError if False: # flake8: noqa - from typing import Optional + from typing import Optional, Any, List from .source import Source __all__ = ["Token", "Lexer", "TokenKind", "get_token_desc", "get_token_kind_desc"] @@ -28,9 +28,10 @@ def __repr__(self): ) def __eq__(self, other): - # type: (Token) -> bool + # type: (Any) -> bool return ( - self.kind == other.kind + isinstance(other, Token) + and self.kind == other.kind and self.start == other.start and self.end == other.end and self.value == other.value @@ -163,29 +164,33 @@ def read_token(source, from_position): return Token(TokenKind.EOF, position, position) code = char_code_at(body, position) + if code: + if code < 0x0020 and code not in (0x0009, 0x000A, 0x000D): + raise GraphQLSyntaxError( + source, position, u"Invalid character {}.".format(print_char_code(code)) + ) - if code < 0x0020 and code not in (0x0009, 0x000A, 0x000D): - raise GraphQLSyntaxError( - source, position, u"Invalid character {}.".format(print_char_code(code)) - ) - - kind = PUNCT_CODE_TO_KIND.get(code) - if kind is not None: - return Token(kind, position, position + 1) + kind = PUNCT_CODE_TO_KIND.get(code) + if kind is not None: + return Token(kind, position, position + 1) - if code == 46: # . - if char_code_at(body, position + 1) == char_code_at(body, position + 2) == 46: - return Token(TokenKind.SPREAD, position, position + 3) + if code == 46: # . + if ( + char_code_at(body, position + 1) + == char_code_at(body, position + 2) + == 46 + ): + return Token(TokenKind.SPREAD, position, position + 3) - elif 65 <= code <= 90 or code == 95 or 97 <= code <= 122: - # A-Z, _, a-z - return read_name(source, position) + elif 65 <= code <= 90 or code == 95 or 97 <= code <= 122: + # A-Z, _, a-z + return read_name(source, position) - elif code == 45 or 48 <= code <= 57: # -, 0-9 - return read_number(source, position, code) + elif code == 45 or 48 <= code <= 57: # -, 0-9 + return read_number(source, position, code) - elif code == 34: # " - return read_string(source, position) + elif code == 34: # " + return read_string(source, position) raise GraphQLSyntaxError( source, position, u"Unexpected character {}.".format(print_char_code(code)) @@ -238,7 +243,7 @@ def position_after_whitespace(body, start_position): def read_number(source, start, first_code): - # type: (Source, int, int) -> Token + # type: (Source, int, Optional[int]) -> Token """Reads a number token from the source file, either a float or an int depending on whether a decimal point appears. @@ -341,26 +346,23 @@ def read_string(source, start): position = start + 1 chunk_start = position - code = 0 - value = [] + code = 0 # type: Optional[int] + value = [] # type: List[str] append = value.append while position < body_length: code = char_code_at(body, position) - if not ( - code is not None - and code - not in ( - # LineTerminator - 0x000A, - 0x000D, - # Quote - 34, - ) + if code in ( + None, + # LineTerminator + 0x000A, + 0x000D, + # Quote + 34, ): break - if code < 0x0020 and code != 0x0009: + if code < 0x0020 and code != 0x0009: # type: ignore raise GraphQLSyntaxError( source, position, @@ -372,7 +374,7 @@ def read_string(source, start): append(body[chunk_start : position - 1]) code = char_code_at(body, position) - escaped = ESCAPED_CHAR_CODES.get(code) + escaped = ESCAPED_CHAR_CODES.get(code) # type: ignore if escaped is not None: append(escaped) @@ -399,7 +401,9 @@ def read_string(source, start): raise GraphQLSyntaxError( source, position, - u"Invalid character escape sequence: \\{}.".format(unichr(code)), + u"Invalid character escape sequence: \\{}.".format( + unichr(code) # type: ignore + ), ) position += 1 diff --git a/graphql/language/printer.py b/graphql/language/printer.py index 68bb0e4d..cedd8d73 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -56,15 +56,15 @@ class PrintingVisitor(Visitor): def leave_Name(self, node, *args): # type: (Name, *Any) -> str - return node.value + return node.value # type: ignore def leave_Variable(self, node, *args): # type: (Variable, *Any) -> str - return "$" + node.name + return "$" + node.name # type: ignore def leave_Document(self, node, *args): # type: (Document, *Any) -> str - return join(node.definitions, "\n\n") + "\n" + return join(node.definitions, "\n\n") + "\n" # type: ignore def leave_OperationDefinition(self, node, *args): # type: (OperationDefinition, *Any) -> str diff --git a/graphql/language/tests/test_ast.py b/graphql/language/tests/test_ast.py index e0f8476f..64b849a0 100644 --- a/graphql/language/tests/test_ast.py +++ b/graphql/language/tests/test_ast.py @@ -1,6 +1,6 @@ import copy -from graphql.language.visitor_meta import QUERY_DOCUMENT_KEYS, VisitorMeta +from graphql.language.visitor_meta import QUERY_DOCUMENT_KEYS def test_ast_is_hashable(): diff --git a/graphql/language/tests/test_visitor.py b/graphql/language/tests/test_visitor.py index e37a333a..1392fe3e 100644 --- a/graphql/language/tests/test_visitor.py +++ b/graphql/language/tests/test_visitor.py @@ -28,7 +28,7 @@ from typing import Union from graphql.language.ast import Field from graphql.language.ast import Name -from graphql.language.visitor import Falsey +from graphql.language.visitor import _Falsey from typing import List from graphql.language.ast import Argument from graphql.language.ast import IntValue diff --git a/graphql/language/visitor.py b/graphql/language/visitor.py index 4314b28f..ba193046 100644 --- a/graphql/language/visitor.py +++ b/graphql/language/visitor.py @@ -13,7 +13,7 @@ from .printer import PrintingVisitor -class Falsey(object): +class _Falsey(object): def __nonzero__(self): return False @@ -22,15 +22,19 @@ def __bool__(self): return False -BREAK = object() -REMOVE = Falsey() +class _Break(object): + pass + + +BREAK = _Break() +REMOVE = _Falsey() class Stack(object): __slots__ = "in_array", "index", "keys", "edits", "prev" def __init__(self, in_array, index, keys, edits, prev): - # type: (bool, int, Any, List[Tuple[str, str]], Optional[Stack]) -> None + # type: (bool, int, Any, List[Tuple[Union[str, int], Any]], Optional[Stack]) -> None self.in_array = in_array self.index = index self.keys = keys @@ -46,7 +50,7 @@ def visit(root, visitor, key_map=None): in_array = isinstance(root, list) keys = [root] index = -1 - edits = [] # type: List[Tuple[int, Any]] + edits = [] # type: List[Tuple[Union[str, int], Any]] parent = None # type: Optional[Node] path = [] # type: List ancestors = [] # type: List[Node] @@ -75,7 +79,7 @@ def visit(root, visitor, key_map=None): edit_offset = 0 for edit_key, edit_value in edits: if in_array: - edit_key -= edit_offset + edit_key -= edit_offset # type: ignore if in_array and edit_value is REMOVE: node.pop(edit_key) # type: ignore @@ -84,7 +88,6 @@ def visit(root, visitor, key_map=None): else: if isinstance(node, list): node[edit_key] = edit_value - else: setattr(node, edit_key, edit_value) # type: ignore @@ -99,7 +102,6 @@ def visit(root, visitor, key_map=None): key = index if in_array else keys[index] if isinstance(parent, list): node = parent[key] - else: node = getattr(parent, key, None) @@ -148,7 +150,11 @@ def visit(root, visitor, key_map=None): if not is_leaving: stack = Stack(in_array, index, keys, edits, stack) in_array = isinstance(node, list) - keys = node if in_array else visitor_keys.get(type(node), None) or [] + keys = ( + node + if in_array + else visitor_keys.get(type(node), None) or [] # type: ignore + ) # type: ignore index = -1 edits = [] @@ -178,10 +184,11 @@ def enter( path, # type: List[Union[int, str]] ancestors, # type: List[Any] ): - # type: (...) -> Optional[Any] - method = self._get_enter_handler(type(node)) + # type: (...) -> Any + method = self._get_enter_handler(type(node)) # type: ignore if method: return method(self, node, key, parent, path, ancestors) + return None def leave( self, @@ -191,10 +198,11 @@ def leave( path, # type: List[Union[int, str]] ancestors, # type: List[Any] ): - # type: (...) -> Optional[Any] - method = self._get_leave_handler(type(node)) + # type: (...) -> Any + method = self._get_leave_handler(type(node)) # type: ignore if method: return method(self, node, key, parent, path, ancestors) + return None class ParallelVisitor(Visitor): @@ -203,7 +211,10 @@ class ParallelVisitor(Visitor): def __init__(self, visitors): # type: (List[Any]) -> None self.visitors = visitors - self.skipping = [None] * len(visitors) + self.skipping = [None] * len( + visitors + ) # type: List[Union[Node, _Break, _Falsey, None]] + return None def enter( self, @@ -213,7 +224,7 @@ def enter( path, # type: List[Union[int, str]] ancestors, # type: List[Any] ): - # type: (...) -> Optional[Any] + # type: (...) -> Any for i, visitor in enumerate(self.visitors): if not self.skipping[i]: result = visitor.enter(node, key, parent, path, ancestors) @@ -223,6 +234,7 @@ def enter( self.skipping[i] = BREAK elif result is not None: return result + return None def leave( self, @@ -232,7 +244,7 @@ def leave( path, # type: List[Union[int, str]] ancestors, # type: List[Any] ): - # type: (...) -> Optional[Any] + # type: (...) -> Any for i, visitor in enumerate(self.visitors): if not self.skipping[i]: result = visitor.leave(node, key, parent, path, ancestors) @@ -242,17 +254,14 @@ def leave( return result elif self.skipping[i] == node: self.skipping[i] = REMOVE + return None class TypeInfoVisitor(Visitor): __slots__ = "visitor", "type_info" - def __init__( - self, - type_info, # type: TypeInfo - visitor, # type: Union[TestVisitor, ParallelVisitor, UsageVisitor] - ): - # type: (...) -> None + def __init__(self, type_info, visitor): + # type: (TypeInfo, Visitor) -> None self.type_info = type_info self.visitor = visitor diff --git a/graphql/type/definition.py b/graphql/type/definition.py index f7e0e7ba..2aba9352 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -84,14 +84,22 @@ def get_named_type(type): class GraphQLType(object): + pass + + +class GraphQLNamedType(GraphQLType): __slots__ = ("name",) + def __init__(self, name): + # type: (str) -> None + self.name = name + def __str__(self): # type: () -> str return self.name def is_same_type(self, other): - # type: (GraphQLObjectType) -> bool + # type: (Any) -> bool return self.__class__ is other.__class__ and self.name == other.name @@ -99,7 +107,7 @@ def none_func(x): None -class GraphQLScalarType(GraphQLType): +class GraphQLScalarType(GraphQLNamedType): """Scalar Type Definition The leaf values of any request and input values to arguments are @@ -120,12 +128,13 @@ def coerce_odd(value): def __init__( self, - name, - description=None, - serialize=None, - parse_value=None, - parse_literal=None, + name, # type: str + description=None, # type: Optional[str] + serialize=None, # type: Optional[Callable] + parse_value=None, # type: Optional[Callable] + parse_literal=None, # type: Optional[Callable] ): + # type: (...) -> None assert name, "Type must be named." assert_valid_name(name) self.name = name @@ -153,7 +162,7 @@ def __str__(self): return self.name -class GraphQLObjectType(GraphQLType): +class GraphQLObjectType(GraphQLNamedType): """Object Type Definition Almost all of the GraphQL types you define will be object types. @@ -325,8 +334,7 @@ class GraphQLArgument(object): def __init__( self, - # type: Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLScalarType] - type, + type, # type: Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType] default_value=None, # type: Optional[Any] description=None, # type: Optional[Any] out_name=None, # type: Optional[str] @@ -350,7 +358,7 @@ def __hash__(self): return id(self) -class GraphQLInterfaceType(GraphQLType): +class GraphQLInterfaceType(GraphQLNamedType): """Interface Type Definition When a field can return one of a heterogeneous set of types, a Interface type is used to describe what types are possible, @@ -392,7 +400,7 @@ def fields(self): return define_field_map(self, self._fields) -class GraphQLUnionType(GraphQLType): +class GraphQLUnionType(GraphQLNamedType): """Union Type Definition When a field can return one of a heterogeneous set of types, a Union type is used to describe what types are possible @@ -414,7 +422,7 @@ def resolve_type(self, value): def __init__( self, name, # type: str - types=None, # type: List[GraphQLObjectType] + types, # type: Union[Callable[[], List[GraphQLObjectType]], List[GraphQLObjectType]] resolve_type=None, # type: Optional[Callable] description=None, # type: Optional[Any] ): @@ -441,7 +449,7 @@ def types(self): # fmt: off def define_types( union_type, # type: GraphQLUnionType - types, # type: List[GraphQLObjectType] + types, # type: Union[Callable[[], List[GraphQLObjectType]], List[GraphQLObjectType]] ): # type: (...) -> List[GraphQLObjectType] # fmt: on @@ -471,7 +479,7 @@ def define_types( return types -class GraphQLEnumType(GraphQLType): +class GraphQLEnumType(GraphQLNamedType): """Enum Type Definition Some leaf values of requests and input values are Enums. GraphQL serializes Enum values as strings, @@ -506,7 +514,7 @@ def get_value(self, name): return self._name_lookup.get(name) def serialize(self, value): - # type: (str) -> str + # type: (str) -> Optional[str] if isinstance(value, collections.Hashable): enum_value = self._value_lookup.get(value) @@ -594,7 +602,7 @@ def __eq__(self, other): ) -class GraphQLInputObjectType(GraphQLType): +class GraphQLInputObjectType(GraphQLNamedType): """Input Object Type Definition An input object defines a structured collection of fields which may be @@ -627,7 +635,7 @@ def __init__(self, self.name = name self.description = description if container_type is None: - container_type = dict + container_type = dict # type: ignore assert callable(container_type), "container_type must be callable" self.container_type = container_type self._fields = fields @@ -643,9 +651,10 @@ def fields(self): def _define_field_map(self): # type: () -> OrderedDict - fields = self._fields - if callable(fields): - fields = fields() + if callable(self._fields): + fields = self._fields() + else: + fields = self._fields assert isinstance(fields, collections.Mapping) and len(fields) > 0, ( "{} fields must be a mapping (dict / OrderedDict) with field names as keys or a " @@ -665,8 +674,7 @@ class GraphQLInputObjectField(object): def __init__( self, - # type: Union[GraphQLInputObjectType, GraphQLScalarType] - type, + type, # type: Union[GraphQLInputObjectType, GraphQLScalarType] default_value=None, # type: Optional[Any] description=None, # type: Optional[Any] out_name=None, # type: str @@ -746,8 +754,7 @@ class RowType(GraphQLObjectType): def __init__( self, - # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType] - type, + type, # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType, GraphQLInputObjectType, GraphQLInterfaceType] ): # type: (...) -> None assert is_type(type) and not isinstance( diff --git a/graphql/type/tests/test_validation.py b/graphql/type/tests/test_validation.py index 0667ef91..4bead700 100644 --- a/graphql/type/tests/test_validation.py +++ b/graphql/type/tests/test_validation.py @@ -485,7 +485,7 @@ def test_accepts_a_union_type_with_aray_types(self): def test_rejects_a_union_without_types(self): with raises(AssertionError) as excinfo: schema_with_field_type( - GraphQLUnionType(name="SomeUnion", resolve_type=_none) + GraphQLUnionType(name="SomeUnion", resolve_type=_none, types=[]) ) assert str(excinfo.value) == "Must provide types for Union SomeUnion." diff --git a/graphql/utils/is_valid_literal_value.py b/graphql/utils/is_valid_literal_value.py index 47d7c13a..9b9f3b41 100644 --- a/graphql/utils/is_valid_literal_value.py +++ b/graphql/utils/is_valid_literal_value.py @@ -17,7 +17,7 @@ def is_valid_literal_value(type, value_ast): - # type: (Union[GraphQLInputObjectType, GraphQLScalarType], Any) -> List + # type: (Union[GraphQLInputObjectType, GraphQLScalarType, GraphQLNonNull], Any) -> List if isinstance(type, GraphQLNonNull): of_type = type.of_type if not value_ast: diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index 2e6b2bbc..b5a4952f 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -8,7 +8,6 @@ ) if False: # flake8: noqa - from ..type.typemap import GraphQLTypeMap from ..type.definition import ( GraphQLScalarType, GraphQLInterfaceType, @@ -33,7 +32,7 @@ def is_equal_type(type_a, type_b): def is_type_sub_type_of(schema, maybe_subtype, super_type): - # type: (GraphQLTypeMap, GraphQLScalarType, GraphQLScalarType) -> bool + # type: (GraphQLSchema, GraphQLScalarType, GraphQLScalarType) -> bool if maybe_subtype is super_type: return True @@ -67,7 +66,7 @@ def is_type_sub_type_of(schema, maybe_subtype, super_type): def do_types_overlap( schema, # type: GraphQLSchema - t1, # type: GraphQLObjectType + t1, # type: Union[GraphQLInterfaceType, GraphQLUnionType] t2, # type: Union[GraphQLInterfaceType, GraphQLUnionType] ): # type: (...) -> bool diff --git a/graphql/utils/type_from_ast.py b/graphql/utils/type_from_ast.py index c3a0d411..51c0bbd6 100644 --- a/graphql/utils/type_from_ast.py +++ b/graphql/utils/type_from_ast.py @@ -3,12 +3,13 @@ if False: # flake8: noqa from ..language.ast import ListType, NamedType, NonNullType + from ..type.definition import GraphQLNamedType from ..type.schema import GraphQLSchema from typing import Any, Union def type_from_ast(schema, input_type_ast): - # type: (GraphQLSchema, Union[ListType, NamedType, NonNullType]) -> Any + # type: (GraphQLSchema, Union[ListType, NamedType, NonNullType]) -> Union[GraphQLList, GraphQLNonNull, GraphQLNamedType] if isinstance(input_type_ast, ast.ListType): inner_type = type_from_ast(schema, input_type_ast.type) if inner_type: diff --git a/graphql/utils/type_info.py b/graphql/utils/type_info.py index 9f87f7c4..6a17de9b 100644 --- a/graphql/utils/type_info.py +++ b/graphql/utils/type_info.py @@ -16,8 +16,12 @@ from ..type.definition import ( GraphQLType, GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLObjectType, GraphQLField, GraphQLArgument, + GraphQLNonNull, + GraphQLScalarType, ) from ..type.directives import GraphQLDirective from ..language.ast import ( @@ -28,7 +32,7 @@ Argument, ObjectField, ) - from typing import Callable, Optional, Any, List + from typing import Callable, Optional, Any, List, Union def pop(lst): @@ -54,10 +58,10 @@ class TypeInfo(object): def __init__(self, schema, get_field_def_fn=get_field_def): # type: (GraphQLSchema, Callable) -> None self._schema = schema - self._type_stack = [] # type: List[GraphQLType] - self._parent_type_stack = [] # type: List[GraphQLType] - self._input_type_stack = [] # type: List[GraphQLInputObjectType] - self._field_def_stack = [] # type: List[GraphQLField] + self._type_stack = [] # type: List[Optional[GraphQLType]] + self._parent_type_stack = [] # type: List[Union[GraphQLInterfaceType, GraphQLObjectType, None]] + self._input_type_stack = [] # type: List[Optional[Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType, None]]] + self._field_def_stack = [] # type: List[Optional[GraphQLField]] self._directive = None # type: Optional[GraphQLDirective] self._argument = None # type: Optional[GraphQLArgument] self._get_field_def_fn = get_field_def_fn @@ -69,13 +73,13 @@ def get_type(self): return None def get_parent_type(self): - # type: () -> Optional[GraphQLType] + # type: () -> Union[GraphQLInterfaceType, GraphQLObjectType, None] if self._parent_type_stack: return self._parent_type_stack[-1] return None def get_input_type(self): - # type: () -> Optional[GraphQLInputObjectType] + # type: () -> Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType, None] if self._input_type_stack: return self._input_type_stack[-1] return None @@ -114,7 +118,7 @@ def enter_SelectionSet(self, node): composite_type = None if is_composite_type(named_type): composite_type = named_type - self._parent_type_stack.append(composite_type) + self._parent_type_stack.append(composite_type) # type: ignore def enter_Field(self, node): # type: (Field) -> None diff --git a/graphql/validation/rules/__init__.py b/graphql/validation/rules/__init__.py index 8ed07e5b..329dabf8 100644 --- a/graphql/validation/rules/__init__.py +++ b/graphql/validation/rules/__init__.py @@ -23,6 +23,11 @@ from .variables_are_input_types import VariablesAreInputTypes from .variables_in_allowed_position import VariablesInAllowedPosition +if False: # flake8: noqa + from typing import List, Type + from ...language.visitor import Visitor + + specified_rules = [ UniqueOperationNames, LoneAnonymousOperation, @@ -48,7 +53,7 @@ OverlappingFieldsCanBeMerged, UniqueInputFieldNames, UniqueVariableNames, -] +] # type: List[Type[Visitor]] __all__ = [ "ArgumentsOfCorrectType", diff --git a/graphql/validation/rules/fields_on_correct_type.py b/graphql/validation/rules/fields_on_correct_type.py index f6446471..03a68984 100644 --- a/graphql/validation/rules/fields_on_correct_type.py +++ b/graphql/validation/rules/fields_on_correct_type.py @@ -13,7 +13,7 @@ try: # Python 2 - from itertools import izip + from itertools import izip # type: ignore except ImportError: # Python 3 izip = zip diff --git a/graphql/validation/rules/no_fragment_cycles.py b/graphql/validation/rules/no_fragment_cycles.py index 6dfdf46b..f9a85a1f 100644 --- a/graphql/validation/rules/no_fragment_cycles.py +++ b/graphql/validation/rules/no_fragment_cycles.py @@ -3,8 +3,9 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition - from typing import List, Union + from ...language.ast import Document, OperationDefinition, FragmentSpread + from ...error import GraphQLError + from typing import List, Union, Dict, Set class NoFragmentCycles(ValidationRule): @@ -13,10 +14,10 @@ class NoFragmentCycles(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(NoFragmentCycles, self).__init__(context) - self.errors = [] - self.visited_frags = set() - self.spread_path = [] - self.spread_path_index_by_name = {} + self.errors = [] # type: List[GraphQLError] + self.visited_frags = set() # type: Set[str] + self.spread_path = [] # type: List[FragmentSpread] + self.spread_path_index_by_name = {} # type: Dict[str, int] def enter_OperationDefinition( self, diff --git a/graphql/validation/rules/no_undefined_variables.py b/graphql/validation/rules/no_undefined_variables.py index 77f3eb6e..8a9ed3d3 100644 --- a/graphql/validation/rules/no_undefined_variables.py +++ b/graphql/validation/rules/no_undefined_variables.py @@ -4,7 +4,7 @@ if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition - from typing import List, Union + from typing import List, Union, Set class NoUndefinedVariables(ValidationRule): @@ -12,7 +12,7 @@ class NoUndefinedVariables(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None - self.defined_variable_names = set() + self.defined_variable_names = set() # type: Set[str] super(NoUndefinedVariables, self).__init__(context) @staticmethod diff --git a/graphql/validation/rules/no_unused_fragments.py b/graphql/validation/rules/no_unused_fragments.py index 76f8f35a..e8d2dfc1 100644 --- a/graphql/validation/rules/no_unused_fragments.py +++ b/graphql/validation/rules/no_unused_fragments.py @@ -3,7 +3,7 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition + from ...language.ast import Document, OperationDefinition, FragmentDefinition from typing import List, Union, Any, Optional @@ -18,8 +18,8 @@ class NoUnusedFragments(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(NoUnusedFragments, self).__init__(context) - self.operation_definitions = [] - self.fragment_definitions = [] + self.operation_definitions = [] # type: List[OperationDefinition] + self.fragment_definitions = [] # type: List[FragmentDefinition] def enter_OperationDefinition( self, diff --git a/graphql/validation/rules/no_unused_variables.py b/graphql/validation/rules/no_unused_variables.py index baca2daa..65b50337 100644 --- a/graphql/validation/rules/no_unused_variables.py +++ b/graphql/validation/rules/no_unused_variables.py @@ -3,7 +3,7 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition + from ...language.ast import Document, OperationDefinition, VariableDefinition from typing import List, Union @@ -12,7 +12,7 @@ class NoUnusedVariables(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None - self.variable_definitions = [] + self.variable_definitions = [] # type: List[VariableDefinition] super(NoUnusedVariables, self).__init__(context) def enter_OperationDefinition( diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index 834acf50..e427be8c 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -19,10 +19,17 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import OperationDefinition, Field, InlineFragment, SelectionSet + from ...language.ast import ( + Node, + OperationDefinition, + Field, + Argument, + InlineFragment, + SelectionSet, + ) from ...type.definition import GraphQLUnionType, GraphQLField, GraphQLScalarType from ...pyutils.pair_set import PairSet - from typing import List, Union, Any, Optional, Dict + from typing import List, Union, Any, Optional, Dict, Tuple class OverlappingFieldsCanBeMerged(ValidationRule): @@ -39,7 +46,7 @@ def __init__(self, context): # A cache for the "field map" and list of fragment names found in any given # selection set. Selection sets may be asked for this information multiple # times, so this improves the performance of this validator. - self._cached_fields_and_fragment_names = {} + self._cached_fields_and_fragment_names = {} # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] def leave_SelectionSet( self, @@ -157,18 +164,17 @@ def reason_message(cls, reason): def _find_conflicts_within_selection_set( context, # type: ValidationContext - cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] compared_fragments, # type: PairSet - parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, None] selection_set, # type: SelectionSet ): - # type: (...) -> List + # type: (...) -> List[Tuple[Tuple[str, str], List[Node], List[Node]]] """Find all conflicts found "within" a selection set, including those found via spreading in fragments. Called when visiting each SelectionSet in the GraphQL Document. """ - conflicts = [] - + conflicts = [] # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] field_map, fragment_names = _get_fields_and_fragments_names( context, cached_fields_and_fragment_names, parent_type, selection_set ) @@ -215,13 +221,13 @@ def _find_conflicts_within_selection_set( def _collect_conflicts_between_fields_and_fragment( - context, - conflicts, - cached_fields_and_fragment_names, - compared_fragments, - are_mutually_exclusive, - field_map, - fragment_name, + context, # type: ValidationContext + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + compared_fragments, # type: PairSet + are_mutually_exclusive, # type: bool + field_map, # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] + fragment_name, # type: str ): fragment = context.get_fragment(fragment_name) @@ -262,13 +268,13 @@ def _collect_conflicts_between_fields_and_fragment( # Collect all conflicts found between two fragments, including via spreading in # any nested fragments def _collect_conflicts_between_fragments( - context, - conflicts, - cached_fields_and_fragment_names, - compared_fragments, - are_mutually_exclusive, - fragment_name1, - fragment_name2, + context, # type: ValidationContext + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + compared_fragments, # type: PairSet + are_mutually_exclusive, # type: bool + fragment_name1, # type: str + fragment_name2, # type: str ): fragment1 = context.get_fragment(fragment_name1) @@ -333,24 +339,27 @@ def _collect_conflicts_between_fragments( fragment_name2, ) + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + are_mutually_exclusive, # type: bool + def _find_conflicts_between_sub_selection_sets( - context, - cached_fields_and_fragment_names, - compared_fragments, - are_mutually_exclusive, - parent_type1, - selection_set1, - parent_type2, - selection_set2, + context, # type: ValidationContext + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + compared_fragments, # type: PairSet + are_mutually_exclusive, # type: bool + parent_type1, # type: Union[GraphQLInterfaceType, GraphQLObjectType, None] + selection_set1, # type: SelectionSet + parent_type2, # type: Union[GraphQLInterfaceType, GraphQLObjectType, None] + selection_set2, # type: SelectionSet ): + # type: (...) -> List[Tuple[Tuple[str, str], List[Node], List[Node]]] """Find all conflicts found between two selection sets. Includes those found via spreading in fragments. Called when determining if conflicts exist between the sub-fields of two overlapping fields. """ - - conflicts = [] + conflicts = [] # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] field_map1, fragment_names1 = _get_fields_and_fragments_names( context, cached_fields_and_fragment_names, parent_type1, selection_set1 @@ -417,10 +426,10 @@ def _find_conflicts_between_sub_selection_sets( def _collect_conflicts_within( context, # type: ValidationContext - conflicts, # type: List - cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] compared_fragments, # type: PairSet - field_map, # type: OrderedDict + field_map, # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] ): # type: (...) -> None """Collect all Conflicts "within" one collection of fields.""" @@ -450,14 +459,15 @@ def _collect_conflicts_within( def _collect_conflicts_between( - context, - conflicts, - cached_fields_and_fragment_names, - compared_fragments, - parent_fields_are_mutually_exclusive, - field_map1, - field_map2, + context, # type: ValidationContext + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + compared_fragments, # type: PairSet + parent_fields_are_mutually_exclusive, # type: bool + field_map1, # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] + field_map2, # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] ): + # type: (...) -> None """Collect all Conflicts between two collections of fields. This is similar to, but different from the `collect_conflicts_within` function above. This check assumes that @@ -491,14 +501,14 @@ def _collect_conflicts_between( def _find_conflict( context, # type: ValidationContext - cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] compared_fragments, # type: PairSet parent_fields_are_mutually_exclusive, # type: bool response_name, # type: str - field1, # type: List[Union[Field, GraphQLField, GraphQLObjectType]] - field2, # type: List[Union[Field, GraphQLField, GraphQLObjectType]] + field1, # type: Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField] + field2, # type: Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField] ): - # type: (...) -> Optional[Any] + # type: (...) -> Optional[Tuple[Tuple[str, str], List[Node], List[Node]]] """Determines if there is a conflict between two particular fields.""" parent_type1, ast1, def1 = field1 parent_type2, ast2, def2 = field2 @@ -555,44 +565,51 @@ def _find_conflict( selection_set2 = ast2.selection_set if selection_set1 and selection_set2: - conflicts = _find_conflicts_between_sub_selection_sets( + conflicts = _find_conflicts_between_sub_selection_sets( # type: ignore context, cached_fields_and_fragment_names, compared_fragments, are_mutually_exclusive, - get_named_type(type1), + get_named_type(type1), # type: ignore selection_set1, - get_named_type(type2), + get_named_type(type2), # type: ignore selection_set2, ) return _subfield_conflicts(conflicts, response_name, ast1, ast2) + return None + def _get_fields_and_fragments_names( context, # type: ValidationContext - cached_fields_and_fragment_names, # type: Dict[SelectionSet, List[Union[List, OrderedDict]]] - parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, None] selection_set, # type: SelectionSet ): - # type: (...) -> List[Union[List, OrderedDict]] + # type: (...) -> Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]] cached = cached_fields_and_fragment_names.get(selection_set) if not cached: - ast_and_defs = OrderedDict() - fragment_names = OrderedDict() + ast_and_defs = ( + OrderedDict() + ) # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] + fragment_names = OrderedDict() # type: Dict[str, bool] _collect_fields_and_fragment_names( context, parent_type, selection_set, ast_and_defs, fragment_names ) - cached = [ast_and_defs, list(fragment_names.keys())] + cached = (ast_and_defs, list(fragment_names.keys())) cached_fields_and_fragment_names[selection_set] = cached return cached def _get_referenced_fields_and_fragment_names( - context, cached_fields_and_fragment_names, fragment + context, # ValidationContext + cached_fields_and_fragment_names, # type: Dict[SelectionSet, Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]]] + fragment, # type: InlineFragment ): + # type: (...) -> Tuple[Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]], List[str]] """Given a reference to a fragment, return the represented collection of fields as well as a list of nested fragment names referenced via fragment spreads.""" @@ -602,7 +619,9 @@ def _get_referenced_fields_and_fragment_names( if cached: return cached - fragment_type = type_from_ast(context.get_schema(), fragment.type_condition) + fragment_type = type_from_ast( # type: ignore + context.get_schema(), fragment.type_condition + ) return _get_fields_and_fragments_names( context, cached_fields_and_fragment_names, fragment_type, fragment.selection_set @@ -611,10 +630,10 @@ def _get_referenced_fields_and_fragment_names( def _collect_fields_and_fragment_names( context, # type: ValidationContext - parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + parent_type, # type: Union[GraphQLInterfaceType, GraphQLObjectType, None] selection_set, # type: SelectionSet - ast_and_defs, # type: OrderedDict - fragment_names, # type: OrderedDict + ast_and_defs, # type: Dict[str, List[Tuple[Union[GraphQLInterfaceType, GraphQLObjectType, None], Field, GraphQLField]]] + fragment_names, # type: Dict[str, bool] ): # type: (...) -> None @@ -629,16 +648,16 @@ def _collect_fields_and_fragment_names( response_name = selection.alias.value if selection.alias else field_name if not ast_and_defs.get(response_name): - ast_and_defs[response_name] = [] + ast_and_defs[response_name] = [] # type: ignore - ast_and_defs[response_name].append([parent_type, selection, field_def]) + ast_and_defs[response_name].append((parent_type, selection, field_def)) elif isinstance(selection, ast.FragmentSpread): fragment_names[selection.name.value] = True elif isinstance(selection, ast.InlineFragment): type_condition = selection.type_condition if type_condition: - inline_fragment_type = type_from_ast( + inline_fragment_type = type_from_ast( # type: ignore context.get_schema(), selection.type_condition ) else: @@ -653,14 +672,21 @@ def _collect_fields_and_fragment_names( ) -def _subfield_conflicts(conflicts, response_name, ast1, ast2): +def _subfield_conflicts( + conflicts, # type: List[Tuple[Tuple[str, str], List[Node], List[Node]]] + response_name, # type: str + ast1, # type: Node + ast2, # type: Node +): + # type: (...) -> Optional[Tuple[Tuple[str, str], List[Node], List[Node]]] """Given a series of Conflicts which occurred between two sub-fields, generate a single Conflict.""" if conflicts: return ( (response_name, [conflict[0] for conflict in conflicts]), tuple(itertools.chain([ast1], *[conflict[1] for conflict in conflicts])), tuple(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])), - ) + ) # type: ignore + return None def do_types_conflict(type1, type2): @@ -692,15 +718,27 @@ def do_types_conflict(type1, type2): def _same_value(value1, value2): - return (not value1 and not value2) or print_ast(value1) == print_ast(value2) + # type: (Optional[Node], Optional[Node]) -> bool + if not value1 and not value2: + return True + if not value1 or not value2: + return False + return print_ast(value1) == print_ast(value2) def _same_arguments(arguments1, arguments2): + # type: (Optional[List[Argument]], Optional[List[Argument]]) -> bool # Check to see if they are empty arguments or nones. If they are, we can # bail out early. - if not (arguments1 or arguments2): + if not arguments1 and not arguments2: return True + if not arguments1: + return False + + if not arguments2: + return False + if len(arguments1) != len(arguments2): return False diff --git a/graphql/validation/rules/possible_fragment_spreads.py b/graphql/validation/rules/possible_fragment_spreads.py index d6b916c0..d8bf329c 100644 --- a/graphql/validation/rules/possible_fragment_spreads.py +++ b/graphql/validation/rules/possible_fragment_spreads.py @@ -4,7 +4,7 @@ from .base import ValidationRule if False: # flake8: noqa - from ..language.ast import Field, InlineFragment + from ...language.ast import Field, InlineFragment from typing import Any, List, Union @@ -13,7 +13,7 @@ def enter_InlineFragment( self, node, # type: InlineFragment key, # type: int - parent, # type: Union[List[Union[Field, InlineFragment]], List[InlineFragment]] + parent, # type: List[Union[Field, InlineFragment]] path, # type: List[Union[int, str]] ancestors, # type: List[Any] ): @@ -24,7 +24,7 @@ def enter_InlineFragment( if ( frag_type and parent_type - and not do_types_overlap(schema, frag_type, parent_type) + and not do_types_overlap(schema, frag_type, parent_type) # type: ignore ): self.context.report_error( GraphQLError( diff --git a/graphql/validation/rules/provided_non_null_arguments.py b/graphql/validation/rules/provided_non_null_arguments.py index 1d727a0d..5558fd6d 100644 --- a/graphql/validation/rules/provided_non_null_arguments.py +++ b/graphql/validation/rules/provided_non_null_arguments.py @@ -35,6 +35,7 @@ def leave_Field( [node], ) ) + return None def leave_Directive(self, node, key, parent, path, ancestors): directive_def = self.context.get_directive() diff --git a/graphql/validation/rules/unique_argument_names.py b/graphql/validation/rules/unique_argument_names.py index 60dfb2e6..e59a5f85 100644 --- a/graphql/validation/rules/unique_argument_names.py +++ b/graphql/validation/rules/unique_argument_names.py @@ -3,8 +3,8 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Field, InlineFragment, Argument - from typing import Any, List, Union + from ...language.ast import Field, InlineFragment, Argument, Name + from typing import Any, List, Union, Dict class UniqueArgumentNames(ValidationRule): @@ -13,7 +13,7 @@ class UniqueArgumentNames(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(UniqueArgumentNames, self).__init__(context) - self.known_arg_names = {} + self.known_arg_names = {} # type: Dict[str, Name] def enter_Field( self, diff --git a/graphql/validation/rules/unique_fragment_names.py b/graphql/validation/rules/unique_fragment_names.py index fe2141e7..cc67f8a4 100644 --- a/graphql/validation/rules/unique_fragment_names.py +++ b/graphql/validation/rules/unique_fragment_names.py @@ -3,8 +3,8 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition - from typing import List, Union + from ...language.ast import Document, OperationDefinition, Name + from typing import List, Union, Dict class UniqueFragmentNames(ValidationRule): @@ -13,7 +13,7 @@ class UniqueFragmentNames(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(UniqueFragmentNames, self).__init__(context) - self.known_fragment_names = {} + self.known_fragment_names = {} # type: Dict[str, Name] def enter_OperationDefinition( self, diff --git a/graphql/validation/rules/unique_input_field_names.py b/graphql/validation/rules/unique_input_field_names.py index 78a89a50..dde35ec9 100644 --- a/graphql/validation/rules/unique_input_field_names.py +++ b/graphql/validation/rules/unique_input_field_names.py @@ -3,8 +3,8 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Argument, ObjectValue, ObjectField - from typing import Any, List, Union + from ...language.ast import Argument, ObjectValue, ObjectField, Name + from typing import Any, List, Union, Dict class UniqueInputFieldNames(ValidationRule): @@ -13,8 +13,8 @@ class UniqueInputFieldNames(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(UniqueInputFieldNames, self).__init__(context) - self.known_names = {} - self.known_names_stack = [] + self.known_names = {} # type: Dict[str, Name] + self.known_names_stack = [] # type: List[Dict[str, Name]] def enter_ObjectValue( self, diff --git a/graphql/validation/rules/unique_operation_names.py b/graphql/validation/rules/unique_operation_names.py index 6bfe70d5..d44d6ee2 100644 --- a/graphql/validation/rules/unique_operation_names.py +++ b/graphql/validation/rules/unique_operation_names.py @@ -3,8 +3,8 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition - from typing import Any, List, Optional, Union + from ...language.ast import Document, OperationDefinition, Name + from typing import Any, List, Optional, Union, Dict class UniqueOperationNames(ValidationRule): @@ -13,7 +13,7 @@ class UniqueOperationNames(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(UniqueOperationNames, self).__init__(context) - self.known_operation_names = {} + self.known_operation_names = {} # type: Dict[str, Name] def enter_OperationDefinition( self, @@ -26,7 +26,7 @@ def enter_OperationDefinition( # type: (...) -> Optional[Any] operation_name = node.name if not operation_name: - return + return None if operation_name.value in self.known_operation_names: self.context.report_error( diff --git a/graphql/validation/rules/unique_variable_names.py b/graphql/validation/rules/unique_variable_names.py index 2d966152..425d43f4 100644 --- a/graphql/validation/rules/unique_variable_names.py +++ b/graphql/validation/rules/unique_variable_names.py @@ -4,7 +4,7 @@ if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition - from typing import List, Union + from typing import List, Union, Dict class UniqueVariableNames(ValidationRule): @@ -13,7 +13,7 @@ class UniqueVariableNames(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(UniqueVariableNames, self).__init__(context) - self.known_variable_names = {} + self.known_variable_names = {} # type: Dict[str, str] def enter_OperationDefinition( self, diff --git a/graphql/validation/rules/variables_in_allowed_position.py b/graphql/validation/rules/variables_in_allowed_position.py index 8bcf1c52..5bdd5da5 100644 --- a/graphql/validation/rules/variables_in_allowed_position.py +++ b/graphql/validation/rules/variables_in_allowed_position.py @@ -6,8 +6,8 @@ if False: # flake8: noqa from ..validation import ValidationContext - from ...language.ast import Document, OperationDefinition - from typing import List, Union + from ...language.ast import Document, OperationDefinition, VariableDefinition + from typing import List, Union, Dict, Any class VariablesInAllowedPosition(ValidationRule): @@ -16,7 +16,7 @@ class VariablesInAllowedPosition(ValidationRule): def __init__(self, context): # type: (ValidationContext) -> None super(VariablesInAllowedPosition, self).__init__(context) - self.var_def_map = {} + self.var_def_map = {} # type: Dict[str, VariableDefinition] def enter_OperationDefinition( self, @@ -63,7 +63,15 @@ def leave_OperationDefinition( ) ) - def enter_VariableDefinition(self, node, key, parent, path, ancestors): + def enter_VariableDefinition( + self, + node, # type: VariableDefinition + key, # type: int + parent, # type: Any + path, # type: List[str] + ancestors, # type: List[Document] + ): + self.var_def_map[node.variable.name.value] = node @staticmethod diff --git a/graphql/validation/validation.py b/graphql/validation/validation.py index b708f6a3..ac890516 100644 --- a/graphql/validation/validation.py +++ b/graphql/validation/validation.py @@ -5,10 +5,11 @@ from .rules import specified_rules if False: # flake8: noqa - from typing import List, Union - from ..language.ast import Document, OperationDefinition, SelectionSet - from ..language.visitor_meta import VisitorMeta + from typing import List, Union, Optional, Dict, Set, Any, Type + from ..language.ast import Document, OperationDefinition, SelectionSet, Node from ..type.schema import GraphQLSchema + from ..error import GraphQLError + from .rules.base import ValidationRule from ..type.definition import ( GraphQLList, GraphQLObjectType, @@ -17,11 +18,13 @@ GraphQLUnionType, GraphQLField, GraphQLArgument, + GraphQLType, + GraphQLInputObjectType, ) def validate(schema, ast, rules=specified_rules): - # type: (GraphQLSchema, Document, List[VisitorMeta]) -> List + # type: (GraphQLSchema, Document, List[Type[ValidationRule]]) -> List assert schema, "Must provide schema" assert ast, "Must provide document" assert isinstance(schema, GraphQLSchema) @@ -30,7 +33,7 @@ def validate(schema, ast, rules=specified_rules): def visit_using_rules(schema, type_info, ast, rules): - # type: (GraphQLSchema, TypeInfo, Document, List[VisitorMeta]) -> List + # type: (GraphQLSchema, TypeInfo, Document, List[Type[ValidationRule]]) -> List context = ValidationContext(schema, ast, type_info) visitors = [rule(context) for rule in rules] visit(ast, TypeInfoVisitor(type_info, ParallelVisitor(visitors))) @@ -49,7 +52,7 @@ class UsageVisitor(Visitor): __slots__ = "usages", "type_info" def __init__(self, usages, type_info): - # type: (List, TypeInfo) -> None + # type: (List[VariableUsage], TypeInfo) -> None self.usages = usages self.type_info = type_info @@ -79,12 +82,12 @@ def __init__(self, schema, ast, type_info): self._schema = schema self._ast = ast self._type_info = type_info - self._errors = [] - self._fragments = None - self._fragment_spreads = {} - self._recursively_referenced_fragments = {} - self._variable_usages = {} - self._recursive_variable_usages = {} + self._errors = [] # type: List[GraphQLError] + self._fragments = None # type: Optional[Dict[str, FragmentDefinition]] + self._fragment_spreads = {} # type: Dict[Node, List[FragmentSpread]] + self._recursively_referenced_fragments = {} # type: Dict[OperationDefinition, List[FragmentSpread]] + self._variable_usages = {} # type: Dict[Node, List[VariableUsage]] + self._recursive_variable_usages = {} # type: Dict[OperationDefinition, List[VariableUsage]] def report_error(self, error): self._errors.append(error) @@ -98,7 +101,7 @@ def get_schema(self): return self._schema def get_variable_usages(self, node): - # type: (OperationDefinition) -> List + # type: (OperationDefinition) -> List[VariableUsage] usages = self._variable_usages.get(node) if usages is None: usages = [] @@ -109,7 +112,7 @@ def get_variable_usages(self, node): return usages def get_recursive_variable_usages(self, operation): - # type: (OperationDefinition) -> List + # type: (OperationDefinition) -> List[VariableUsage] assert isinstance(operation, OperationDefinition) usages = self._recursive_variable_usages.get(operation) if usages is None: @@ -127,7 +130,7 @@ def get_recursively_referenced_fragments(self, operation): fragments = self._recursively_referenced_fragments.get(operation) if not fragments: fragments = [] - collected_names = set() + collected_names = set() # type: Set[str] nodes_to_visit = [operation.selection_set] while nodes_to_visit: node = nodes_to_visit.pop() @@ -144,7 +147,7 @@ def get_recursively_referenced_fragments(self, operation): return fragments def get_fragment_spreads(self, node): - # type: (SelectionSet) -> List + # type: (SelectionSet) -> List[FragmentSpread] spreads = self._fragment_spreads.get(node) if not spreads: spreads = [] @@ -173,23 +176,25 @@ def get_fragment(self, name): return fragments.get(name) def get_type(self): - # type: () -> Union[GraphQLList, GraphQLObjectType, GraphQLScalarType] + # type: () -> Optional[GraphQLType] return self._type_info.get_type() def get_parent_type(self): - # type: () -> Union[GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType] + # type: () -> Union[GraphQLInterfaceType, GraphQLObjectType, None] return self._type_info.get_parent_type() def get_input_type(self): + # type: () -> Optional[GraphQLInputObjectType] return self._type_info.get_input_type() def get_field_def(self): - # type: () -> GraphQLField + # type: () -> Optional[GraphQLField] return self._type_info.get_field_def() def get_directive(self): + # type: () -> Optional[Any] return self._type_info.get_directive() def get_argument(self): - # type: () -> GraphQLArgument + # type: () -> Optional[GraphQLArgument] return self._type_info.get_argument() From 6a3f9004362b51336e082e08b3b4a180c6a325c2 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 29 Jun 2018 14:55:21 -0700 Subject: [PATCH 09/12] Improved typing --- graphql/execution/executor.py | 85 ++++++++++--------- graphql/execution/executors/asyncio.py | 8 +- graphql/execution/executors/thread.py | 7 +- graphql/execution/executors/utils.py | 4 +- graphql/execution/middleware.py | 23 ++--- graphql/execution/utils.py | 26 +++--- graphql/execution/values.py | 31 +++---- graphql/language/printer.py | 72 ++++++++-------- graphql/language/visitor.py | 4 +- graphql/type/introspection.py | 65 +++++++------- graphql/type/schema.py | 29 ++++--- graphql/type/tests/test_schema.py | 2 +- graphql/type/typemap.py | 50 +++++------ graphql/utils/is_valid_literal_value.py | 4 +- graphql/utils/type_comparators.py | 3 +- graphql/utils/type_from_ast.py | 27 +++--- graphql/validation/rules/__init__.py | 4 +- .../rules/overlapping_fields_can_be_merged.py | 10 +-- graphql/validation/validation.py | 2 +- 19 files changed, 235 insertions(+), 221 deletions(-) diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index f23f59c4..d4043612 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -47,7 +47,9 @@ def subscribe(*args, **kwargs): # type: (*Any, **Any) -> Union[ExecutionResult, Observable] allow_subscriptions = kwargs.pop("allow_subscriptions", True) - return execute(*args, allow_subscriptions=allow_subscriptions, **kwargs) + return execute( # type: ignore + *args, allow_subscriptions=allow_subscriptions, **kwargs + ) def execute( @@ -116,7 +118,7 @@ def execute( allow_subscriptions, ) - def executor(v): + def promise_executor(v): # type: (Optional[Any]) -> Union[OrderedDict, Promise, Observable] return execute_operation(exe_context, exe_context.operation, root) @@ -135,7 +137,9 @@ def on_resolve(data): return ExecutionResult(data=data, errors=exe_context.errors) - promise = Promise.resolve(None).then(executor).catch(on_rejected).then(on_resolve) + promise = ( + Promise.resolve(None).then(promise_executor).catch(on_rejected).then(on_resolve) + ) if not return_promise: exe_context.executor.wait_until_finished() @@ -151,7 +155,7 @@ def on_resolve(data): def execute_operation( exe_context, # type: ExecutionContext operation, # type: OperationDefinition - root_value, # type: Union[None, Data, type] + root_value, # type: Any ): # type: (...) -> Union[OrderedDict, Promise] type = get_operation_root_type(exe_context.schema, operation) @@ -224,7 +228,7 @@ def execute_fields( parent_type, # type: GraphQLObjectType source_value, # type: Any fields, # type: DefaultOrderedDict - path, # type: Union[List[Union[int, str]], List[str]] + path, # type: List[Union[int, str]] info, # type: Optional[ResolveInfo] ): # type: (...) -> Union[OrderedDict, Promise] @@ -257,39 +261,43 @@ def execute_fields( def subscribe_fields( exe_context, # type: ExecutionContext parent_type, # type: GraphQLObjectType - source_value, # type: Union[None, Data, type] + source_value, # type: Any fields, # type: DefaultOrderedDict ): # type: (...) -> Observable - exe_context = SubscriberExecutionContext(exe_context) + subscriber_exe_context = SubscriberExecutionContext(exe_context) def on_error(error): - exe_context.report_error(error) + subscriber_exe_context.report_error(error) def map_result( data # type: Union[Dict[str, None], Dict[str, OrderedDict], Dict[str, str]] ): # type: (...) -> ExecutionResult - if exe_context.errors: - result = ExecutionResult(data=data, errors=exe_context.errors) + if subscriber_exe_context.errors: + result = ExecutionResult(data=data, errors=subscriber_exe_context.errors) else: result = ExecutionResult(data=data) - exe_context.reset() + subscriber_exe_context.reset() return result - observables = [] + observables = [] # type: List[Observable] # assert len(fields) == 1, "Can only subscribe one element at a time." for response_name, field_asts in fields.items(): result = subscribe_field( - exe_context, parent_type, source_value, field_asts, [response_name] + subscriber_exe_context, + parent_type, + source_value, + field_asts, + [response_name], ) if result is Undefined: continue def catch_error(error): - exe_context.errors.append(error) + subscriber_exe_context.errors.append(error) return Observable.just(None) # Map observable results @@ -305,10 +313,10 @@ def catch_error(error): def resolve_field( exe_context, # type: ExecutionContext parent_type, # type: GraphQLObjectType - source, # type: Union[None, Cat, Dog] + source, # type: Any field_asts, # type: List[Field] parent_info, # type: Optional[ResolveInfo] - field_path, # type: Union[List[Union[int, str]], List[str]] + field_path, # type: List[Union[int, str]] ): # type: (...) -> Any field_ast = field_asts[0] @@ -360,7 +368,7 @@ def resolve_field( def subscribe_field( exe_context, # type: SubscriberExecutionContext parent_type, # type: GraphQLObjectType - source, # type: Union[None, Data, type] + source, # type: Any field_asts, # type: List[Field] path, # type: List[str] ): @@ -430,12 +438,12 @@ def subscribe_field( def resolve_or_error( resolve_fn, # type: Callable - source, # type: Union[None, Cat, Dog] + source, # type: Any info, # type: ResolveInfo args, # type: Dict - executor, # type: Union[BaseExecutor, SyncExecutor] + executor, # type: Any ): - # type: (...) -> Union[List[Union[Cat, Dog]], bool, str] + # type: (...) -> Any try: return executor.execute(resolve_fn, source, info, **args) except Exception as e: @@ -444,7 +452,7 @@ def resolve_or_error( info.parent_type.name, info.field_name ) ) - e.stack = sys.exc_info()[2] + e.stack = sys.exc_info()[2] # type: ignore return e @@ -453,10 +461,10 @@ def complete_value_catching_error( return_type, # type: Any field_asts, # type: List[Field] info, # type: ResolveInfo - path, # type: Union[List[Union[int, str]], List[str]] + path, # type: List[Union[int, str]] result, # type: Any ): - # type: (...) -> Union[bool, str] + # type: (...) -> Any # If the field type is non-nullable, then it is resolved without any # protection from errors. if isinstance(return_type, GraphQLNonNull): @@ -472,7 +480,7 @@ def complete_value_catching_error( def handle_error(error): # type: (Union[GraphQLError, GraphQLLocatedError]) -> Optional[Any] - traceback = completed._traceback + traceback = completed._traceback # type: ignore exe_context.report_error(error, traceback) return None @@ -490,10 +498,10 @@ def complete_value( return_type, # type: Any field_asts, # type: List[Field] info, # type: ResolveInfo - path, # type: Union[List[Union[int, str]], List[str]] + path, # type: List[Union[int, str]] result, # type: Any ): - # type: (...) -> Union[bool, str] + # type: (...) -> Any """ Implements the instructions for completeValue as defined in the "Field entries" section of the spec. @@ -566,10 +574,10 @@ def complete_list_value( return_type, # type: GraphQLList field_asts, # type: List[Field] info, # type: ResolveInfo - path, # type: List[str] + path, # type: List[Union[int, str]] result, # type: Any ): - # type: (...) -> Any + # type: (...) -> List[Any] """ Complete a list value by completing each item in the list with the inner type """ @@ -597,10 +605,10 @@ def complete_list_value( def complete_leaf_value( return_type, # type: Union[GraphQLEnumType, GraphQLScalarType] - path, # type: Union[List[Union[int, str]], List[str]] - result, # type: Union[int, str] + path, # type: List[Union[int, str]] + result, # type: Any ): - # type: (...) -> Union[int, str] + # type: (...) -> Union[int, str, float, bool] """ Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible. """ @@ -625,12 +633,12 @@ def complete_abstract_value( path, # type: List[Union[int, str]] result, # type: Any ): - # type: (...) -> OrderedDict + # type: (...) -> Dict[str, Any] """ Complete an value of an abstract type by determining the runtime type of that value, then completing based on that type. """ - runtime_type = None + runtime_type = None # type: Union[str, GraphQLObjectType, None] # Field type must be Object, Interface or Union and expect sub-selections. if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)): @@ -640,7 +648,7 @@ def complete_abstract_value( runtime_type = get_default_resolve_type_fn(result, info, return_type) if isinstance(runtime_type, string_types): - runtime_type = info.schema.get_type(runtime_type) + runtime_type = info.schema.get_type(runtime_type) # type: ignore if not isinstance(runtime_type, GraphQLObjectType): raise GraphQLError( @@ -671,11 +679,12 @@ def get_default_resolve_type_fn( info, # type: ResolveInfo abstract_type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] ): - # type: (...) -> GraphQLObjectType + # type: (...) -> Optional[GraphQLObjectType] possible_types = info.schema.get_possible_types(abstract_type) for type in possible_types: if callable(type.is_type_of) and type.is_type_of(value, info): return type + return None def complete_object_value( @@ -683,10 +692,10 @@ def complete_object_value( return_type, # type: GraphQLObjectType field_asts, # type: List[Field] info, # type: ResolveInfo - path, # type: Union[List[Union[int, str]], List[str]] + path, # type: List[Union[int, str]] result, # type: Any ): - # type: (...) -> Union[OrderedDict, Promise] + # type: (...) -> Dict[str, Any] """ Complete an Object value by evaluating all sub-selections. """ @@ -708,7 +717,7 @@ def complete_nonnull_value( return_type, # type: GraphQLNonNull field_asts, # type: List[Field] info, # type: ResolveInfo - path, # type: Union[List[Union[int, str]], List[str]] + path, # type: List[Union[int, str]] result, # type: Any ): # type: (...) -> Any diff --git a/graphql/execution/executors/asyncio.py b/graphql/execution/executors/asyncio.py index 27637c23..8dc183eb 100644 --- a/graphql/execution/executors/asyncio.py +++ b/graphql/execution/executors/asyncio.py @@ -6,13 +6,13 @@ if False: # flake8: noqa from asyncio.unix_events import _UnixSelectorEventLoop - from typing import Optional, Any, Callable + from typing import Optional, Any, Callable, List try: from asyncio import ensure_future except ImportError: # ensure_future is only implemented in Python 3.4.4+ - def ensure_future(coro_or_future, loop=None): + def ensure_future(coro_or_future, loop=None): # type: ignore """Wrap a coroutine or an awaitable in a future. If the argument is a Future, it is returned directly. @@ -39,7 +39,7 @@ def ensure_future(coro_or_future, loop=None): def isasyncgen(obj): False - def asyncgen_to_observable(asyncgen): + def asyncgen_to_observable(asyncgen, loop=None): pass @@ -49,7 +49,7 @@ def __init__(self, loop=None): if loop is None: loop = get_event_loop() self.loop = loop - self.futures = [] + self.futures = [] # type: List[Future] def wait_until_finished(self): # type: () -> None diff --git a/graphql/execution/executors/thread.py b/graphql/execution/executors/thread.py index 35210d99..1544ec98 100644 --- a/graphql/execution/executors/thread.py +++ b/graphql/execution/executors/thread.py @@ -5,7 +5,7 @@ from .utils import process if False: # flake8: noqa - from typing import Any, Callable + from typing import Any, Callable, List class ThreadExecutor(object): @@ -14,7 +14,7 @@ class ThreadExecutor(object): def __init__(self, pool=False): # type: (bool) -> None - self.threads = [] + self.threads = [] # type: List[Thread] if pool: self.execute = self.execute_in_pool self.pool = ThreadPool(processes=pool) @@ -26,7 +26,8 @@ def wait_until_finished(self): while self.threads: threads = self.threads self.threads = [] - [thread.join() for thread in threads] + for thread in threads: + thread.join() def clean(self): self.threads = [] diff --git a/graphql/execution/executors/utils.py b/graphql/execution/executors/utils.py index 41cd29d1..d710e4c7 100644 --- a/graphql/execution/executors/utils.py +++ b/graphql/execution/executors/utils.py @@ -3,7 +3,7 @@ if False: # flake8: noqa from ..base import ResolveInfo from promise import Promise - from typing import Callable, Dict, Tuple, Union + from typing import Callable, Dict, Tuple, Union, Any def process( @@ -18,5 +18,5 @@ def process( p.do_resolve(val) except Exception as e: traceback = exc_info()[2] - e.stack = traceback + e.stack = traceback # type: ignore p.do_reject(e, traceback=traceback) diff --git a/graphql/execution/middleware.py b/graphql/execution/middleware.py index 0880858b..97cbec11 100644 --- a/graphql/execution/middleware.py +++ b/graphql/execution/middleware.py @@ -2,11 +2,11 @@ from functools import partial from itertools import chain -from promise import Promise +from promise import Promise, promisify if False: # flake8: noqa from .base import ResolveInfo - from typing import Any, Callable, Iterator, Tuple, Union, List, Dict + from typing import Any, Callable, Iterator, Tuple, Union, List, Dict, Iterable MIDDLEWARE_RESOLVER_FUNCTION = "resolve" @@ -20,16 +20,16 @@ class MiddlewareManager(object): ) def __init__(self, *middlewares, **kwargs): - # type: (*Any, **Dict[str, bool]) -> None + # type: (*Callable, **bool) -> None self.middlewares = middlewares self.wrap_in_promise = kwargs.get("wrap_in_promise", True) self._middleware_resolvers = ( list(get_middleware_resolvers(middlewares)) if middlewares else [] ) - self._cached_resolvers = {} + self._cached_resolvers = {} # type: Dict[Callable, Callable] def get_field_resolver(self, field_resolver): - # type: (Callable[[Any, ResolveInfo, ...], Any]) -> Callable[[Any, ResolveInfo, ...], Any] + # type: (Callable) -> Callable if field_resolver not in self._cached_resolvers: self._cached_resolvers[field_resolver] = middleware_chain( field_resolver, @@ -44,7 +44,7 @@ def get_field_resolver(self, field_resolver): def get_middleware_resolvers(middlewares): - # type: (Tuple[Any]) -> Iterator[Callable] + # type: (Tuple[Any, ...]) -> Iterator[Callable] for middleware in middlewares: # If the middleware is a function instead of a class if inspect.isfunction(middleware): @@ -55,7 +55,7 @@ def get_middleware_resolvers(middlewares): def middleware_chain(func, middlewares, wrap_in_promise): - # type: (Callable, List[Callable], bool) -> Callable + # type: (Callable, Iterable[Callable], bool) -> Callable if not middlewares: return func if wrap_in_promise: @@ -66,9 +66,10 @@ def middleware_chain(func, middlewares, wrap_in_promise): for middleware in middlewares: last_func = partial(middleware, last_func) if last_func else middleware - return last_func + return last_func # type: ignore -def make_it_promise(next, *a, **b): - # type: (Callable, *Any, **Any) -> Promise - return Promise.resolve(next(*a, **b)) +@promisify +def make_it_promise(next, *args, **kwargs): + # type: (Callable, *Any, **Any) -> Any + return next(*args, **kwargs) diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py index bbab86c3..a44cd503 100644 --- a/graphql/execution/utils.py +++ b/graphql/execution/utils.py @@ -29,7 +29,7 @@ ) from .base import ResolveInfo from types import TracebackType - from typing import Any, List, Dict, Optional, Union, Callable, Set + from typing import Any, List, Dict, Optional, Union, Callable, Set, Tuple logger = logging.getLogger(__name__) @@ -59,9 +59,9 @@ def __init__( self, schema, # type: GraphQLSchema document_ast, # type: Document - root_value, # type: Union[None, Data, type] - context_value, # type: Optional[Context] - variable_values, # type: Dict[str, int] + root_value, # type: Any + context_value, # type: Any + variable_values, # type: Optional[Dict[str, Any]] operation_name, # type: Optional[str] executor, # type: Any middleware, # type: Optional[Any] @@ -71,9 +71,9 @@ def __init__( """Constructs a ExecutionContext object from the arguments passed to execute, which we will pass throughout the other execution methods.""" - errors = [] + errors = [] # type: List[Exception] operation = None - fragments = {} + fragments = {} # type: Dict[str, FragmentDefinition] for definition in document_ast.definitions: if isinstance(definition, ast.OperationDefinition): @@ -120,11 +120,11 @@ def __init__( self.variable_values = variable_values self.errors = errors self.context_value = context_value - self.argument_values_cache = {} + self.argument_values_cache = {} # type: Dict[Tuple[GraphQLField, Field], Dict[str, Any]] self.executor = executor self.middleware = middleware self.allow_subscriptions = allow_subscriptions - self._subfields_cache = {} + self._subfields_cache = {} # type: Dict[Tuple[GraphQLObjectType, Tuple[Field, ...]], DefaultOrderedDict] def get_field_resolver(self, field_resolver): # type: (Callable) -> Callable @@ -144,7 +144,7 @@ def get_argument_values(self, field_def, field_ast): return result def report_error(self, error, traceback=None): - # type: (GraphQLError, Optional[TracebackType]) -> None + # type: (Exception, Optional[TracebackType]) -> None exception = format_exception( type(error), error, getattr(error, "stack", None) or traceback ) @@ -156,7 +156,7 @@ def get_sub_fields(self, return_type, field_asts): k = return_type, tuple(field_asts) if k not in self._subfields_cache: subfield_asts = DefaultOrderedDict(list) - visited_fragment_names = set() + visited_fragment_names = set() # type: Set[str] for field_ast in field_asts: selection_set = field_ast.selection_set if selection_set: @@ -177,7 +177,7 @@ class SubscriberExecutionContext(object): def __init__(self, exe_context): # type: (ExecutionContext) -> None self.exe_context = exe_context - self.errors = [] + self.errors = [] # type: List[Exception] def reset(self): # type: () -> None @@ -262,7 +262,7 @@ def collect_fields( continue prev_fragment_names.add(frag_name) - fragment = ctx.fragments.get(frag_name) + fragment = ctx.fragments[frag_name] frag_directives = fragment.directives if ( not fragment @@ -279,7 +279,7 @@ def collect_fields( def should_include_node(ctx, directives): - # type: (ExecutionContext, List[Directive]) -> bool + # type: (ExecutionContext, Optional[List[Directive]]) -> bool """Determines if a field should be included based on the @include and @skip directives, where @skip has higher precidence than @include.""" # TODO: Refactor based on latest code diff --git a/graphql/execution/values.py b/graphql/execution/values.py index a0568321..c1a20f22 100644 --- a/graphql/execution/values.py +++ b/graphql/execution/values.py @@ -22,7 +22,7 @@ from ..language.ast import VariableDefinition, Argument from ..type.schema import GraphQLSchema from ..type.definition import GraphQLArgument - from typing import Any, Dict, List, Union, Dict + from typing import Any, Dict, List, Union, Dict, Optional __all__ = ["get_variable_values", "get_argument_values"] @@ -32,7 +32,7 @@ def get_variable_values( definition_asts, # type: List[VariableDefinition] inputs, # type: Any ): - # type: (...) -> Union[Dict[str, Dict[str, Any]], Dict[str, Dict[str, str]], Dict[str, int]] + # type: (...) -> Dict[str, Any] """Prepares an object map of variables of the correct type based on the provided variable definitions and arbitrary input. If the input cannot be parsed to match the variable definitions, a GraphQLError will be thrown.""" if inputs is None: @@ -53,7 +53,9 @@ def get_variable_values( ) elif value is None: if def_ast.default_value is not None: - values[var_name] = value_from_ast(def_ast.default_value, var_type) + values[var_name] = value_from_ast( + def_ast.default_value, var_type + ) # type: ignore if isinstance(var_type, GraphQLNonNull): raise GraphQLError( 'Variable "${var_name}" of required type "{var_type}" was not provided.'.format( @@ -82,8 +84,8 @@ def get_variable_values( def get_argument_values( arg_defs, # type: Union[Dict[str, GraphQLArgument], Dict] - arg_asts, # type: List[Argument] - variables=None, # type: Dict[str, int] + arg_asts, # type: Optional[List[Argument]] + variables=None, # type: Optional[Dict[str, Union[List, Dict, int, float, bool, str, None]]] ): # type: (...) -> Dict[str, Any] """Prepares an object map of argument values given a list of argument @@ -92,14 +94,16 @@ def get_argument_values( return {} if arg_asts: - arg_ast_map = {arg.name.value: arg for arg in arg_asts} + arg_ast_map = { + arg.name.value: arg for arg in arg_asts + } # type: Dict[str, Argument] else: arg_ast_map = {} result = {} for name, arg_def in arg_defs.items(): arg_type = arg_def.type - value_ast = arg_ast_map.get(name) + arg_ast = arg_ast_map.get(name) if name not in arg_ast_map: if arg_def.default_value is not None: result[arg_def.out_name or name] = arg_def.default_value @@ -111,11 +115,10 @@ def get_argument_values( ), arg_asts, ) - elif isinstance(value_ast.value, ast.Variable): - variable_name = value_ast.value.name.value - variable_value = variables.get(variable_name) + elif isinstance(arg_ast.value, ast.Variable): # type: ignore + variable_name = arg_ast.value.name.value # type: ignore if variables and variable_name in variables: - result[arg_def.out_name or name] = variable_value + result[arg_def.out_name or name] = variables[variable_name] elif arg_def.default_value is not None: result[arg_def.out_name or name] = arg_def.default_value elif isinstance(arg_type, GraphQLNonNull): @@ -128,9 +131,7 @@ def get_argument_values( continue else: - value_ast = value_ast.value - - value = value_from_ast(value_ast, arg_type, variables) + value = value_from_ast(arg_ast.value, arg_type, variables) # type: ignore if value is None: if arg_def.default_value is not None: value = arg_def.default_value @@ -144,7 +145,7 @@ def get_argument_values( def coerce_value(type, value): - # type: (Any, Any) -> Union[int, str] + # type: (Any, Any) -> Union[List, Dict, int, float, bool, str, None] """Given a type and any value, return a runtime value coerced to match the type.""" if isinstance(type, GraphQLNonNull): # Note: we're not checking that the result of coerceValue is diff --git a/graphql/language/printer.py b/graphql/language/printer.py index cedd8d73..02e15ee9 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -55,19 +55,19 @@ class PrintingVisitor(Visitor): __slots__ = () def leave_Name(self, node, *args): - # type: (Name, *Any) -> str + # type: (Any, *Any) -> str return node.value # type: ignore def leave_Variable(self, node, *args): - # type: (Variable, *Any) -> str + # type: (Any, *Any) -> str return "$" + node.name # type: ignore def leave_Document(self, node, *args): - # type: (Document, *Any) -> str + # type: (Any, *Any) -> str return join(node.definitions, "\n\n") + "\n" # type: ignore def leave_OperationDefinition(self, node, *args): - # type: (OperationDefinition, *Any) -> str + # type: (Any, *Any) -> str name = node.name selection_set = node.selection_set op = node.operation @@ -80,15 +80,15 @@ def leave_OperationDefinition(self, node, *args): return join([op, join([name, var_defs]), directives, selection_set], " ") def leave_VariableDefinition(self, node, *args): - # type: (VariableDefinition, *Any) -> str + # type: (Any, *Any) -> str return node.variable + ": " + node.type + wrap(" = ", node.default_value) def leave_SelectionSet(self, node, *args): - # type: (SelectionSet, *Any) -> str + # type: (Any, *Any) -> str return block(node.selections) def leave_Field(self, node, *args): - # type: (Field, *Any) -> str + # type: (Any, *Any) -> str return join( [ wrap("", node.alias, ": ") @@ -101,17 +101,17 @@ def leave_Field(self, node, *args): ) def leave_Argument(self, node, *args): - # type: (Argument, *Any) -> str + # type: (Any, *Any) -> str return "{0.name}: {0.value}".format(node) # Fragments def leave_FragmentSpread(self, node, *args): - # type: (FragmentSpread, *Any) -> str + # type: (Any, *Any) -> str return "..." + node.name + wrap(" ", join(node.directives, " ")) def leave_InlineFragment(self, node, *args): - # type: (InlineFragment, *Any) -> str + # type: (Any, *Any) -> str return join( [ "...", @@ -123,7 +123,7 @@ def leave_InlineFragment(self, node, *args): ) def leave_FragmentDefinition(self, node, *args): - # type: (FragmentDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( "fragment {} on {} ".format(node.name, node.type_condition) + wrap("", join(node.directives, " "), " ") @@ -133,74 +133,74 @@ def leave_FragmentDefinition(self, node, *args): # Value def leave_IntValue(self, node, *args): - # type: (IntValue, *Any) -> str + # type: (Any, *Any) -> str return node.value def leave_FloatValue(self, node, *args): return node.value def leave_StringValue(self, node, *args): - # type: (StringValue, *Any) -> str + # type: (Any, *Any) -> str return json.dumps(node.value) def leave_BooleanValue(self, node, *args): - # type: (BooleanValue, *Any) -> str + # type: (Any, *Any) -> str return json.dumps(node.value) def leave_EnumValue(self, node, *args): - # type: (EnumValue, *Any) -> str + # type: (Any, *Any) -> str return node.value def leave_ListValue(self, node, *args): - # type: (ListValue, *Any) -> str + # type: (Any, *Any) -> str return "[" + join(node.values, ", ") + "]" def leave_ObjectValue(self, node, *args): - # type: (ObjectValue, *Any) -> str + # type: (Any, *Any) -> str return "{" + join(node.fields, ", ") + "}" def leave_ObjectField(self, node, *args): - # type: (ObjectField, *Any) -> str + # type: (Any, *Any) -> str return node.name + ": " + node.value # Directive def leave_Directive(self, node, *args): - # type: (Directive, *Any) -> str + # type: (Any, *Any) -> str return "@" + node.name + wrap("(", join(node.arguments, ", "), ")") # Type def leave_NamedType(self, node, *args): - # type: (NamedType, *Any) -> str + # type: (Any, *Any) -> str return node.name def leave_ListType(self, node, *args): - # type: (ListType, *Any) -> str + # type: (Any, *Any) -> str return "[" + node.type + "]" def leave_NonNullType(self, node, *args): - # type: (NonNullType, *Any) -> str + # type: (Any, *Any) -> str return node.type + "!" # Type Definitions: def leave_SchemaDefinition(self, node, *args): - # type: (SchemaDefinition, *Any) -> str + # type: (Any, *Any) -> str return join( ["schema", join(node.directives, " "), block(node.operation_types)], " " ) def leave_OperationTypeDefinition(self, node, *args): - # type: (OperationTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return "{}: {}".format(node.operation, node.type) def leave_ScalarTypeDefinition(self, node, *args): - # type: (ScalarTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return "scalar " + node.name + wrap(" ", join(node.directives, " ")) def leave_ObjectTypeDefinition(self, node, *args): - # type: (ObjectTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return join( [ "type", @@ -213,7 +213,7 @@ def leave_ObjectTypeDefinition(self, node, *args): ) def leave_FieldDefinition(self, node, *args): - # type: (FieldDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( node.name + wrap("(", join(node.arguments, ", "), ")") @@ -223,7 +223,7 @@ def leave_FieldDefinition(self, node, *args): ) def leave_InputValueDefinition(self, node, *args): - # type: (InputValueDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( node.name + ": " @@ -233,7 +233,7 @@ def leave_InputValueDefinition(self, node, *args): ) def leave_InterfaceTypeDefinition(self, node, *args): - # type: (InterfaceTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( "interface " + node.name @@ -243,7 +243,7 @@ def leave_InterfaceTypeDefinition(self, node, *args): ) def leave_UnionTypeDefinition(self, node, *args): - # type: (UnionTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( "union " + node.name @@ -253,7 +253,7 @@ def leave_UnionTypeDefinition(self, node, *args): ) def leave_EnumTypeDefinition(self, node, *args): - # type: (EnumTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( "enum " + node.name @@ -263,11 +263,11 @@ def leave_EnumTypeDefinition(self, node, *args): ) def leave_EnumValueDefinition(self, node, *args): - # type: (EnumValueDefinition, *Any) -> str + # type: (Any, *Any) -> str return node.name + wrap(" ", join(node.directives, " ")) def leave_InputObjectTypeDefinition(self, node, *args): - # type: (InputObjectTypeDefinition, *Any) -> str + # type: (Any, *Any) -> str return ( "input " + node.name @@ -277,11 +277,11 @@ def leave_InputObjectTypeDefinition(self, node, *args): ) def leave_TypeExtensionDefinition(self, node, *args): - # type: (TypeExtensionDefinition, *Any) -> str + # type: (Any, *Any) -> str return "extend " + node.definition def leave_DirectiveDefinition(self, node, *args): - # type: (DirectiveDefinition, *Any) -> str + # type: (Any, *Any) -> str return "directive @{}{} on {}".format( node.name, wrap("(", join(node.arguments, ", "), ")"), @@ -290,7 +290,7 @@ def leave_DirectiveDefinition(self, node, *args): def join(maybe_list, separator=""): - # type: (Optional[List[Optional[str]]], str) -> str + # type: (Optional[List[str]], str) -> str if maybe_list: return separator.join(filter(None, maybe_list)) return "" diff --git a/graphql/language/visitor.py b/graphql/language/visitor.py index ba193046..c2a7bbac 100644 --- a/graphql/language/visitor.py +++ b/graphql/language/visitor.py @@ -150,11 +150,11 @@ def visit(root, visitor, key_map=None): if not is_leaving: stack = Stack(in_array, index, keys, edits, stack) in_array = isinstance(node, list) - keys = ( + keys = ( # type: ignore node if in_array else visitor_keys.get(type(node), None) or [] # type: ignore - ) # type: ignore + ) index = -1 edits = [] diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index 1dafd80d..1f5d1292 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -20,7 +20,8 @@ if False: # flake8: noqa from ..execution.base import ResolveInfo - from typing import Union, List, Optional, Any + from .definition import GraphQLInputObjectField + from typing import Union, List, Optional, Any, Dict InputField = namedtuple("InputField", ["name", "description", "type", "default_value"]) Field = namedtuple( @@ -29,6 +30,7 @@ def input_fields_to_list(input_fields): + # type: (Dict[str, GraphQLInputObjectField]) -> List[InputField] fields = [] for field_name, field in input_fields.items(): fields.append( @@ -53,7 +55,9 @@ def input_fields_to_list(input_fields): "types", GraphQLField( description="A list of all types supported by this server.", - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Type))), + type=GraphQLNonNull( + GraphQLList(GraphQLNonNull(__Type)) # type: ignore + ), resolver=lambda schema, *_: schema.get_type_map().values(), ), ), @@ -61,7 +65,7 @@ def input_fields_to_list(input_fields): "queryType", GraphQLField( description="The type that query operations will be rooted at.", - type=GraphQLNonNull(__Type), + type=GraphQLNonNull(__Type), # type: ignore resolver=lambda schema, *_: schema.get_query_type(), ), ), @@ -70,7 +74,7 @@ def input_fields_to_list(input_fields): GraphQLField( description="If this server supports mutation, the type that " "mutation operations will be rooted at.", - type=__Type, + type=__Type, # type: ignore resolver=lambda schema, *_: schema.get_mutation_type(), ), ), @@ -79,7 +83,7 @@ def input_fields_to_list(input_fields): GraphQLField( description="If this server support subscription, the type " "that subscription operations will be rooted at.", - type=__Type, + type=__Type, # type: ignore resolver=lambda schema, *_: schema.get_subscription_type(), ), ), @@ -87,7 +91,9 @@ def input_fields_to_list(input_fields): "directives", GraphQLField( description="A list of all directives supported by this server.", - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__Directive))), + type=GraphQLNonNull( + GraphQLList(GraphQLNonNull(__Directive)) # type: ignore + ), resolver=lambda schema, *_: schema.get_directives(), ), ), @@ -115,14 +121,16 @@ def input_fields_to_list(input_fields): "locations", GraphQLField( type=GraphQLNonNull( - GraphQLList(GraphQLNonNull(__DirectiveLocation)) + GraphQLList(GraphQLNonNull(__DirectiveLocation)) # type: ignore ) ), ), ( "args", GraphQLField( - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), + type=GraphQLNonNull( + GraphQLList(GraphQLNonNull(__InputValue)) # type: ignore + ), resolver=lambda directive, *args: input_fields_to_list( directive.args ), @@ -359,13 +367,11 @@ def fields( return None @staticmethod - def interfaces( - type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] - info, # type: ResolveInfo - ): - # type: (...) -> Optional[Any] + def interfaces(type, info): + # type: (Optional[GraphQLObjectType], ResolveInfo) -> Optional[List[GraphQLInterfaceType]] if isinstance(type, GraphQLObjectType): return type.interfaces + return None @staticmethod def possible_types( @@ -379,24 +385,22 @@ def possible_types( @staticmethod def enum_values( - type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] + type, # type: GraphQLEnumType info, # type: ResolveInfo includeDeprecated=None, # type: bool ): - # type: (...) -> Optional[Any] + # type: (...) -> Optional[List[GraphQLEnumValue]] if isinstance(type, GraphQLEnumType): values = type.values if not includeDeprecated: values = [v for v in values if not v.deprecation_reason] return values + return None @staticmethod - def input_fields( - type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] - info, # type: ResolveInfo - ): - # type: (...) -> Optional[Any] + def input_fields(type, info): + # type: (GraphQLInputObjectType, ResolveInfo) -> List[InputField] if isinstance(type, GraphQLInputObjectType): return input_fields_to_list(type.fields) @@ -416,7 +420,8 @@ def input_fields( ( "kind", GraphQLField( - type=GraphQLNonNull(__TypeKind), resolver=TypeFieldResolvers.kind + type=GraphQLNonNull(__TypeKind), # type: ignore + resolver=TypeFieldResolvers.kind, ), ), ("name", GraphQLField(GraphQLString)), @@ -424,7 +429,7 @@ def input_fields( ( "fields", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Field)), + type=GraphQLList(GraphQLNonNull(__Field)), # type: ignore args={ "includeDeprecated": GraphQLArgument( GraphQLBoolean, default_value=False @@ -436,21 +441,21 @@ def input_fields( ( "interfaces", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), + type=GraphQLList(GraphQLNonNull(__Type)), # type: ignore resolver=TypeFieldResolvers.interfaces, ), ), ( "possibleTypes", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), + type=GraphQLList(GraphQLNonNull(__Type)), # type: ignore resolver=TypeFieldResolvers.possible_types, ), ), ( "enumValues", GraphQLField( - type=GraphQLList(GraphQLNonNull(__EnumValue)), + type=GraphQLList(GraphQLNonNull(__EnumValue)), # type: ignore args={ "includeDeprecated": GraphQLArgument( GraphQLBoolean, default_value=False @@ -462,14 +467,14 @@ def input_fields( ( "inputFields", GraphQLField( - type=GraphQLList(GraphQLNonNull(__InputValue)), + type=GraphQLList(GraphQLNonNull(__InputValue)), # type: ignore resolver=TypeFieldResolvers.input_fields, ), ), ( "ofType", GraphQLField( - type=__Type, + type=__Type, # type: ignore resolver=lambda type, *_: getattr(type, "of_type", None), ), ), @@ -488,11 +493,13 @@ def input_fields( ( "args", GraphQLField( - type=GraphQLNonNull(GraphQLList(GraphQLNonNull(__InputValue))), + type=GraphQLNonNull( + GraphQLList(GraphQLNonNull(__InputValue)) # type: ignore + ), resolver=lambda field, *_: input_fields_to_list(field.args), ), ), - ("type", GraphQLField(GraphQLNonNull(__Type))), + ("type", GraphQLField(GraphQLNonNull(__Type))), # type: ignore ( "isDeprecated", GraphQLField( diff --git a/graphql/type/schema.py b/graphql/type/schema.py index 06cf5be6..54e0a09f 100644 --- a/graphql/type/schema.py +++ b/graphql/type/schema.py @@ -6,7 +6,12 @@ from .typemap import GraphQLTypeMap if False: # flake8: noqa - from .definition import GraphQLInterfaceType, GraphQLUnionType, GraphQLType + from .definition import ( + GraphQLNamedType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLType, + ) from typing import Dict, Union, Any, List, Optional @@ -51,7 +56,7 @@ def __init__( mutation=None, # type: Optional[GraphQLObjectType] subscription=None, # type: Optional[GraphQLObjectType] directives=None, # type: Optional[List[GraphQLDirective]] - types=None, # type: Optional[List[GraphQLObjectType]] + types=None, # type: Optional[List[GraphQLNamedType]] ): # type: (...) -> None assert isinstance( @@ -87,10 +92,12 @@ def __init__( ) self._directives = directives - initial_types = [query, mutation, subscription, IntrospectionSchema] + initial_types = list( + filter(None, [query, mutation, subscription, IntrospectionSchema]) + ) # type: List[GraphQLNamedType] if types: initial_types += types - self._type_map = GraphQLTypeMap(initial_types) # type: Dict[str, GraphQLType] + self._type_map = GraphQLTypeMap(initial_types) # type: GraphQLTypeMap def get_query_type(self): # type: () -> GraphQLObjectType @@ -109,8 +116,9 @@ def get_type_map(self): return self._type_map def get_type(self, name): - # type: (str) -> Optional[GraphQLType] + # type: (str) -> Optional[GraphQLNamedType] return self._type_map.get(name) + # raise Exception("Type {name} not found in schema.".format(name=name)) def get_directives(self): # type: () -> List[GraphQLDirective] @@ -124,18 +132,13 @@ def get_directive(self, name): return None - def get_possible_types( - self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, - ): - # type: (...) -> List[GraphQLObjectType] + def get_possible_types(self, abstract_type): + # type: (Union[GraphQLInterfaceType, GraphQLUnionType]) -> List[GraphQLObjectType] return self._type_map.get_possible_types(abstract_type) def is_possible_type( self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, + abstract_type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] possible_type, # type: GraphQLObjectType ): # type: (...) -> bool diff --git a/graphql/type/tests/test_schema.py b/graphql/type/tests/test_schema.py index 96173f29..5f7b56dc 100644 --- a/graphql/type/tests/test_schema.py +++ b/graphql/type/tests/test_schema.py @@ -39,6 +39,6 @@ def test_throws_human_readable_error_if_schematypes_not_defined(): schema.is_possible_type(interface_type, implementing_type) assert str(exci.value) == ( - "Could not find possible implementing types for $Interface in schema. Check that " + "Could not find possible implementing types for Interface in schema. Check that " "schema.types is defined and is an array ofall possible types in the schema." ) diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index aebff6f0..146bd129 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -16,28 +16,25 @@ ) if False: # flake8: noqa - from typing import Any, List, Optional, Union + from ..type.definition import GraphQLNamedType + from typing import Any, List, Optional, Union, Dict, Set, Mapping, DefaultDict class GraphQLTypeMap(OrderedDict): - def __init__( - self, - # type: Union[List[Optional[GraphQLObjectType]], List[GraphQLObjectType]] - types, - ): - # type: (...) -> None + def __init__(self, types): + # type: (List[GraphQLNamedType]) -> None super(GraphQLTypeMap, self).__init__() - self.update(reduce(self.reducer, types, OrderedDict())) - self._possible_type_map = defaultdict(set) + self.update(reduce(self.reducer, types, OrderedDict())) # type: ignore + self._possible_type_map = defaultdict(set) # type: DefaultDict[str, Set[str]] # Keep track of all implementations by interface name. - self._implementations = {} + self._implementations = defaultdict( + list + ) # type: DefaultDict[str, List[GraphQLObjectType]] for gql_type in self.values(): if isinstance(gql_type, GraphQLObjectType): for interface in gql_type.interfaces: - self._implementations.setdefault(interface.name, []).append( - gql_type - ) + self._implementations[interface.name].append(gql_type) # Enforce correct interface implementations. for type in self.values(): @@ -45,32 +42,29 @@ def __init__( for interface in type.interfaces: self.assert_object_implements_interface(self, type, interface) - def get_possible_types( - self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, - ): - # type: (...) -> List[GraphQLObjectType] + def get_possible_types(self, abstract_type): + # type: (Union[GraphQLInterfaceType, GraphQLUnionType]) -> List[GraphQLObjectType] if isinstance(abstract_type, GraphQLUnionType): return abstract_type.types assert isinstance(abstract_type, GraphQLInterfaceType) - return self._implementations.get(abstract_type.name, None) + if abstract_type.name not in self._implementations: + return [] + return self._implementations[abstract_type.name] def is_possible_type( self, - # type: Union[GraphQLInterfaceType, GraphQLUnionType] - abstract_type, + abstract_type, # type: Union[GraphQLInterfaceType, GraphQLUnionType] possible_type, # type: GraphQLObjectType ): # type: (...) -> bool possible_types = self.get_possible_types(abstract_type) - assert isinstance(possible_types, Sequence), ( - "Could not find possible implementing types for ${} in " + assert possible_types, ( + "Could not find possible implementing types for {} in " + "schema. Check that schema.types is defined and is an array of" + "all possible types in the schema." ).format(abstract_type) - if not self._possible_type_map[abstract_type.name]: + if abstract_type.name not in self._possible_type_map: self._possible_type_map[abstract_type.name].update( [p.name for p in possible_types] ) @@ -79,11 +73,11 @@ def is_possible_type( @classmethod def reducer(cls, map, type): - # type: (OrderedDict, Any) -> OrderedDict + # type: (Dict, Union[GraphQLNamedType, GraphQLList, GraphQLNonNull]) -> Dict if not type: return map - if isinstance(type, GraphQLList) or isinstance(type, GraphQLNonNull): + if isinstance(type, (GraphQLList, GraphQLNonNull)): return cls.reducer(map, type.of_type) if type.name in map: @@ -93,7 +87,7 @@ def reducer(cls, map, type): return map - map[type.name] = type + map[type.name] = type # type: ignore reduced_map = map diff --git a/graphql/utils/is_valid_literal_value.py b/graphql/utils/is_valid_literal_value.py index 9b9f3b41..9e99d587 100644 --- a/graphql/utils/is_valid_literal_value.py +++ b/graphql/utils/is_valid_literal_value.py @@ -17,13 +17,13 @@ def is_valid_literal_value(type, value_ast): - # type: (Union[GraphQLInputObjectType, GraphQLScalarType, GraphQLNonNull], Any) -> List + # type: (Union[GraphQLInputObjectType, GraphQLScalarType, GraphQLNonNull, GraphQLList], Any) -> List if isinstance(type, GraphQLNonNull): of_type = type.of_type if not value_ast: return [u'Expected "{}", found null.'.format(type)] - return is_valid_literal_value(of_type, value_ast) + return is_valid_literal_value(of_type, value_ast) # type: ignore if not value_ast: return _empty_list diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index b5a4952f..4789df26 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -14,6 +14,7 @@ GraphQLObjectType, GraphQLUnionType, ) + from ..type.typemap import GraphQLTypeMap from ..type.schema import GraphQLSchema from typing import Union @@ -32,7 +33,7 @@ def is_equal_type(type_a, type_b): def is_type_sub_type_of(schema, maybe_subtype, super_type): - # type: (GraphQLSchema, GraphQLScalarType, GraphQLScalarType) -> bool + # type: (Union[GraphQLSchema, GraphQLTypeMap], GraphQLScalarType, GraphQLScalarType) -> bool if maybe_subtype is super_type: return True diff --git a/graphql/utils/type_from_ast.py b/graphql/utils/type_from_ast.py index 51c0bbd6..c76a2d28 100644 --- a/graphql/utils/type_from_ast.py +++ b/graphql/utils/type_from_ast.py @@ -8,21 +8,18 @@ from typing import Any, Union -def type_from_ast(schema, input_type_ast): +def type_from_ast(schema, type_node): # type: (GraphQLSchema, Union[ListType, NamedType, NonNullType]) -> Union[GraphQLList, GraphQLNonNull, GraphQLNamedType] - if isinstance(input_type_ast, ast.ListType): - inner_type = type_from_ast(schema, input_type_ast.type) - if inner_type: - return GraphQLList(inner_type) - else: - return None + if isinstance(type_node, ast.ListType): + inner_type = type_from_ast(schema, type_node.type) + return inner_type and GraphQLList(inner_type) - if isinstance(input_type_ast, ast.NonNullType): - inner_type = type_from_ast(schema, input_type_ast.type) - if inner_type: - return GraphQLNonNull(inner_type) - else: - return None + elif isinstance(type_node, ast.NonNullType): + inner_type = type_from_ast(schema, type_node.type) + return inner_type and GraphQLNonNull(inner_type) # type: ignore - assert isinstance(input_type_ast, ast.NamedType), "Must be a type name." - return schema.get_type(input_type_ast.name.value) + elif isinstance(type_node, ast.NamedType): + schema_type = schema.get_type(type_node.name.value) + return schema_type # type: ignore + + raise Exception("Unexpected type kind: {type_kind}".format(type_kind=type_node)) diff --git a/graphql/validation/rules/__init__.py b/graphql/validation/rules/__init__.py index 329dabf8..e9f19cbf 100644 --- a/graphql/validation/rules/__init__.py +++ b/graphql/validation/rules/__init__.py @@ -25,7 +25,7 @@ if False: # flake8: noqa from typing import List, Type - from ...language.visitor import Visitor + from .base import ValidationRule specified_rules = [ @@ -53,7 +53,7 @@ OverlappingFieldsCanBeMerged, UniqueInputFieldNames, UniqueVariableNames, -] # type: List[Type[Visitor]] +] # type: List[Type[ValidationRule]] __all__ = [ "ArgumentsOfCorrectType", diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index e427be8c..ae8ee6c5 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -623,7 +623,7 @@ def _get_referenced_fields_and_fragment_names( context.get_schema(), fragment.type_condition ) - return _get_fields_and_fragments_names( + return _get_fields_and_fragments_names( # type: ignore context, cached_fields_and_fragment_names, fragment_type, fragment.selection_set ) @@ -661,9 +661,9 @@ def _collect_fields_and_fragment_names( context.get_schema(), selection.type_condition ) else: - inline_fragment_type = parent_type + inline_fragment_type = parent_type # type: ignore - _collect_fields_and_fragment_names( + _collect_fields_and_fragment_names( # type: ignore context, inline_fragment_type, selection.selection_set, @@ -681,11 +681,11 @@ def _subfield_conflicts( # type: (...) -> Optional[Tuple[Tuple[str, str], List[Node], List[Node]]] """Given a series of Conflicts which occurred between two sub-fields, generate a single Conflict.""" if conflicts: - return ( + return ( # type: ignore (response_name, [conflict[0] for conflict in conflicts]), tuple(itertools.chain([ast1], *[conflict[1] for conflict in conflicts])), tuple(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])), - ) # type: ignore + ) return None diff --git a/graphql/validation/validation.py b/graphql/validation/validation.py index ac890516..9422ad56 100644 --- a/graphql/validation/validation.py +++ b/graphql/validation/validation.py @@ -185,7 +185,7 @@ def get_parent_type(self): def get_input_type(self): # type: () -> Optional[GraphQLInputObjectType] - return self._type_info.get_input_type() + return self._type_info.get_input_type() # type: ignore def get_field_def(self): # type: () -> Optional[GraphQLField] From 80836e43190f2b1e1145b283e5db7f5acfc75efd Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sun, 1 Jul 2018 23:37:50 -0700 Subject: [PATCH 10/12] Added mypy to the travis tests --- .travis.yml | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8b55782..d0a6a960 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,20 +3,6 @@ sudo: false python: - 2.7 # - "pypy-5.3.1" -before_install: -- | - if [ "$TRAVIS_PYTHON_VERSION" = "pypy" ]; then - export PYENV_ROOT="$HOME/.pyenv" - if [ -f "$PYENV_ROOT/bin/pyenv" ]; then - cd "$PYENV_ROOT" && git pull - else - rm -rf "$PYENV_ROOT" && git clone --depth 1 https://github.com/yyuu/pyenv.git "$PYENV_ROOT" - fi - export PYPY_VERSION="4.0.1" - "$PYENV_ROOT/bin/pyenv" install "pypy-$PYPY_VERSION" - virtualenv --python="$PYENV_ROOT/versions/pypy-$PYPY_VERSION/bin/python" "$HOME/virtualenvs/pypy-$PYPY_VERSION" - source "$HOME/virtualenvs/pypy-$PYPY_VERSION/bin/activate" - fi install: - pip install -e .[test] - pip install flake8 @@ -33,10 +19,12 @@ matrix: script: - py.test --cov=graphql graphql tests tests_py35 - python: '3.6' - after_install: - - pip install pytest-asyncio + install: + - pip install -e .[test] + - pip install pytest-asyncio mypy script: - py.test --cov=graphql graphql tests tests_py35 + - mypy graphql --ignore-missing-imports - python: '2.7' deploy: From 2f6ddd7c7e68db1bbd523c79727655cc45853015 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 2 Jul 2018 09:52:28 -0700 Subject: [PATCH 11/12] Added comments for if False checks --- graphql/backend/__init__.py | 1 + graphql/backend/base.py | 1 + graphql/backend/cache.py | 1 + graphql/backend/compiled.py | 1 + graphql/backend/core.py | 1 + graphql/backend/decider.py | 1 + graphql/error/base.py | 1 + graphql/error/format_error.py | 1 + graphql/error/located_error.py | 1 + graphql/error/syntax_error.py | 1 + graphql/error/tests/test_base.py | 1 + graphql/execution/base.py | 1 + graphql/execution/executor.py | 1 + graphql/execution/executors/asyncio.py | 1 + graphql/execution/executors/sync.py | 1 + graphql/execution/executors/thread.py | 1 + graphql/execution/executors/utils.py | 1 + graphql/execution/middleware.py | 1 + graphql/execution/tests/test_nonnull.py | 1 + graphql/execution/tests/test_subscribe.py | 1 + graphql/execution/utils.py | 1 + graphql/execution/values.py | 1 + graphql/graphql.py | 1 + graphql/language/ast.py | 1 + graphql/language/lexer.py | 1 + graphql/language/location.py | 1 + graphql/language/parser.py | 1 + graphql/language/printer.py | 1 + graphql/language/visitor.py | 1 + graphql/pyutils/cached_property.py | 1 + graphql/pyutils/contain_subset.py | 1 + graphql/pyutils/default_ordered_dict.py | 3 ++- graphql/pyutils/pair_set.py | 1 + graphql/type/definition.py | 1 + graphql/type/introspection.py | 1 + graphql/type/scalars.py | 1 + graphql/type/schema.py | 1 + graphql/type/typemap.py | 1 + graphql/utils/ast_to_code.py | 1 + graphql/utils/concat_ast.py | 1 + graphql/utils/get_field_def.py | 1 + graphql/utils/get_operation_ast.py | 1 + graphql/utils/is_valid_literal_value.py | 1 + graphql/utils/is_valid_value.py | 1 + graphql/utils/quoted_or_list.py | 1 + graphql/utils/schema_printer.py | 1 + graphql/utils/type_comparators.py | 1 + graphql/utils/type_from_ast.py | 1 + graphql/utils/type_info.py | 1 + graphql/utils/value_from_ast.py | 1 + graphql/validation/rules/__init__.py | 1 + graphql/validation/rules/arguments_of_correct_type.py | 1 + graphql/validation/rules/base.py | 1 + graphql/validation/rules/default_values_of_correct_type.py | 1 + graphql/validation/rules/fields_on_correct_type.py | 1 + graphql/validation/rules/fragments_on_composite_types.py | 1 + graphql/validation/rules/known_argument_names.py | 1 + graphql/validation/rules/known_type_names.py | 1 + graphql/validation/rules/lone_anonymous_operation.py | 1 + graphql/validation/rules/no_fragment_cycles.py | 1 + graphql/validation/rules/no_undefined_variables.py | 1 + graphql/validation/rules/no_unused_fragments.py | 1 + graphql/validation/rules/no_unused_variables.py | 1 + graphql/validation/rules/overlapping_fields_can_be_merged.py | 1 + graphql/validation/rules/possible_fragment_spreads.py | 1 + graphql/validation/rules/provided_non_null_arguments.py | 1 + graphql/validation/rules/scalar_leafs.py | 1 + graphql/validation/rules/unique_argument_names.py | 1 + graphql/validation/rules/unique_fragment_names.py | 1 + graphql/validation/rules/unique_input_field_names.py | 1 + graphql/validation/rules/unique_operation_names.py | 1 + graphql/validation/rules/unique_variable_names.py | 1 + graphql/validation/rules/variables_in_allowed_position.py | 1 + graphql/validation/validation.py | 1 + 74 files changed, 75 insertions(+), 1 deletion(-) diff --git a/graphql/backend/__init__.py b/graphql/backend/__init__.py index 87e9493e..9cd0e198 100644 --- a/graphql/backend/__init__.py +++ b/graphql/backend/__init__.py @@ -9,6 +9,7 @@ from .decider import GraphQLDeciderBackend from .cache import GraphQLCachedBackend +# Necessary for static type checking if False: # flake8: noqa from typing import Union diff --git a/graphql/backend/base.py b/graphql/backend/base.py index ee6c143e..9d3420b3 100644 --- a/graphql/backend/base.py +++ b/graphql/backend/base.py @@ -4,6 +4,7 @@ from abc import ABCMeta, abstractmethod import six +# Necessary for static type checking if False: # flake8: noqa from typing import Dict, Optional, Union, Callable from ..language.ast import Document diff --git a/graphql/backend/cache.py b/graphql/backend/cache.py index 1ecd1267..f6f0f4a1 100644 --- a/graphql/backend/cache.py +++ b/graphql/backend/cache.py @@ -4,6 +4,7 @@ from .base import GraphQLBackend +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Dict, Optional, Union, Tuple, Hashable from .base import GraphQLDocument diff --git a/graphql/backend/compiled.py b/graphql/backend/compiled.py index 7dc88e50..e3805cd1 100644 --- a/graphql/backend/compiled.py +++ b/graphql/backend/compiled.py @@ -1,6 +1,7 @@ from six import string_types from .base import GraphQLDocument +# Necessary for static type checking if False: # flake8: noqa from ..type.schema import GraphQLSchema from typing import Any, Optional, Dict, Callable, Union diff --git a/graphql/backend/core.py b/graphql/backend/core.py index 9368c7de..0d956c15 100644 --- a/graphql/backend/core.py +++ b/graphql/backend/core.py @@ -8,6 +8,7 @@ from .base import GraphQLBackend, GraphQLDocument +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Optional, Union from .base import GraphQLDocument diff --git a/graphql/backend/decider.py b/graphql/backend/decider.py index 6019393c..409b28fa 100644 --- a/graphql/backend/decider.py +++ b/graphql/backend/decider.py @@ -1,5 +1,6 @@ from .base import GraphQLBackend, GraphQLDocument +# Necessary for static type checking if False: # flake8: noqa from typing import List, Union, Any, Optional from ..type.schema import GraphQLSchema diff --git a/graphql/error/base.py b/graphql/error/base.py index f84482f2..c57d0959 100644 --- a/graphql/error/base.py +++ b/graphql/error/base.py @@ -1,6 +1,7 @@ import six from ..language.location import get_location +# Necessary for static type checking if False: # flake8: noqa from ..language.source import Source from ..language.location import SourceLocation diff --git a/graphql/error/format_error.py b/graphql/error/format_error.py index e60b6f1b..8cdec1ed 100644 --- a/graphql/error/format_error.py +++ b/graphql/error/format_error.py @@ -2,6 +2,7 @@ from .base import GraphQLError +# Necessary for static type checking if False: # flake8: noqa from .base import GraphQLError from .located_error import GraphQLLocatedError diff --git a/graphql/error/located_error.py b/graphql/error/located_error.py index 06bcccea..fe84e495 100644 --- a/graphql/error/located_error.py +++ b/graphql/error/located_error.py @@ -2,6 +2,7 @@ from .base import GraphQLError +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import Field from typing import List, Union diff --git a/graphql/error/syntax_error.py b/graphql/error/syntax_error.py index 4be4a4b4..d38adc1f 100644 --- a/graphql/error/syntax_error.py +++ b/graphql/error/syntax_error.py @@ -1,6 +1,7 @@ from ..language.location import get_location from .base import GraphQLError +# Necessary for static type checking if False: # flake8: noqa from ..language.source import Source from ..language.location import SourceLocation diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index 28d8e2a3..e53f152a 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -5,6 +5,7 @@ from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString +# Necessary for static type checking if False: # flake8: noqa from graphql.execution.base import ResolveInfo from typing import Any diff --git a/graphql/execution/base.py b/graphql/execution/base.py index 36c42428..47bb71d4 100644 --- a/graphql/execution/base.py +++ b/graphql/execution/base.py @@ -12,6 +12,7 @@ ) from ..error.format_error import format_error as default_format_error +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Optional, Dict, List, Union from ..language.ast import Field, OperationDefinition diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index d4043612..75f2ac95 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -35,6 +35,7 @@ from .executors.sync import SyncExecutor from .middleware import MiddlewareManager +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Optional, Union, Dict, List, Callable from rx import Observable diff --git a/graphql/execution/executors/asyncio.py b/graphql/execution/executors/asyncio.py index 8dc183eb..bafa492b 100644 --- a/graphql/execution/executors/asyncio.py +++ b/graphql/execution/executors/asyncio.py @@ -4,6 +4,7 @@ from promise import Promise +# Necessary for static type checking if False: # flake8: noqa from asyncio.unix_events import _UnixSelectorEventLoop from typing import Optional, Any, Callable, List diff --git a/graphql/execution/executors/sync.py b/graphql/execution/executors/sync.py index df8aabb6..c45d8a8f 100644 --- a/graphql/execution/executors/sync.py +++ b/graphql/execution/executors/sync.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Callable diff --git a/graphql/execution/executors/thread.py b/graphql/execution/executors/thread.py index 1544ec98..f540a1a0 100644 --- a/graphql/execution/executors/thread.py +++ b/graphql/execution/executors/thread.py @@ -4,6 +4,7 @@ from promise import Promise from .utils import process +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Callable, List diff --git a/graphql/execution/executors/utils.py b/graphql/execution/executors/utils.py index d710e4c7..1ba3aaa6 100644 --- a/graphql/execution/executors/utils.py +++ b/graphql/execution/executors/utils.py @@ -1,5 +1,6 @@ from sys import exc_info +# Necessary for static type checking if False: # flake8: noqa from ..base import ResolveInfo from promise import Promise diff --git a/graphql/execution/middleware.py b/graphql/execution/middleware.py index 97cbec11..be61abda 100644 --- a/graphql/execution/middleware.py +++ b/graphql/execution/middleware.py @@ -4,6 +4,7 @@ from promise import Promise, promisify +# Necessary for static type checking if False: # flake8: noqa from .base import ResolveInfo from typing import Any, Callable, Iterator, Tuple, Union, List, Dict, Iterable diff --git a/graphql/execution/tests/test_nonnull.py b/graphql/execution/tests/test_nonnull.py index ebd1e844..6f8a3725 100644 --- a/graphql/execution/tests/test_nonnull.py +++ b/graphql/execution/tests/test_nonnull.py @@ -12,6 +12,7 @@ from .utils import rejected, resolved +# Necessary for static type checking if False: # flake8: noqa from promise import Promise from typing import Any, Optional, Dict, Tuple, Union diff --git a/graphql/execution/tests/test_subscribe.py b/graphql/execution/tests/test_subscribe.py index f6ad3f34..2fa039c3 100644 --- a/graphql/execution/tests/test_subscribe.py +++ b/graphql/execution/tests/test_subscribe.py @@ -15,6 +15,7 @@ subscribe, ) +# Necessary for static type checking if False: # flake8: noqa from graphql.execution.base import ResolveInfo from rx import Observable diff --git a/graphql/execution/utils.py b/graphql/execution/utils.py index a44cd503..a942c729 100644 --- a/graphql/execution/utils.py +++ b/graphql/execution/utils.py @@ -15,6 +15,7 @@ from ..utils.type_from_ast import type_from_ast from .values import get_argument_values, get_variable_values +# Necessary for static type checking if False: # flake8: noqa from ..type.definition import GraphQLObjectType, GraphQLField from ..type.schema import GraphQLSchema diff --git a/graphql/execution/values.py b/graphql/execution/values.py index c1a20f22..18388b4b 100644 --- a/graphql/execution/values.py +++ b/graphql/execution/values.py @@ -18,6 +18,7 @@ from ..utils.type_from_ast import type_from_ast from ..utils.value_from_ast import value_from_ast +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import VariableDefinition, Argument from ..type.schema import GraphQLSchema diff --git a/graphql/graphql.py b/graphql/graphql.py index f7c394b7..7e22be53 100644 --- a/graphql/graphql.py +++ b/graphql/graphql.py @@ -3,6 +3,7 @@ from promise import promisify +# Necessary for static type checking if False: # flake8: noqa from rx import Observable from typing import Any, Union, Optional diff --git a/graphql/language/ast.py b/graphql/language/ast.py index a05072d3..f7f407ea 100644 --- a/graphql/language/ast.py +++ b/graphql/language/ast.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from .parser import Loc from typing import Any, Optional, Union, List, Tuple, Iterable diff --git a/graphql/language/lexer.py b/graphql/language/lexer.py index ce4f3179..a60bc6e2 100644 --- a/graphql/language/lexer.py +++ b/graphql/language/lexer.py @@ -4,6 +4,7 @@ from ..error import GraphQLSyntaxError +# Necessary for static type checking if False: # flake8: noqa from typing import Optional, Any, List from .source import Source diff --git a/graphql/language/location.py b/graphql/language/location.py index 6cf48f50..71c19bd9 100644 --- a/graphql/language/location.py +++ b/graphql/language/location.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from .source import Source from typing import Any diff --git a/graphql/language/parser.py b/graphql/language/parser.py index f8a20b84..8b658e50 100644 --- a/graphql/language/parser.py +++ b/graphql/language/parser.py @@ -5,6 +5,7 @@ from .lexer import Lexer, TokenKind, get_token_desc, get_token_kind_desc from .source import Source +# Necessary for static type checking if False: # flake8: noqa from typing import Dict, Union, Any, Optional, Callable, List from ..error.syntax_error import GraphQLSyntaxError diff --git a/graphql/language/printer.py b/graphql/language/printer.py index 02e15ee9..d2f27ef8 100644 --- a/graphql/language/printer.py +++ b/graphql/language/printer.py @@ -2,6 +2,7 @@ from .visitor import Visitor, visit +# Necessary for static type checking if False: # flake8: noqa from typing import Any, List, Optional, Union from graphql.language.ast import ( diff --git a/graphql/language/visitor.py b/graphql/language/visitor.py index c2a7bbac..66dded46 100644 --- a/graphql/language/visitor.py +++ b/graphql/language/visitor.py @@ -5,6 +5,7 @@ from . import ast from .visitor_meta import QUERY_DOCUMENT_KEYS, VisitorMeta +# Necessary for static type checking if False: # flake8: noqa from typing import Any, List, Optional, Union, Tuple, Dict from ..utils.type_info import TypeInfo diff --git a/graphql/pyutils/cached_property.py b/graphql/pyutils/cached_property.py index 119b9e2a..c17a4dbe 100644 --- a/graphql/pyutils/cached_property.py +++ b/graphql/pyutils/cached_property.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from typing import Any diff --git a/graphql/pyutils/contain_subset.py b/graphql/pyutils/contain_subset.py index da3aea78..3b34c621 100644 --- a/graphql/pyutils/contain_subset.py +++ b/graphql/pyutils/contain_subset.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Dict diff --git a/graphql/pyutils/default_ordered_dict.py b/graphql/pyutils/default_ordered_dict.py index 83a0b307..2408cb43 100644 --- a/graphql/pyutils/default_ordered_dict.py +++ b/graphql/pyutils/default_ordered_dict.py @@ -1,6 +1,7 @@ import copy from collections import OrderedDict +# Necessary for static type checking if False: # flake8: noqa from typing import Any, List @@ -18,7 +19,7 @@ def __init__(self, default_factory=None, *a, **kw): self.default_factory = default_factory def __missing__(self, key): - # type: (str) -> List + # type: (str) -> Any if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() diff --git a/graphql/pyutils/pair_set.py b/graphql/pyutils/pair_set.py index 9b369a4c..e7b18ebb 100644 --- a/graphql/pyutils/pair_set.py +++ b/graphql/pyutils/pair_set.py @@ -1,3 +1,4 @@ +# Necessary for static type checking if False: # flake8: noqa from typing import Dict, Any diff --git a/graphql/type/definition.py b/graphql/type/definition.py index 2aba9352..9099242e 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -7,6 +7,7 @@ from ..utils.assert_valid_name import assert_valid_name from ..utils.undefined import Undefined +# Necessary for static type checking if False: # flake8: noqa from typing import List, Dict, Any, Callable, Optional, Union, Type diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index 1f5d1292..520011f2 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -18,6 +18,7 @@ from .directives import DirectiveLocation from .scalars import GraphQLBoolean, GraphQLString +# Necessary for static type checking if False: # flake8: noqa from ..execution.base import ResolveInfo from .definition import GraphQLInputObjectField diff --git a/graphql/type/scalars.py b/graphql/type/scalars.py index 0169e825..137cf279 100644 --- a/graphql/type/scalars.py +++ b/graphql/type/scalars.py @@ -3,6 +3,7 @@ from ..language.ast import BooleanValue, FloatValue, IntValue, StringValue from .definition import GraphQLScalarType +# Necessary for static type checking if False: # flake8: noqa from typing import Any, Optional, Union diff --git a/graphql/type/schema.py b/graphql/type/schema.py index 54e0a09f..3fe84659 100644 --- a/graphql/type/schema.py +++ b/graphql/type/schema.py @@ -5,6 +5,7 @@ from .introspection import IntrospectionSchema from .typemap import GraphQLTypeMap +# Necessary for static type checking if False: # flake8: noqa from .definition import ( GraphQLNamedType, diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index 146bd129..f492b7de 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -15,6 +15,7 @@ is_output_type, ) +# Necessary for static type checking if False: # flake8: noqa from ..type.definition import GraphQLNamedType from typing import Any, List, Optional, Union, Dict, Set, Mapping, DefaultDict diff --git a/graphql/utils/ast_to_code.py b/graphql/utils/ast_to_code.py index 2db01b35..07b8068b 100644 --- a/graphql/utils/ast_to_code.py +++ b/graphql/utils/ast_to_code.py @@ -1,6 +1,7 @@ from ..language.ast import Node from ..language.parser import Loc +# Necessary for static type checking if False: # flake8: noqa from typing import Any diff --git a/graphql/utils/concat_ast.py b/graphql/utils/concat_ast.py index 8685bbc0..1f5cfdc0 100644 --- a/graphql/utils/concat_ast.py +++ b/graphql/utils/concat_ast.py @@ -2,6 +2,7 @@ from ..language.ast import Document +# Necessary for static type checking if False: # flake8: noqa from typing import Iterable diff --git a/graphql/utils/get_field_def.py b/graphql/utils/get_field_def.py index 5b06973f..b690fbfb 100644 --- a/graphql/utils/get_field_def.py +++ b/graphql/utils/get_field_def.py @@ -5,6 +5,7 @@ TypeNameMetaFieldDef, ) +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import Field from ..type.definition import GraphQLField, GraphQLInterfaceType, GraphQLObjectType diff --git a/graphql/utils/get_operation_ast.py b/graphql/utils/get_operation_ast.py index 56dccd4e..cd5ba26d 100644 --- a/graphql/utils/get_operation_ast.py +++ b/graphql/utils/get_operation_ast.py @@ -1,5 +1,6 @@ from ..language import ast +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import Document, OperationDefinition from typing import Optional diff --git a/graphql/utils/is_valid_literal_value.py b/graphql/utils/is_valid_literal_value.py index 9e99d587..0949e6f4 100644 --- a/graphql/utils/is_valid_literal_value.py +++ b/graphql/utils/is_valid_literal_value.py @@ -8,6 +8,7 @@ GraphQLScalarType, ) +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import ObjectValue, StringValue from ..type.definition import GraphQLInputObjectType, GraphQLScalarType diff --git a/graphql/utils/is_valid_value.py b/graphql/utils/is_valid_value.py index 2dd83bfc..8b403c94 100644 --- a/graphql/utils/is_valid_value.py +++ b/graphql/utils/is_valid_value.py @@ -15,6 +15,7 @@ GraphQLScalarType, ) +# Necessary for static type checking if False: # flake8: noqa from typing import Any, List diff --git a/graphql/utils/quoted_or_list.py b/graphql/utils/quoted_or_list.py index c968b73f..8931cec1 100644 --- a/graphql/utils/quoted_or_list.py +++ b/graphql/utils/quoted_or_list.py @@ -1,5 +1,6 @@ import functools +# Necessary for static type checking if False: # flake8: noqa from typing import List diff --git a/graphql/utils/schema_printer.py b/graphql/utils/schema_printer.py index 5fe2df68..30a28abd 100644 --- a/graphql/utils/schema_printer.py +++ b/graphql/utils/schema_printer.py @@ -11,6 +11,7 @@ from .ast_from_value import ast_from_value +# Necessary for static type checking if False: # flake8: noqa from ..type.definition import ( GraphQLArgument, diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index 4789df26..ba8867e1 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -7,6 +7,7 @@ is_abstract_type, ) +# Necessary for static type checking if False: # flake8: noqa from ..type.definition import ( GraphQLScalarType, diff --git a/graphql/utils/type_from_ast.py b/graphql/utils/type_from_ast.py index c76a2d28..1694cfd4 100644 --- a/graphql/utils/type_from_ast.py +++ b/graphql/utils/type_from_ast.py @@ -1,6 +1,7 @@ from ..language import ast from ..type.definition import GraphQLList, GraphQLNonNull +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import ListType, NamedType, NonNullType from ..type.definition import GraphQLNamedType diff --git a/graphql/utils/type_info.py b/graphql/utils/type_info.py index 6a17de9b..76433eb6 100644 --- a/graphql/utils/type_info.py +++ b/graphql/utils/type_info.py @@ -11,6 +11,7 @@ from .get_field_def import get_field_def from .type_from_ast import type_from_ast +# Necessary for static type checking if False: # flake8: noqa from ..type.schema import GraphQLSchema from ..type.definition import ( diff --git a/graphql/utils/value_from_ast.py b/graphql/utils/value_from_ast.py index f8a78c70..ff012896 100644 --- a/graphql/utils/value_from_ast.py +++ b/graphql/utils/value_from_ast.py @@ -7,6 +7,7 @@ GraphQLScalarType, ) +# Necessary for static type checking if False: # flake8: noqa from ..language.ast import Node from ..type.definition import GraphQLType diff --git a/graphql/validation/rules/__init__.py b/graphql/validation/rules/__init__.py index e9f19cbf..056a530d 100644 --- a/graphql/validation/rules/__init__.py +++ b/graphql/validation/rules/__init__.py @@ -23,6 +23,7 @@ from .variables_are_input_types import VariablesAreInputTypes from .variables_in_allowed_position import VariablesInAllowedPosition +# Necessary for static type checking if False: # flake8: noqa from typing import List, Type from .base import ValidationRule diff --git a/graphql/validation/rules/arguments_of_correct_type.py b/graphql/validation/rules/arguments_of_correct_type.py index d9d7d950..7b9f87d3 100644 --- a/graphql/validation/rules/arguments_of_correct_type.py +++ b/graphql/validation/rules/arguments_of_correct_type.py @@ -3,6 +3,7 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Argument from typing import Any, List, Union diff --git a/graphql/validation/rules/base.py b/graphql/validation/rules/base.py index 821dd747..53541c9c 100644 --- a/graphql/validation/rules/base.py +++ b/graphql/validation/rules/base.py @@ -1,5 +1,6 @@ from ...language.visitor import Visitor +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext diff --git a/graphql/validation/rules/default_values_of_correct_type.py b/graphql/validation/rules/default_values_of_correct_type.py index d09500c4..d35c0872 100644 --- a/graphql/validation/rules/default_values_of_correct_type.py +++ b/graphql/validation/rules/default_values_of_correct_type.py @@ -4,6 +4,7 @@ from ...utils.is_valid_literal_value import is_valid_literal_value from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Document, OperationDefinition, SelectionSet from typing import List, Union diff --git a/graphql/validation/rules/fields_on_correct_type.py b/graphql/validation/rules/fields_on_correct_type.py index 03a68984..fdcec447 100644 --- a/graphql/validation/rules/fields_on_correct_type.py +++ b/graphql/validation/rules/fields_on_correct_type.py @@ -7,6 +7,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/fragments_on_composite_types.py b/graphql/validation/rules/fragments_on_composite_types.py index e775b700..33324b40 100644 --- a/graphql/validation/rules/fragments_on_composite_types.py +++ b/graphql/validation/rules/fragments_on_composite_types.py @@ -3,6 +3,7 @@ from ...type.definition import is_composite_type from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/known_argument_names.py b/graphql/validation/rules/known_argument_names.py index e7b4839a..96966a8c 100644 --- a/graphql/validation/rules/known_argument_names.py +++ b/graphql/validation/rules/known_argument_names.py @@ -4,6 +4,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Argument from typing import Any, List, Union diff --git a/graphql/validation/rules/known_type_names.py b/graphql/validation/rules/known_type_names.py index b0a95aeb..4c68c27b 100644 --- a/graphql/validation/rules/known_type_names.py +++ b/graphql/validation/rules/known_type_names.py @@ -3,6 +3,7 @@ from ...utils.suggestion_list import suggestion_list from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import NamedType from typing import Any diff --git a/graphql/validation/rules/lone_anonymous_operation.py b/graphql/validation/rules/lone_anonymous_operation.py index 89c480f6..51b1ae23 100644 --- a/graphql/validation/rules/lone_anonymous_operation.py +++ b/graphql/validation/rules/lone_anonymous_operation.py @@ -2,6 +2,7 @@ from ...language import ast from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition diff --git a/graphql/validation/rules/no_fragment_cycles.py b/graphql/validation/rules/no_fragment_cycles.py index f9a85a1f..e3cc06b0 100644 --- a/graphql/validation/rules/no_fragment_cycles.py +++ b/graphql/validation/rules/no_fragment_cycles.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, FragmentSpread diff --git a/graphql/validation/rules/no_undefined_variables.py b/graphql/validation/rules/no_undefined_variables.py index 8a9ed3d3..59df5bb0 100644 --- a/graphql/validation/rules/no_undefined_variables.py +++ b/graphql/validation/rules/no_undefined_variables.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition diff --git a/graphql/validation/rules/no_unused_fragments.py b/graphql/validation/rules/no_unused_fragments.py index e8d2dfc1..320a0c4a 100644 --- a/graphql/validation/rules/no_unused_fragments.py +++ b/graphql/validation/rules/no_unused_fragments.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, FragmentDefinition diff --git a/graphql/validation/rules/no_unused_variables.py b/graphql/validation/rules/no_unused_variables.py index 65b50337..49b81faf 100644 --- a/graphql/validation/rules/no_unused_variables.py +++ b/graphql/validation/rules/no_unused_variables.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, VariableDefinition diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index ae8ee6c5..8506e2cd 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -17,6 +17,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import ( diff --git a/graphql/validation/rules/possible_fragment_spreads.py b/graphql/validation/rules/possible_fragment_spreads.py index d8bf329c..460d9191 100644 --- a/graphql/validation/rules/possible_fragment_spreads.py +++ b/graphql/validation/rules/possible_fragment_spreads.py @@ -3,6 +3,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/provided_non_null_arguments.py b/graphql/validation/rules/provided_non_null_arguments.py index 5558fd6d..bfdbabe8 100644 --- a/graphql/validation/rules/provided_non_null_arguments.py +++ b/graphql/validation/rules/provided_non_null_arguments.py @@ -2,6 +2,7 @@ from ...type.definition import GraphQLNonNull from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Optional, Union diff --git a/graphql/validation/rules/scalar_leafs.py b/graphql/validation/rules/scalar_leafs.py index 76d25a24..a36c4e8d 100644 --- a/graphql/validation/rules/scalar_leafs.py +++ b/graphql/validation/rules/scalar_leafs.py @@ -2,6 +2,7 @@ from ...type.definition import get_named_type, is_leaf_type from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ...language.ast import Field, InlineFragment from typing import Any, List, Union diff --git a/graphql/validation/rules/unique_argument_names.py b/graphql/validation/rules/unique_argument_names.py index e59a5f85..4f7cefc1 100644 --- a/graphql/validation/rules/unique_argument_names.py +++ b/graphql/validation/rules/unique_argument_names.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Field, InlineFragment, Argument, Name diff --git a/graphql/validation/rules/unique_fragment_names.py b/graphql/validation/rules/unique_fragment_names.py index cc67f8a4..aa7fa5ba 100644 --- a/graphql/validation/rules/unique_fragment_names.py +++ b/graphql/validation/rules/unique_fragment_names.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, Name diff --git a/graphql/validation/rules/unique_input_field_names.py b/graphql/validation/rules/unique_input_field_names.py index dde35ec9..b0e64077 100644 --- a/graphql/validation/rules/unique_input_field_names.py +++ b/graphql/validation/rules/unique_input_field_names.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Argument, ObjectValue, ObjectField, Name diff --git a/graphql/validation/rules/unique_operation_names.py b/graphql/validation/rules/unique_operation_names.py index d44d6ee2..f7546595 100644 --- a/graphql/validation/rules/unique_operation_names.py +++ b/graphql/validation/rules/unique_operation_names.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, Name diff --git a/graphql/validation/rules/unique_variable_names.py b/graphql/validation/rules/unique_variable_names.py index 425d43f4..6d7bfcbf 100644 --- a/graphql/validation/rules/unique_variable_names.py +++ b/graphql/validation/rules/unique_variable_names.py @@ -1,6 +1,7 @@ from ...error import GraphQLError from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition diff --git a/graphql/validation/rules/variables_in_allowed_position.py b/graphql/validation/rules/variables_in_allowed_position.py index 5bdd5da5..8a0209d1 100644 --- a/graphql/validation/rules/variables_in_allowed_position.py +++ b/graphql/validation/rules/variables_in_allowed_position.py @@ -4,6 +4,7 @@ from ...utils.type_from_ast import type_from_ast from .base import ValidationRule +# Necessary for static type checking if False: # flake8: noqa from ..validation import ValidationContext from ...language.ast import Document, OperationDefinition, VariableDefinition diff --git a/graphql/validation/validation.py b/graphql/validation/validation.py index 9422ad56..ed647742 100644 --- a/graphql/validation/validation.py +++ b/graphql/validation/validation.py @@ -4,6 +4,7 @@ from ..utils.type_info import TypeInfo from .rules import specified_rules +# Necessary for static type checking if False: # flake8: noqa from typing import List, Union, Optional, Dict, Set, Any, Type from ..language.ast import Document, OperationDefinition, SelectionSet, Node From e6d11f6a24ad4a978b8cbe46bf7ee89fc44e28dd Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 2 Jul 2018 09:59:47 -0700 Subject: [PATCH 12/12] Improved executed types --- graphql/execution/executor.py | 22 ++++++++++------------ graphql/graphql.py | 5 +++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 75f2ac95..7e49fdf8 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -66,7 +66,7 @@ def execute( allow_subscriptions=False, # type: bool **options # type: Any ): - # type: (...) -> ExecutionResult + # type: (...) -> Union[ExecutionResult, Promise[ExecutionResult]] if root is None and "root_value" in options: warnings.warn( @@ -120,16 +120,16 @@ def execute( ) def promise_executor(v): - # type: (Optional[Any]) -> Union[OrderedDict, Promise, Observable] + # type: (Optional[Any]) -> Union[Dict, Promise[Dict], Observable] return execute_operation(exe_context, exe_context.operation, root) def on_rejected(error): - # type: (Exception) -> Optional[Any] + # type: (Exception) -> None exe_context.errors.append(error) return None def on_resolve(data): - # type: (Union[None, OrderedDict, Observable]) -> Union[ExecutionResult, Observable] + # type: (Union[None, Dict, Observable]) -> Union[ExecutionResult, Observable] if isinstance(data, Observable): return data @@ -158,7 +158,7 @@ def execute_operation( operation, # type: OperationDefinition root_value, # type: Any ): - # type: (...) -> Union[OrderedDict, Promise] + # type: (...) -> Union[Dict, Promise[Dict]] type = get_operation_root_type(exe_context.schema, operation) fields = collect_fields( exe_context, type, operation.selection_set, DefaultOrderedDict(list), set() @@ -188,7 +188,7 @@ def execute_fields_serially( ): # type: (...) -> Promise def execute_field_callback(results, response_name): - # type: (OrderedDict, str) -> Union[OrderedDict, Promise] + # type: (Dict, str) -> Union[Dict, Promise[Dict]] field_asts = fields[response_name] result = resolve_field( exe_context, @@ -204,7 +204,7 @@ def execute_field_callback(results, response_name): if is_thenable(result): def collect_result(resolved_result): - # type: (OrderedDict) -> OrderedDict + # type: (Dict) -> Dict results[response_name] = resolved_result return results @@ -232,7 +232,7 @@ def execute_fields( path, # type: List[Union[int, str]] info, # type: Optional[ResolveInfo] ): - # type: (...) -> Union[OrderedDict, Promise] + # type: (...) -> Union[Dict, Promise[Dict]] contains_promise = False final_results = OrderedDict() @@ -271,10 +271,8 @@ def subscribe_fields( def on_error(error): subscriber_exe_context.report_error(error) - def map_result( - data # type: Union[Dict[str, None], Dict[str, OrderedDict], Dict[str, str]] - ): - # type: (...) -> ExecutionResult + def map_result(data): + # type: (Dict[str, Any]) -> ExecutionResult if subscriber_exe_context.errors: result = ExecutionResult(data=data, errors=subscriber_exe_context.errors) else: diff --git a/graphql/graphql.py b/graphql/graphql.py index 7e22be53..89ccf386 100644 --- a/graphql/graphql.py +++ b/graphql/graphql.py @@ -5,6 +5,7 @@ # Necessary for static type checking if False: # flake8: noqa + from promise import Promise from rx import Observable from typing import Any, Union, Optional from .language.ast import Document @@ -35,7 +36,7 @@ def graphql(*args, **kwargs): - # type: (*Any, **Any) -> Union[ExecutionResult, Observable] + # type: (*Any, **Any) -> Union[ExecutionResult, Observable, Promise[ExecutionResult]] return_promise = kwargs.get("return_promise", False) if return_promise: return execute_graphql_as_promise(*args, **kwargs) @@ -54,7 +55,7 @@ def execute_graphql( backend=None, # type: Optional[Any] **execute_options # type: Any ): - # type: (...) -> Union[ExecutionResult, Observable] + # type: (...) -> Union[ExecutionResult, Observable, Promise[ExecutionResult]] try: if backend is None: backend = get_default_backend()