I’m upgrading an app from Graphene 2 to 3 and have run into an issue with some of the more complex ObjectType inheritance patterns that we have.
We have some code that looks similar to this:
class Person(ObjectType):
first_name = graphene.String()
last_name = graphene.String()
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
class Employee(Person):
email = graphene.String()
def __init__(self, first_name, last_name):
super().__init__(first_name, last_name)
self.email = f"{self.first_name}{self.last_name}@company.com"
This used to work in graphene 2, but in graphene 3 it raises an Exception with the message:
'Employee' object has no attribute 'first_name'
.
I believe this may be related to Graphene 3 optimizations to ObjectType initialization: https://github.com/graphql-python/graphene/pull/1157.
Looking at the MRO of Employee
it looks something like:
ipdb> Employee.mro()
[<Employee meta=<ObjectTypeOptions name='Employee'>>, <class 'graphene.types.objecttype.ObjectTypeMeta.__new__.<locals>.InterObjectType'>, <Person meta=None>, <class 'graphene.types.objecttype.ObjectTypeMeta.__new__.<locals>.InterObjectType'>, <ObjectType meta=None>, <class 'graphene.types.objecttype.ObjectTypeMeta.__new__.<locals>.InterObjectType'>, <BaseType meta=None>, <SubclassWithMeta meta=None>, <class 'object'>]
So I think super().__init__()
is resolving to the __init__
method on 'graphene.types.objecttype.ObjectTypeMeta.__new__.<locals>.InterObjectType'
. Thus, __init__
is never called on Person
.
I can overcome this issue by calling __init__
directly on Person
rather than as a method on super
. But, generally this is assumed to be a bad practice.
Is there a recommended way to implement an ObjectType class hierarchy with custom __init__
methods in Graphene 3?