Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphene ObjectType constructor does not make deep copy but instead shallow copy #1256

Open
LinnaViljami opened this issue Aug 20, 2020 · 0 comments
Labels

Comments

@LinnaViljami
Copy link

LinnaViljami commented Aug 20, 2020

Note: for support questions, please use stackoverflow. This repository's issues are reserved for feature requests and bug reports.

  • What is the current behavior?
    We have types:
  ChildType(graphene.ObjectType):
    enabled = graphene.Boolean(required=True, default_value=False)
    def enable(self):
      self.enabled = True
    def disable(self):
      self.enabled = False

  ParentType(graphene.ObjectType):
    p1prop1 = graphene.Field(ChildType, required=True, default_value=ChildType())
    p1prop2 = graphene.Field(ChildType, required=True, default_value=ChildType())
    def enable_children(self):
      self.p1prop1.enable()
      self.p1prop2.enable()

  ParentType2(graphene.ObjectType):
    p2prop1 = graphene.Field(ParentType, required=True, default_value=ParentType())
    p2prop2 = graphene.Field(ParentType, required=True, default_value=ParentType())

In schema we call

class Query(graphene.ObjectType):
    parent_two = graphene.Field(ParentType2)

    def resolve_parent_two(self, info, *args, **kwargs):
        parent_two = ParentType2()
        parent_two.p2prop1.enable_children()
        return parent_two

When querying parent_two trough localhost:8000/graphql, it returns:

  parent_two {
    p2prop1{
      p1prop1{
        enabled: True
      }
      p1prop2{
        enabled: True
      }
    }
    p2prop2{
      p1prop1{
        enabled: True
      }
      p1prop2{
        enabled: True
      }
    }
  }

The memory addresses of p2prop1 and p2prop2 are not equal which is right, but somehow mutating p2prop1.p1prop1 also affects to p2prop2.p1prop1 which leads to conclusion that calling constructor ParentType() when setting ParentType2 fields default_value leads to shallow copy instead of deep copy

  • What is the expected behavior?
    When querying parent_two trough localhost:8000/graphql, we expect it return:
  parent_two {
    p2prop1{
      p1prop1{
        enabled: True
      }
      p1prop2{
        enabled: True
      }
    }
    p2prop2{
      p1prop1{
        enabled: False
      }
      p1prop2{
        enabled: False
      }
    }
  }

We would want ParentType() constructor always make new object instead of shallow copy

  • What is the motivation / use case for changing the behavior?
    Current behaviour leads to unintuitive results

  • Please tell us about your environment:

    • Version:
      graphene==2.1.8
      graphene-django==2.10.1
    • Platform:
      Ubuntu 18.04, Pycharm, community edition, Chromium browser
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
    We can fix the behaviour by calling

  import copy

  parentTypeInstance = ParentType()

  ParentType2(graphene.ObjectType):
    p2prop1 = graphene.Field(ParentType, required=True, default_value=copy.deepcopy(parentTypeInstance))
    p2prop2 = graphene.Field(ParentType, required=True, default_value=copy.deepcopy(parentTypeInstance))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant