From 2dee4f2b375671af3d10475f8af39d6a626676a8 Mon Sep 17 00:00:00 2001 From: Laurent Riviere Date: Fri, 14 Oct 2022 13:21:09 +0000 Subject: [PATCH] feat: added object_type_name_prefix --- graphene/types/schema.py | 38 +++++++- graphene/types/tests/test_mutation.py | 41 +++++++++ graphene/types/tests/test_query.py | 25 ++++++ graphene/types/tests/test_schema.py | 125 +++++++++++++++++++++++++- 4 files changed, 225 insertions(+), 4 deletions(-) diff --git a/graphene/types/schema.py b/graphene/types/schema.py index 1a33a93d..0915899d 100644 --- a/graphene/types/schema.py +++ b/graphene/types/schema.py @@ -91,6 +91,7 @@ class TypeMap(dict): subscription=None, types=None, auto_camelcase=True, + object_type_name_prefix=None, ): assert_valid_root_type(query) assert_valid_root_type(mutation) @@ -101,9 +102,18 @@ class TypeMap(dict): assert is_graphene_type(type_) self.auto_camelcase = auto_camelcase + self.object_type_name_prefix = object_type_name_prefix create_graphql_type = self.add_type + self.root_names = [] + if query: + self.root_names.append(query._meta.name) + if mutation: + self.root_names.append(mutation._meta.name) + if subscription: + self.root_names.append(subscription._meta.name) + self.query = create_graphql_type(query) if query else None self.mutation = create_graphql_type(mutation) if mutation else None self.subscription = create_graphql_type(subscription) if subscription else None @@ -215,9 +225,15 @@ class TypeMap(dict): else: is_type_of = graphene_type.is_type_of + name = ( + self.object_type_name_prefix.capitalize() + if self.object_type_name_prefix + else "" + ) + graphene_type._meta.name + return GrapheneObjectType( graphene_type=graphene_type, - name=graphene_type._meta.name, + name=name, description=graphene_type._meta.description, fields=partial(self.create_fields_for_type, graphene_type), is_type_of=is_type_of, @@ -357,7 +373,17 @@ class TypeMap(dict): deprecation_reason=field.deprecation_reason, description=field.description, ) - field_name = field.name or self.get_name(name) + if field.name: + field_name = field.name + else: + if ( + self.object_type_name_prefix + and graphene_type._meta.name in self.root_names + ): + object_type_name_prefix = self.object_type_name_prefix + "_" + field_name = self.get_name(object_type_name_prefix + name) + else: + field_name = self.get_name(name) fields[field_name] = _field return fields @@ -421,12 +447,18 @@ class Schema: types=None, directives=None, auto_camelcase=True, + object_type_name_prefix=None, ): self.query = query self.mutation = mutation self.subscription = subscription type_map = TypeMap( - query, mutation, subscription, types, auto_camelcase=auto_camelcase + query, + mutation, + subscription, + types, + auto_camelcase=auto_camelcase, + object_type_name_prefix=object_type_name_prefix, ) self.graphql_schema = GraphQLSchema( type_map.query, diff --git a/graphene/types/tests/test_mutation.py b/graphene/types/tests/test_mutation.py index 4a7ad3c7..09ec5102 100644 --- a/graphene/types/tests/test_mutation.py +++ b/graphene/types/tests/test_mutation.py @@ -218,3 +218,44 @@ def test_mutation_as_subclass(): ) assert not result.errors assert result.data == {"createUserWithPlanet": {"name": "Peter", "planet": "earth"}} + + +def test_object_type_name_prefix(): + class BaseCreateUser(Mutation): + class Arguments: + name = String() + + name = String() + + def mutate(self, info, **args): + return args + + class CreateUserWithPlanet(BaseCreateUser): + class Arguments(BaseCreateUser.Arguments): + planet = String() + + planet = String() + + def mutate(self, info, **args): + return CreateUserWithPlanet(**args) + + class MyMutation(ObjectType): + create_user_with_planet = CreateUserWithPlanet.Field() + + class Query(ObjectType): + a = String() + + schema = Schema(query=Query, mutation=MyMutation, object_type_name_prefix="prefix") + result = schema.execute( + """ mutation mymutation { + prefixCreateUserWithPlanet(name:"Peter", planet: "earth") { + name + planet + } + } + """ + ) + assert not result.errors + assert result.data == { + "prefixCreateUserWithPlanet": {"name": "Peter", "planet": "earth"} + } diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index e117754f..3b9debeb 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -497,3 +497,28 @@ def test_default_as_kwarg_to_NonNull(): assert not result.errors assert result.data == expected + + +def test_object_type_name_prefix(): + class Cat(ObjectType): + name = String() + + class User(ObjectType): + name = String() + cat = Field(Cat) + + def resolve_cat(self, *args, **kwargs): + return Cat(name="bar") + + class Query(ObjectType): + user = Field(User) + + def resolve_user(self, *args, **kwargs): + return User(name="foo") + + schema = Schema(query=Query, object_type_name_prefix="prefix") + expected = {"prefixUser": {"name": "foo", "cat": {"name": "bar"}}} + result = schema.execute("{ prefixUser { name cat { name } } }") + + assert not result.errors + assert result.data == expected diff --git a/graphene/types/tests/test_schema.py b/graphene/types/tests/test_schema.py index c03c81ba..a8e25ee8 100644 --- a/graphene/types/tests/test_schema.py +++ b/graphene/types/tests/test_schema.py @@ -5,19 +5,43 @@ from pytest import raises from graphql.type import GraphQLObjectType, GraphQLSchema from ..field import Field +from ..mutation import Mutation from ..objecttype import ObjectType -from ..scalars import String +from ..scalars import Int, String from ..schema import Schema +class MyType(ObjectType): + field = String() + + class MyOtherType(ObjectType): field = String() + my_type = Field(MyType) class Query(ObjectType): inner = Field(MyOtherType) +class CreateUser(Mutation): + class Arguments: + name = String() + + name = String() + + def mutate(self, info, name): + return CreateUser(name=name) + + +class Mutation(ObjectType): + create_user = CreateUser.Field() + + +class Subscription(ObjectType): + count_to_ten = Field(Int) + + def test_schema(): schema = Schema(Query) graphql_schema = schema.graphql_schema @@ -54,6 +78,11 @@ def test_schema_str(): type MyOtherType { field: String + myType: MyType + } + + type MyType { + field: String } """ ).strip() @@ -72,3 +101,97 @@ def test_schema_requires_query_type(): assert len(result.errors) == 1 error = result.errors[0] assert error.message == "Query root type must be provided." + + +def test_schema_object_type_name_prefix_camelcase(): + schema = Schema( + Query, + Mutation, + Subscription, + auto_camelcase=True, + object_type_name_prefix="prefix", + ) + assert ( + str(schema).strip() + == dedent( + """ + schema { + query: PrefixQuery + mutation: PrefixMutation + subscription: PrefixSubscription + } + + type PrefixQuery { + prefixInner: PrefixMyOtherType + } + + type PrefixMyOtherType { + field: String + myType: PrefixMyType + } + + type PrefixMyType { + field: String + } + + type PrefixMutation { + prefixCreateUser(name: String): PrefixCreateUser + } + + type PrefixCreateUser { + name: String + } + + type PrefixSubscription { + prefixCountToTen: Int + } + """ + ).strip() + ) + + +def test_schema_object_type_name_prefix_camelcase_disabled(): + schema = Schema( + Query, + Mutation, + Subscription, + auto_camelcase=False, + object_type_name_prefix="prefix", + ) + assert ( + str(schema).strip() + == dedent( + """ + schema { + query: PrefixQuery + mutation: PrefixMutation + subscription: PrefixSubscription + } + + type PrefixQuery { + prefix_inner: PrefixMyOtherType + } + + type PrefixMyOtherType { + field: String + my_type: PrefixMyType + } + + type PrefixMyType { + field: String + } + + type PrefixMutation { + prefix_create_user(name: String): PrefixCreateUser + } + + type PrefixCreateUser { + name: String + } + + type PrefixSubscription { + prefix_count_to_ten: Int + } + """ + ).strip() + )