Пример #1
0
def test_custom_python_name_in_input_object():
    arg = Argument(
        "foo",
        NonNullType(
            InputObjectType(
                "Foo",
                [InputField("field", NonNullType(Int), python_name="value")],
            )
        ),
    )
    field = Field("test", Int, [arg])
    node = _test_node(parse_value("{ field: 42 }"))
    assert coerce_argument_values(field, node) == {"foo": {"value": 42}}
Пример #2
0
def test_replace_interface_in_implementers(schema: Schema) -> None:
    NewObject = InterfaceType(
        "Object",
        fields=[
            Field("id", NonNullType(ID)),
            Field("name", NonNullType(String)),
        ],
    )

    schema._replace_types_and_directives({"Object": NewObject})

    assert (cast(ObjectType, schema.get_type("Person")).interfaces[0] is cast(
        ObjectType, schema.get_type("Animal")).interfaces[0] is
            schema.types["Object"] is NewObject)
Пример #3
0
async def test_full_response_path_is_included_on_error(raiser,
                                                       assert_execution):
    A = ObjectType(
        "A",
        [
            Field("nullableA", lambda: A, resolver=lambda *_: {}),
            Field("nonNullA", lambda: NonNullType(A), resolver=lambda *_: {}),
            Field(
                "raises",
                lambda: NonNullType(String),
                resolver=raiser(ResolverError, "Catch me if you can"),
            ),
        ],
    )  # type: ObjectType

    await assert_execution(
        Schema(
            ObjectType(
                "query",
                [Field("nullableA", lambda: A, resolver=lambda *_: {})])),
        """
        query {
            nullableA {
                aliasedA: nullableA {
                    nonNullA {
                        anotherA: nonNullA {
                            raises
                        }
                    }
                }
            }
        }
        """,
        expected_data={
            "nullableA": {
                "aliasedA": {
                    "nonNullA": {
                        "anotherA": {
                            "raises": None
                        }
                    }
                }
            }
        },
        expected_errors=[(
            "Catch me if you can",
            (134, 140),
            "nullableA.aliasedA.nonNullA.anotherA.raises",
        )],
    )
Пример #4
0
async def test_raises_on_missing_subscription_resolver(starwars_schema):
    schema = subscription_schema(
        Field(
            "counter",
            NonNullType(Int),
            args=[Argument("delay", NonNullType(Float))],
            resolver=lambda event, *_, **__: event,
        )
    )

    with pytest.raises(RuntimeError):
        subscribe(
            schema,
            parse("subscription { counter(delay: 0.001) }"),
            runtime=AsyncIORuntime(),
        )
Пример #5
0
def test_null_non_nullable_type():
    _test(
        None,
        NonNullType(Int),
        None,
        "Expected non-nullable type Int! not to be null",
    )
Пример #6
0
async def test_raises_on_unsupported_runtime():
    schema = subscription_schema(
        Field(
            "counter",
            NonNullType(Int),
            args=[Argument("delay", NonNullType(Float))],
            subscription_resolver=lambda *_, delay: AsyncCounter(delay, 10),
            resolver=lambda event, *_, **__: event,
        )
    )

    with pytest.raises(RuntimeError):
        subscribe(
            schema,
            parse("subscription { counter(delay: 0.001) }"),
            runtime=BlockingRuntime(),  # type: ignore
        )
Пример #7
0
async def test_nullable_list_of_non_nullable_items_ok(assert_execution, data,
                                                      expected):
    await run_test(
        ListType(NonNullType(Int)),
        data,
        expected_data=expected,
        assert_execution=assert_execution,
    )
Пример #8
0
def test_string_field_with_non_null_int_arg():
    schema = _single_field_schema(String,
                                  args=[Argument("argOne", NonNullType(Int))])
    assert print_schema(schema, indent="    ") == dedent("""
        type Query {
            singleField(argOne: Int!): String
        }
        """)
Пример #9
0
async def test_nullable_list_of_non_nullable_items_fail(
        assert_execution, data, expected_err):
    await run_test(
        ListType(NonNullType(Int)),
        data,
        expected_errors=[expected_err],
        assert_execution=assert_execution,
    )
Пример #10
0
def test_reject_object_with_null_interface_non_null_field():
    iface = InterfaceType("IFace", [Field("f", NonNullType(String))])
    schema = _single_type_schema(
        ObjectType("SomeObject", [Field("f", String)], interfaces=[iface]))
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert ('Interface field "IFace.f" expects type "String!" but '
            '"SomeObject.f" is type "String"' in str(exc_info.value))
Пример #11
0
def test_missing_non_nullable_arg_without_default():
    arg = Argument("foo", NonNullType(Int))
    field = Field("test", Int, [arg])
    node = _test_node()
    with pytest.raises(CoercionError) as exc_info:
        coerce_argument_values(field, node)
    assert (
        str(exc_info.value)
        == 'Argument "foo" of required type "Int!" was not provided'
    )
Пример #12
0
def test_provided_unknown_variable_without_default_non_nullable():
    arg = Argument("foo", NonNullType(Int))
    field = Field("test", Int, [arg])
    node = _test_node(_var("bar"))
    with pytest.raises(CoercionError) as exc_info:
        coerce_argument_values(field, node)
    assert str(exc_info.value) == (
        'Argument "foo" of required type "Int!" was provided the missing '
        'variable "$bar"'
    )
Пример #13
0
async def test_raises_on_multiple_fields(starwars_schema):
    schema = subscription_schema(
        Field(
            "counter",
            NonNullType(Int),
            args=[Argument("delay", NonNullType(Float))],
            subscription_resolver=lambda *_, delay: AsyncCounter(delay, 10),
            resolver=lambda event, *_, **__: event,
        )
    )

    with pytest.raises(ExecutionError):
        subscribe(
            schema,
            parse(
                "subscription { counter(delay: 0.001), other: counter(delay: 0.001) }"
            ),
            runtime=AsyncIORuntime(),
        )
Пример #14
0
async def test_simple_counter_subscription_with_error():
    def resolver(event, *_, **__):
        if event % 2:
            raise ResolverError("I don't like odd numbers.")
        return event

    schema = subscription_schema(
        Field(
            "counter",
            NonNullType(Int),
            args=[Argument("delay", NonNullType(Float))],
            subscription_resolver=lambda *_, delay: AsyncCounter(delay, 10),
            resolver=resolver,
        )
    )

    response_stream = await subscribe(
        schema,
        parse("subscription { counter(delay: 0.001) }"),
        runtime=AsyncIORuntime(),
    )

    assert [
        (
            {"data": {"counter": x}}
            if not x % 2
            else (
                {
                    "data": {"counter": None},  # type: ignore
                    "errors": [  # type: ignore
                        {
                            "locations": [{"column": 16, "line": 1}],
                            "message": "I don't like odd numbers.",
                            "path": ["counter"],
                        }
                    ],
                }
            )
        )
        for x in range(1, 11)
    ] == [r.response() for r in await collect_async_iterator(response_stream)]
Пример #15
0
def test_reject_object_which_implements_interface_along_with_required_args():
    iface = InterfaceType("IFace", [Field("f", String)])
    schema = _single_type_schema(
        ObjectType(
            "SomeObject",
            [Field("f", String, [Argument("arg", NonNullType(String))])],
            interfaces=[iface],
        ))
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert ('Object field argument "SomeObject.f.arg" is of required '
            'type "String!" but is not provided by interface field "IFace.f"'
            ) in str(exc_info.value)
Пример #16
0
async def test_simple_counter_subscription():
    schema = subscription_schema(
        Field(
            "counter",
            NonNullType(Int),
            args=[Argument("delay", NonNullType(Float))],
            resolver=lambda event, *_, **__: event,
        )
    )

    @schema.subscription("Subscription.counter")
    def counter_subscription(*_, delay):
        return AsyncCounter(delay, 10)

    response_stream = await subscribe(
        schema,
        parse("subscription { counter(delay: 0.001) }"),
        runtime=AsyncIORuntime(),
    )

    assert [{"data": {"counter": x}} for x in range(1, 11)] == [
        r.response() for r in await collect_async_iterator(response_stream)
    ]
Пример #17
0
def test_replace_type_in_union(schema: Schema) -> None:
    NewPerson = ObjectType(
        "Person",
        fields=(list(cast(ObjectType, schema.types["Person"]).fields) +
                [Field("last_name", NonNullType(String))]),
        interfaces=[cast(InterfaceType, schema.types["Object"])],
    )

    schema._replace_types_and_directives({"Person": NewPerson})

    assert cast(ObjectType, schema.get_type("Person")) is NewPerson

    union_type = cast(UnionType, schema.get_type("LivingBeing"))

    assert NewPerson in union_type.types
    assert 2 == len(union_type.types)
Пример #18
0
 def schema(self) -> Schema:
     return _single_type_schema(
         ObjectType(
             "Object",
             [
                 Field(
                     "field",
                     String,
                     [
                         Argument("a", String),
                         Argument("b", NonNullType(String)),
                         Argument("c", String, default_value="c"),
                     ],
                 )
             ],
         ))
Пример #19
0
def schema() -> Schema:
    Object = InterfaceType("Object", fields=[Field("id", NonNullType(ID))])

    Person = ObjectType(
        "Person",
        fields=[
            Field("id", NonNullType(ID)),
            Field("name", NonNullType(String)),
            Field("pets", NonNullType(ListType(lambda: Animal))),
        ],
        interfaces=[Object],
    )

    Animal = ObjectType(
        "Animal",
        fields=[
            Field("id", NonNullType(ID)),
            Field("name", NonNullType(String)),
            Field("owner", Person),
        ],
        interfaces=[Object],
    )

    LivingBeing = UnionType("LivingBeing", [Person, Animal])

    CreatePersonInput = InputObjectType(
        "CreatePersonInput",
        [InputField("id", ID),
         InputField("name", NonNullType(String))],
    )

    return Schema(
        query_type=ObjectType(
            "Query",
            fields=[
                Field("person", Person, args=[Argument("id", ID)]),
                Field("pet", Animal, args=[Argument("id", ID)]),
                Field("living_being", LivingBeing, args=[Argument("id", ID)]),
            ],
        ),
        mutation_type=ObjectType(
            "Mutation", fields=[Field("createPerson", CreatePersonInput)]),
    )
Пример #20
0
def test_Enum_for_a_known_enum_names():
    _test("FOO", Enum, "InternalFoo")
    _test("BAR", Enum, 123456789)


def test_Enum_raises_for_misspelled_enum_value():
    _test("foo", Enum, None, "Invalid name foo for enum TestEnum")


def test_Enum_raises_for_incorrect_value_type():
    _test(123, Enum, None, "Expected type TestEnum")


Input = InputObjectType(
    "TestInputObject",
    [InputField("foo", NonNullType(Int)), InputField("bar", Int)],
)


def test_InputObject_for_valid_input():
    _test({"foo": 123}, Input, {"foo": 123})


def test_InputObject_raises_for_non_dict_input():
    _test(123, Input, None, "Expected type TestInputObject to be an object")


def test_InputObject_raises_for_invalid_field():
    _test(
        {"foo": "abc"},
        Input,
Пример #21
0
def _type_modifiers(t):
    return [t, ListType(t), NonNullType(t), NonNullType(ListType(t))]
Пример #22
0

def test_raises_on_non_input_type():
    with pytest.raises(TypeError):
        ast_node_from_value(42, ObjectType("Foo", [Field("foo", Int)]))


@pytest.mark.parametrize(
    "value, input_type, expected",
    [
        (True, Boolean, _ast.BooleanValue(value=True)),
        (False, Boolean, _ast.BooleanValue(value=False)),
        (None, Boolean, _ast.NullValue()),
        (1, Boolean, _ast.BooleanValue(value=True)),
        (0, Boolean, _ast.BooleanValue(value=False)),
        (0, NonNullType(Boolean), _ast.BooleanValue(value=False)),
        (
            None,
            NonNullType(Boolean),
            ValueError('Value of type "Boolean!" cannot be null'),
        ),
        (-1, Int, _ast.IntValue(value="-1")),
        (123.0, Int, _ast.IntValue(value="123")),
        (1e4, Int, _ast.IntValue(value="10000")),
        (
            123.5,
            Int,
            ValueError("Int cannot represent non integer value: 123.5"),
        ),
        (
            1e40,
Пример #23
0
def test_as_non_null():
    assert UUID.as_non_null() == NonNullType(UUID)
Пример #24
0
def schema_2():
    SomeBox = InterfaceType(
        "SomeBox",
        [Field("deepBox", lambda: SomeBox),
         Field("unrelatedField", String)],
    )  # type: InterfaceType

    StringBox = ObjectType(
        "StringBox",
        [
            Field("scalar", String),
            Field("deepBox", lambda: StringBox),
            Field("unrelatedField", String),
            Field("listStringBox", lambda: ListType(StringBox)),
            Field("stringBox", lambda: StringBox),
            Field("intBox", lambda: IntBox),
        ],
        [SomeBox],
    )  # type: ObjectType

    IntBox = ObjectType(
        "IntBox",
        [
            Field("scalar", Int),
            Field("deepBox", lambda: IntBox),
            Field("unrelatedField", String),
            Field("listStringBox", lambda: ListType(StringBox)),
            Field("stringBox", lambda: StringBox),
            Field("intBox", lambda: IntBox),
        ],
        [SomeBox],
    )  # type: ObjectType

    NonNullStringBox1 = InterfaceType("NonNullStringBox1",
                                      [Field("scalar", NonNullType(String))])

    NonNullStringBox1Impl = ObjectType(
        "NonNullStringBox1Impl",
        [
            Field("scalar", NonNullType(String)),
            Field("unrelatedField", String),
            Field("deepBox", SomeBox),
        ],
        [SomeBox, NonNullStringBox1],
    )

    NonNullStringBox2 = InterfaceType("NonNullStringBox2",
                                      [Field("scalar", NonNullType(String))])

    NonNullStringBox2Impl = ObjectType(
        "NonNullStringBox2Impl",
        [
            Field("scalar", NonNullType(String)),
            Field("unrelatedField", String),
            Field("deepBox", SomeBox),
        ],
        [SomeBox, NonNullStringBox2],
    )

    Connection = ObjectType(
        "Connection",
        [
            Field(
                "edges",
                ListType(
                    ObjectType(
                        "Edge",
                        [
                            Field(
                                "node",
                                ObjectType(
                                    "Node",
                                    [Field("id", ID),
                                     Field("name", String)],
                                ),
                            )
                        ],
                    )),
            )
        ],
    )

    yield Schema(
        ObjectType(
            "QueryRoot",
            [Field("someBox", SomeBox),
             Field("connection", Connection)],
        ),
        types=[
            IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl
        ],
    )
Пример #25
0
class TestNonNullArguments:
    schema_with_null_args = Schema(
        ObjectType(
            "Query",
            [
                Field(
                    "withNonNullArg",
                    String,
                    args=[Argument("cannotBeNull", NonNullType(String))],
                    resolver=lambda *_, **args: json.dumps(
                        args.get("cannotBeNull", "NOT PROVIDED")),
                )
            ],
        ))

    async def test_non_null_literal(self):
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query {
                withNonNullArg (cannotBeNull: "literal value")
            }
            """,
            expected_data={"withNonNullArg": '"literal value"'},
            expected_errors=[],
        )

    async def test_non_null_variable(self):
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query ($testVar: String!) {
                withNonNullArg (cannotBeNull: $testVar)
            }
            """,
            variables={"testVar": "variable value"},
            expected_data={"withNonNullArg": '"variable value"'},
            expected_errors=[],
        )

    async def test_missing_variable_with_default(self):
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query ($testVar: String = "default value") {
                withNonNullArg (cannotBeNull: $testVar)
            }
            """,
            expected_data={"withNonNullArg": '"default value"'},
            expected_errors=[],
        )

    async def test_missing(self):
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query {
                withNonNullArg
            }
            """,
            expected_data={"withNonNullArg": None},
            expected_errors=[(
                'Argument "cannotBeNull" of required type "String!" was '
                "not provided",
                (12, 26),
                "withNonNullArg",
            )],
        )

    async def test_null_literal(self):
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query {
                withNonNullArg (cannotBeNull: null)
            }
            """,
            expected_data={"withNonNullArg": None},
            expected_errors=[(
                'Argument "cannotBeNull" of type "String!" was provided '
                "invalid value null (Expected non null value.)",
                (12, 47),
                "withNonNullArg",
            )],
        )

    async def test_missing_variable(self):
        # Differs from reference implementation as a missing variable will
        # abort the full execution. This is consistent as all variables defined
        # must be used in an operation and so a missing variables for a non null
        # type should break.
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query ($testVar: String!) {
                withNonNullArg (cannotBeNull: $testVar)
            }
            """,
            expected_exc=(
                VariablesCoercionError,
                ('Variable "$testVar" of required type "String!" was not '
                 "provided."),
            ),
        )

    async def test_null_variable(self):
        # Differs from reference implementation as a null variable provided for
        # a non null type will abort the full execution.
        assert_sync_execution(
            self.schema_with_null_args,
            """
            query ($testVar: String!) {
                withNonNullArg (cannotBeNull: $testVar)
            }
            """,
            variables={"testVar": None},
            expected_exc=(
                VariablesCoercionError,
                ('Variable "$testVar" of required type "String!" '
                 "must not be null."),
            ),
        )
Пример #26
0
def test_accept_object_with_non_null_interface_null_field():
    iface = InterfaceType("IFace", [Field("f", String)])
    schema = _single_type_schema(
        ObjectType("SomeObject", [Field("f", NonNullType(String))],
                   interfaces=[iface]))
    schema.validate()
Пример #27
0
        EnumValue("EMPIRE", 5, description="Released in 1980."),
        EnumValue("JEDI", 6, description="Released in 1983."),
    ],
    description="One of the films in the Star Wars Trilogy",
)


