コード例 #1
0
def test_interfaces():
    Foo = InterfaceType("Foo", [Field("str", String)])
    Baz = InterfaceType("Baz", [Field("int", Int)])
    Bar = ObjectType(
        "Bar", [Field("str", String), Field("int", Int)],
        interfaces=[Foo, Baz])
    Query = ObjectType("Query", [Field("bar", Bar)])
    assert print_schema(Schema(Query), indent="    ") == dedent("""
        type Bar implements Foo & Baz {
            str: String
            int: Int
        }

        interface Baz {
            int: Int
        }

        interface Foo {
            str: String
        }

        type Query {
            bar: Bar
        }
        """)
コード例 #2
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_collects_multiple_errors():
    iface = InterfaceType("IFace", [Field("f", ListType(String))])

    bad_name_union = UnionType("#BadNameUnion", lambda: [object_type])
    empty_union = UnionType("EmptyUnion", [])

    object_type = ObjectType(
        "SomeObject",
        [
            Field("f", String),
            Field("__f", lambda: empty_union),
            Field("g", lambda: bad_name_union),
        ],
        interfaces=[iface],
    )  # type: ObjectType

    schema = _single_type_schema(object_type)

    with pytest.raises(SchemaValidationError) as exc_info:
        validate_schema(schema)

    assert set([str(e) for e in exc_info.value.errors]) == set([
        'Invalid name "__f".',
        'Interface field "IFace.f" expects type "[String]" but "SomeObject.f" '
        'is type "String"',
        'UnionType "EmptyUnion" must at least define one member',
        'Invalid type name "#BadNameUnion"',
    ])
コード例 #3
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_accept_object_fields_with_interface_subtype_of_interface_field():
    iface = InterfaceType("IFace",
                          [Field("f", lambda: iface)])  # type: InterfaceType
    obj = ObjectType("Obj", [Field("f", lambda: obj)],
                     interfaces=[iface])  # type: ObjectType
    schema = _single_type_schema(obj)
    schema.validate()
コード例 #4
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_reject_interface_with_no_field():
    iface = InterfaceType("BadInterface", [])
    schema = _single_type_schema(iface)
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert 'Type "BadInterface" must define at least one field' in str(
        exc_info.value)
コード例 #5
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_reject_interface_fields_with_non_output_type(type_):
    iface = InterfaceType("BadInterface", [Field("f", type_)])
    schema = _single_type_schema(iface)
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert ('Expected output type for field "f" on "BadInterface" '
            'but got "%s"' % type_) in str(exc_info.value)
コード例 #6
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
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))
コード例 #7
0
ファイル: test_abstract_types.py プロジェクト: lirsacc/py-gql
async def test_type_resolution_supports_object_attribute(assert_execution):
    PetType = InterfaceType("Pet", [Field("name", String)])

    DogType = ObjectType(
        "Dog",
        [Field("name", String), Field("woofs", Boolean)],
        interfaces=[PetType],
    )

    CatType = ObjectType(
        "Cat",
        [Field("name", String), Field("meows", Boolean)],
        interfaces=[PetType],
    )

    class Dog:
        __typename__ = "Dog"

        def __init__(self, name, woofs):
            self.name = name
            self.woofs = woofs

    class Cat:
        __typename__ = "Cat"

        def __init__(self, name, meows):
            self.name = name
            self.meows = meows

    schema = Schema(
        ObjectType(
            "Query",
            [
                Field(
                    "pets",
                    ListType(PetType),
                    resolver=lambda *_: [
                        Dog("Odie", True),
                        Cat("Garfield", False),
                    ],
                )
            ],
        ),
        types=[DogType, CatType],
    )

    await assert_execution(
        schema,
        """{
        pets {
            name
            __typename
            ... on Dog { woofs }
            ... on Cat { meows }
        }
        }""",
    )
