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}}
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)
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", )], )
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(), )
def test_null_non_nullable_type(): _test( None, NonNullType(Int), None, "Expected non-nullable type Int! not to be null", )
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 )
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, )
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 } """)
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, )
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))
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' )
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"' )
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(), )
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)]
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)
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) ]
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)
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"), ], ) ], ))
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)]), )
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,
def _type_modifiers(t): return [t, ListType(t), NonNullType(t), NonNullType(ListType(t))]
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,
def test_as_non_null(): assert UUID.as_non_null() == NonNullType(UUID)
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 ], )
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."), ), )
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()
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.", ),
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}, )
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):
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"]), ], )