def resolve_character_type(character, *_):
    return {"Human": Human, "Droid": Droid}[character["type"]]


Character = InterfaceType(
    "Character",
    [
        Field(
            "id", NonNullType(String), description="The id of the character."
        ),
        Field("name", String, description="The name of the character."),
        Field(
            "friends",
            ListType(lambda: Character),
            description=(
                "The friends of the character, or an empty list if they have "
                "none."
            ),
        ),
        Field(
            "appearsIn",
            ListType(Episode),
            description="Which movies they appear in.",
        ),
Пример #28
0

class _obj:
    def __init__(self, **attrs):
        for k, v in attrs.items():
            setattr(self, k, v)


# All test coroutines will be treated as marked.
pytestmark = pytest.mark.asyncio

NullNonNullDataType = ObjectType(
    "DataType",
    [
        Field("scalar", String),
        Field("scalarNonNull", NonNullType(String)),
        Field("nested", lambda: NullNonNullDataType),
        Field("nestedNonNull", lambda: NonNullType(NullNonNullDataType)),
    ],
)  # type: ObjectType

NullAndNonNullSchema = Schema(NullNonNullDataType)


async def test_nulls_nullable_field(assert_execution):
    await assert_execution(
        NullAndNonNullSchema,
        "query Q { scalar }",
        initial_value=dict(scalar=None),
        expected_data={"scalar": None},
    )
Пример #29
0

def _complex_parse(value):
    if value == "SerializedValue":
        return "DeserializedValue"
    raise ValueError(value)


ComplexScalar = ScalarType("ComplexScalar", _complex_parse, _complex_parse)

TestInputObject = InputObjectType(
    "TestInputObject",
    [
        InputField("a", String),
        InputField("b", ListType(String)),
        InputField("c", NonNullType(String)),
        InputField("d", ComplexScalar),
    ],
)

TestNestedInputObject = InputObjectType(
    "TestNestedInputObject",
    [
        InputField("na", NonNullType(TestInputObject)),
        InputField("nb", NonNullType(String)),
    ],
)


def _inspect(name):
    def _inspect_resolver(*_, **args):
Пример #30
0
def schema():

    Being = InterfaceType(
        "Being", [Field("name", String, [Argument("surname", Boolean)])])

    Pet = InterfaceType(
        "Pet", [Field("name", String, [Argument("surname", Boolean)])])

    Canine = InterfaceType(
        "Canine", [Field("name", String, [Argument("surname", Boolean)])])

    DogCommand = EnumType(
        "DogCommand",
        [EnumValue("SIT", 0),
         EnumValue("HEEL", 1),
         EnumValue("DOWN", 2)],
    )

    FurColor = EnumType(
        "FurColor",
        [
            EnumValue("BROWN", 0),
            EnumValue("BLACK", 1),
            EnumValue("TAN", 2),
            EnumValue("SPOTTED", 3),
            EnumValue("NO_FUR", None),
            EnumValue("UNKNOWN", -1),
        ],
    )

    Dog = ObjectType(
        "Dog",
        [
            Field("name", String, args=[Argument("surname", Boolean)]),
            Field("nickname", String),
            Field("barkVolume", Int),
            Field("barks", Boolean),
            Field("doesKnowCommand", Boolean,
                  [Argument("dogCommand", DogCommand)]),
            Field(
                "isHousetrained",
                Boolean,
                [Argument("atOtherHomes", Boolean, True)],
            ),
            Field(
                "isAtLocation",
                Boolean,
                [Argument("x", Int), Argument("y", Int)],
            ),
        ],
        [Being, Pet, Canine],
    )

    Cat = ObjectType(
        "Cat",
        [
            Field("name", String, args=[Argument("surname", Boolean)]),
            Field("nickname", String),
            Field("meowVolume", Int),
            Field("meows", Boolean),
            Field("furColor", FurColor),
        ],
        [Being, Pet],
    )

    CatOrDog = UnionType("CatOrDog", [Dog, Cat])

    Intelligent = InterfaceType("Intelligent", [Field("iq", Int)])

    Human = ObjectType(
        "Human",
        lambda: [
            Field("name", String, args=[Argument("surname", Boolean)]),
            Field("iq", Int),
            Field("pets", ListType(Pet)),
            Field("relatives", ListType(Human)),
        ],
        [Being, Intelligent],
    )

    Alien = ObjectType(
        "Alien",
        [
            Field("name", String, args=[Argument("surname", Boolean)]),
            Field("iq", Int),
            Field("numEyes", Int),
        ],
        [Being, Intelligent],
    )

    DogOrHuman = UnionType("DogOrHuman", [Dog, Human])

    HumanOrAlien = UnionType("HumanOrAlien", [Human, Alien])

    ComplexInput = InputObjectType(
        "ComplexInput",
        [
            InputField("requiredField", NonNullType(Boolean)),
            InputField(
                "nonNullField", NonNullType(Boolean), default_value=False),
            InputField("intField", Int),
            InputField("stringField", String),
            InputField("booleanField", Boolean),
            InputField("stringListField", ListType(String)),
        ],
    )

    ComplicatedArgs = ObjectType(
        "ComplicatedArgs",
        [
            Field("intArgField", String, [Argument("intArg", Int)]),
            Field(
                "nonNullIntArgField",
                String,
                [Argument("nonNullIntArg", NonNullType(Int))],
            ),
            Field("stringArgField", String, [Argument("stringArg", String)]),
            Field("booleanArgField", String,
                  [Argument("booleanArg", Boolean)]),
            Field("enumArgField", String, [Argument("enumArg", FurColor)]),
            Field("floatArgField", String, [Argument("floatArg", Float)]),
            Field("idArgField", String, [Argument("idArg", ID)]),
            Field(
                "stringListArgField",
                String,
                [Argument("stringListArg", ListType(String))],
            ),
            Field(
                "stringListNonNullArgField",
                String,
                [
                    Argument("stringListNonNullArg",
                             ListType(NonNullType(String)))
                ],
            ),
            Field(
                "complexArgField",
                String,
                [Argument("complexArg", ComplexInput)],
            ),
            Field(
                "multipleReqs",
                String,
                [
                    Argument("req1", NonNullType(Int)),
                    Argument("req2", NonNullType(Int)),
                ],
            ),
            Field(
                "nonNullFieldWithDefault",
                String,
                [Argument("arg", NonNullType(Int), default_value=0)],
            ),
            Field(
                "multipleOpts",
                String,
                [Argument("opt1", Int, 0),
                 Argument("opt2", Int, 0)],
            ),
            Field(
                "multipleOptAndReq",
                String,
                [
                    Argument("req1", NonNullType(Int)),
                    Argument("req2", NonNullType(Int)),
                    Argument("opt1", Int, 0),
                    Argument("opt2", Int, 0),
                ],
            ),
        ],
    )

    def _invalid(*args, **kwargs):
        raise ValueError("Invalid scalar is always invalid")

    def _stringify(value):
        return str(value)

    InvalidScalar = ScalarType("Invalid", _stringify, _invalid, _invalid)
    AnyScalar = ScalarType("Any", _stringify, lambda x: x)  # type: ScalarType

    return Schema(
        ObjectType(
            "QueryRoot",
            [
                Field("human", Human, [Argument("id", ID)]),
                Field("alien", Alien),
                Field("dog", Dog),
                Field("cat", Cat),
                Field("pet", Pet),
                Field("catOrDog", CatOrDog),
                Field("dogOrHuman", DogOrHuman),
                Field("humanOrAlien", HumanOrAlien),
                Field("humanOrAlien", HumanOrAlien),
                Field("complicatedArgs", ComplicatedArgs),
                Field("invalidArg", String, [Argument("arg", InvalidScalar)]),
                Field("anydArg", String, [Argument("arg", AnyScalar)]),
            ],
        ),
        types=[Cat, Dog, Human, Alien],
        directives=[
            Directive("onQuery", ["QUERY"]),
            Directive("onMutation", ["MUTATION"]),
            Directive("onSubscription", ["SUBSCRIPTION"]),
            Directive("onField", ["FIELD"]),
            Directive("onFragmentDefinition", ["FRAGMENT_DEFINITION"]),
            Directive("onFragmentSpread", ["FRAGMENT_SPREAD"]),
            Directive("onInlineFragment", ["INLINE_FRAGMENT"]),
            Directive("onSchema", ["SCHEMA"]),
            Directive("onScalar", ["SCALAR"]),
            Directive("onObject", ["OBJECT"]),
            Directive("onFieldDefinition", ["FIELD_DEFINITION"]),
            Directive("onArgumentDefinition", ["ARGUMENT_DEFINITION"]),
            Directive("onInterface", ["INTERFACE"]),
            Directive("onUnion", ["UNION"]),
            Directive("onEnum", ["ENUM"]),
            Directive("onEnumValue", ["ENUM_VALUE"]),
            Directive("onInputObject", ["INPUT_OBJECT"]),
            Directive("onInputFieldDefinition", ["INPUT_FIELD_DEFINITION"]),
        ],
    )