graphene icon indicating copy to clipboard operation
graphene copied to clipboard

Graphene v3 ignores mixin/multiple inheritance methods

Open serenajiang opened this issue 5 years ago • 3 comments

  • What is the current behavior?
  • If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via a github repo, https://repl.it or similar.

We use mixins to override __init__ (and other methods) for certain types. However, Graphene 3 does not seem to handle this python multiple-inheritance correctly. It calls the default graphene.ObjectType.__init__ instead of the custom __init__ method defined on the mixin.

A minimal example:

import graphene

class Mixin:
    def __init__(self):
        print("Calling Mixin.__init__()...")
        super().__init__(
            value="mixin value"
        )

class Thing(Mixin, graphene.ObjectType):
    value = graphene.String()

class TestQuery(graphene.ObjectType):
    test = graphene.Field(Thing)
    resolve_test = lambda parent, info: Thing()


schema = graphene.Schema(query=TestQuery)
print(schema.execute(
"""
{
  test {
    value
  }
}
"""
))

In Graphene 2, this works correctly, printing the result ExecutionResult(data={'test': {'value': 'mixin value'}}, errors=None) and the statement Calling Mixin.__init__().... However, in Graphene 3, we get the result ExecutionResult(data={'test': {'value': None}}, errors=None), and Calling Mixin.__init__()... never prints.

  • What is the expected behavior?

    • Mixin.__init__ should be called.
    • The result of the query should be ExecutionResult(data={'test': {'value': 'mixin value'}}, errors=None)
  • What is the motivation / use case for changing the behavior? Maintain functionality of graphene 2, enable use of multiple inheritance/mixins

  • Please tell us about your environment:

    • Version: graphene==3.0b6
    • python 3.6.8

serenajiang avatar Dec 07 '20 22:12 serenajiang

@serenajiang Were you able to find a workaround for this issue for the time being? I'm using graphene==3.0b7 and I still experience this bug. Thank you

engfragui avatar Jun 16 '21 20:06 engfragui

Maybe try overriding __init_subclass_with_meta__()

lovetoburnswhen avatar Sep 13 '21 00:09 lovetoburnswhen

I came up with this solution, and I don't know if this will work in all cases, but doing an explicit Mixin.__init__ call in Thing's constructor at least seemed to produce the expected result:

class Mixin:
    def __init__(self):
        print("Calling Mixin.__init__()...")
        self.value = "mixin value"


class Thing(Mixin, graphene.ObjectType):
    value = graphene.String()

    def __init__(self):
        Mixin.__init__(self)
Calling Mixin.__init__()...
ExecutionResult(data={'test': {'value': 'mixin value'}}, errors=None)

rgroothuijsen avatar Nov 04 '22 01:11 rgroothuijsen