Graphene v3 ignores mixin/multiple inheritance methods
- 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
- Version:
@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
Maybe try overriding __init_subclass_with_meta__()
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)