コード例 #8
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_reject_object_fields_with_missing_interface_argument():
    iface = InterfaceType("IFace",
                          [Field("f", String, [Argument("arg", String)])])
    obj = ObjectType("Obj", [Field("f", String)], interfaces=[iface])
    schema = _single_type_schema(obj)
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert ('Interface field argument "IFace.f.arg" is not provided by "Obj.f"'
            in str(exc_info.value))
コード例 #9
0
def test_Schema_includes_interface_possible_types_in_the_type_map():
    SomeInterface = InterfaceType("SomeInterface", [Field("f", Int)])

    SomeSubtype = ObjectType("SomeSubtype", [Field("f", Int)],
                             lambda: [SomeInterface])

    schema = Schema(
        ObjectType("Query", [Field("iface", SomeInterface)]),
        types=[SomeSubtype],
    )

    assert schema.types.get("SomeSubtype") is SomeSubtype
コード例 #10
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_reject_object_fields_with_incorrectly_typed_interface_argument():
    iface = InterfaceType("IFace",
                          [Field("f", String, [Argument("arg", String)])])
    obj = ObjectType("Obj", [Field("f", String, [Argument("arg", Int)])],
                     interfaces=[iface])
    schema = _single_type_schema(obj)
    with pytest.raises(SchemaError) as exc_info:
        validate_schema(schema)

    assert ('Interface field argument "IFace.f.arg" expects '
            'type "String" but "Obj.f.arg" is type "Int"'
            in str(exc_info.value))
コード例 #11
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
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)
コード例 #12
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)
コード例 #13
0
ファイル: test_abstract_types.py プロジェクト: lirsacc/py-gql
async def test_type_resolution_supports_strings(assert_execution):
    def _resolve_pet_type(value, *_):
        return type(value).__name__

    PetType = InterfaceType("Pet", [Field("name", String)],
                            resolve_type=_resolve_pet_type)

    DogType = ObjectType(
        "Dog",
        [Field("name", String), Field("woofs", Boolean)],
        interfaces=[PetType],
    )

    CatType = ObjectType(
        "Cat",
        [Field("name", String), Field("meows", Boolean)],
        interfaces=[PetType],
    )

    schema = Schema(
        ObjectType(
            "Query",
            [
                Field(
                    "pets",
                    ListType(PetType),
                    resolver=lambda *_: [
                        Dog("Odie", True),
                        Cat("Garfield", False),
                    ],
                )
            ],
        ),
        types=[DogType, CatType],
    )

    await assert_execution(
        schema,
        """{
        pets {
            name
            __typename
            ... on Dog { woofs }
            ... on Cat { meows }
        }
        }""",
    )
コード例 #14
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)]),
    )
コード例 #15
0
ファイル: test_abstract_types.py プロジェクト: lirsacc/py-gql
    )

    await assert_execution(
        schema,
        """{
        pets {
            name
            __typename
            ... on Dog { woofs }
            ... on Cat { meows }
        }
        }""",
    )


NamedType = InterfaceType("Named", [Field("name", String)])

DogType = ObjectType(
    "Dog",
    [Field("name", String), Field("woofs", Boolean)],
    interfaces=[NamedType],
)

CatType = ObjectType(
    "Cat",
    [Field("name", String), Field("meows", Boolean)],
    interfaces=[NamedType],
)


def _resolve_pet_type(value, *_):
コード例 #16
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_accept_object_with_list_interface_list_field():
    iface = InterfaceType("IFace", [Field("f", ListType(String))])
    schema = _single_type_schema(
        ObjectType("SomeObject", [Field("f", ListType(String))],
                   interfaces=[iface]))
    schema.validate()
コード例 #17
0
ファイル: _star_wars.py プロジェクト: lirsacc/py-gql
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.",
        ),
        Field(
            "secretBackstory",
            String,
            description="All secrets about their past.",
        ),
    ],
    description="A character in the Star Wars Trilogy",
    resolve_type=resolve_character_type,
)  # type: InterfaceType
コード例 #18
0
from py_gql.schema import (
    Argument,
    Boolean,
    Directive,
    Field,
    InputField,
    InputObjectType,
    Int,
    InterfaceType,
    ListType,
    ObjectType,
    Schema,
    String,
)

Interface = InterfaceType("Interface", [Field("fieldName", String)])

Implementing = ObjectType("Object", [Field("fieldName", String)],
                          interfaces=[Interface])

DirInput = InputObjectType("DirInput", [InputField("field", String)])

WrappedDirInput = InputObjectType("WrappedDirInput",
                                  [InputField("field", String)])

Dir = Directive(
    "dir",
    ["OBJECT"],
    [
        Argument("arg", DirInput),
        Argument("argList", ListType(WrappedDirInput))
コード例 #19
0
ファイル: test_abstract_types.py プロジェクト: lirsacc/py-gql
async def test_type_resolution_on_interface_yields_useful_error(
    assert_execution, ):
    # WARN: Different from ref implementation -> this should never happen so we crash.

    def _resolve_pet_type(value, *_):
        return {
            Dog: DogType,
            Cat: CatType,
            Human: HumanType
        }.get(type(value), None)

    PetType = InterfaceType("Pet", [Field("name", String)],
                            resolve_type=_resolve_pet_type)

    HumanType = ObjectType("Human", [Field("name", String)])

    DogType = ObjectType(
        "Dog",
        [Field("name", String), Field("woofs", Boolean)],
        interfaces=[PetType],
    )

    CatType = ObjectType(
        "Cat",
        [Field("name", String), Field("meows", Boolean)],
        interfaces=[PetType],
    )

    schema = Schema(
        ObjectType(
            "Query",
            [
                Field(
                    "pets",
                    ListType(PetType),
                    resolver=lambda *_: [
                        Dog("Odie", True),
                        Cat("Garfield", False),
                        Human("Jon"),
                    ],
                )
            ],
        ),
        types=[DogType, CatType],
    )

    await assert_execution(
        schema,
        """{
        pets {
            name
            __typename
            ... on Dog { woofs }
            ... on Cat { meows }
        }
        }""",
        expected_exc=(
            RuntimeError,
            ('Runtime ObjectType "Human" is not a possible type for field '
             '"pets[2]" of type "Pet".'),
        ),
    )
コード例 #20
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
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()
コード例 #21
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
from py_gql.schema.validation import validate_schema

SomeScalar = ScalarType(
    "SomeScalar",
    serialize=lambda a: None,
    parse=lambda a: None,
    parse_literal=lambda a, **k: None,
)  # type: ScalarType

SomeObject = ObjectType("SomeObject", [Field("f", String)])

IncompleteObject = ObjectType("IncompleteObject", [])

SomeUnion = UnionType("SomeUnion", [SomeObject])

SomeInterface = InterfaceType("SomeInterface", [Field("f", String)])

SomeEnum = EnumType("SomeEnum", [EnumValue("ONLY")])

SomeInputObject = InputObjectType(
    "SomeInputObject", [InputField("val", String, default_value="hello")])


def _type_modifiers(t):
    return [t, ListType(t), NonNullType(t), NonNullType(ListType(t))]


def _with_modifiers(types):
    out = []  # type: List[GraphQLType]
    for t in types:
        out.extend(_type_modifiers(t))
コード例 #22
0
ファイル: conftest.py プロジェクト: lirsacc/py-gql
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
        ],
    )
コード例 #23
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_accept_interface_fields_with_output_type(type_):
    iface = InterfaceType("GoodInterface", [Field("f", type_)])
    schema = _single_type_schema(iface)
    schema.validate()
コード例 #24
0
ファイル: conftest.py プロジェクト: lirsacc/py-gql
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"]),
        ],
    )
コード例 #25
0
ファイル: test_validation.py プロジェクト: lirsacc/py-gql
def test_accept_object_fields_with_union_subtype_of_interface_field():
    union = UnionType("union", [SomeObject])
    iface = InterfaceType("IFace", [Field("f", union)])
    obj = ObjectType("Obj", [Field("f", SomeObject)], interfaces=[iface])
    schema = _single_type_schema(obj)
    schema.validate()