Skip to content
Advertisement

How to troubleshoot `super()` calls finding incorrect type and obj?

I have a decorator in my library which takes a user’s class and creates a new version of it, with a new metaclass, it is supposed to completely replace the original class. Everything works; except for super() calls:

JavaScript

Using this code like so, yields an error:

JavaScript

Some terminology:

  • The source code class A as produced by class A(B):.
  • The produced class A*, as produced by NewMeta(cls.__name__, cls.__bases__, cls_dict).

A is established by Python to be the type when using super inside of the methods of A*. How can I correct this?

There’s some suboptimal solutions like calling super(type(self), self).x, or passing cls.__mro__ instead of cls.__bases__ into the NewMeta call (so that obj=self always inherits from the incorrect type=A). The first is unsustainable for end users, the 2nd pollutes the inheritance chains and is confusing as the class seems to inherit from itself.

Python seems to introspect the source code, or maybe stores some information to automatically establish the type, and in this case, I’d say it is failing to do so;

How could I make sure that inside of the methods of A A* is established as the type argument of argumentless super calls?

Advertisement

Answer

The argument-free super uses the __class__ cell, which is a regular function closure.

Data Model: Creating the class object

__class__ is an implicit closure reference created by the compiler if any methods in a class body refer to either __class__ or super.

JavaScript

Like any other closure, this is a lexical relation: it refers to class scope in which the method was literally defined. Replacing the class with a decorator still has the methods refer to the original class.


The simplest fix is to explicitly refer to the name of the class, which gets rebound to the newly created class by the decorator.

JavaScript

Alternatively, one can change the content of the __class__ cell to point to the new class:

JavaScript
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement