graphql-python / graphene

GraphQL framework for Python
http://graphene-python.org/
MIT License
8.1k stars 828 forks source link

Default_value option in Arguments inside Mutation is not working as expected #1534

Open VicGoico opened 10 months ago

VicGoico commented 10 months ago

Hi,

class AnimalFarm(graphene.Mutation):
    class Arguments:
        animals = graphene.List(graphene.String, default_value=[])

    output = graphene.List(graphene.String)

    def mutate(root, info, **filters):
        import pdb; pdb.set_trace()
        animals_mio = filters["animals"]
        animals_mio.append('duck')

        return animals_mio

class Mutation(graphene.ObjectType):
    animal_farm = AnimalFarm.Field()

where you can see that I am declaring a Mutation that have and argument called "animals" which type is "graphene.List(graphene.String, default_value=[])", that means if I dont pass this argument in the mutation, graphene automatically filled this argument ("animals") with an empty list.

At this point all works perfect, but when I try the following steps, I reckon that could be a little bug in to reset the old value of "animals" argument.

import graphene

class Query(graphene.ObjectType):
    nothing = graphene.String()

    def resolve_nothing(root, info):
        return "empty"

class AnimalFarm(graphene.Mutation):
    class Arguments:
        animals = graphene.List(graphene.String, default_value=[])

    output = graphene.List(graphene.String)

    def mutate(root, info, **filters):
        import pdb; pdb.set_trace()
        animals_local = filters["animals"]
        animals_local.append('duck')

        return animals_local

class Mutation(graphene.ObjectType):
    animal_farm = AnimalFarm.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

mutation = """
    mutation addAnimals{
        animalFarm {
            output
        }
    }
"""

def test_mutation():
    # First request
    result = schema.execute(mutation)
    print(result)

    # Second request, in this request it is the problem !!!
    result = schema.execute(mutation)
    print(result)

test_mutation()
python3 cool_file_name.py
erikwrede commented 10 months ago

Hey @VicGoico, from my point of view, this is not a bug but expected behavior. Default values should be treated as READ-Only. We cannot expect all default values to implement copy to satisfaction. Due to that, it is on the user to avoid mutating the defaults. My recommendation for lists: use an empty tuple for defaults (,). However, documentation could be improved to mention this.

VicGoico commented 10 months ago

Hi @erikwrede , thanks for your answer.

Therefore, the solution is to use .copy(), when we want to handle the value argument, to isolate it.

To sum up, the example that I mentioned, will work fine doing this:

class AnimalFarm(graphene.Mutation):
    class Arguments:
        animals = graphene.List(graphene.String, default_value=(,))

    output = graphene.List(graphene.String)

    def mutate(root, info, **filters):
        animals_mio = filters["animals"].copy() # Here is the solution
        animals_mio.append('duck')

        return animals_mio

class Mutation(graphene.ObjectType):
    animal_farm = AnimalFarm.Field()

Any mantainer can close the issue if they see it necessary.

Thanks for your work and have a nice day