UserExpression breaks if __init__ is given and super().__init__() is not called

Issue #1121 new
Stefano Ottolenghi created an issue

From the Expression documentation, section 3, it looks like one can pass arguments to the UserExpression subclass through __init__, which may then store it as class attribute so that eval can use it. This is not the case. Attempting to do so results in an error message like AttributeError: 'P_class' object has no attribute '_ufl_shape'.

The issue is that if one provides a __init__, then he also needs to call super().__init__().

There are a bunch of fixes by @Chris Richardson on the matter (9732cf9, e6c15db), which would make calling super().__init__() not needed, but it looks like they have never been merged. I guess we can either merge those commits, or update the documentation pointing out that calling the base constructor is needed (docs need updating after #883 anyway).


A minimal (non-)working example:

from fenics import *

test_mode = 2
    # 1 does not work
    # 2 works

mesh = UnitIntervalMesh(10)
V = FunctionSpace(mesh, 'Lagrange', 2)
u  = TrialFunction(V)
v = TestFunction(V)
sol = Function(V)

def f(x):
    return x**2

if test_mode == 1:
    class P_class(UserExpression):
        def __init__(self, f):
            self._f = f
        def eval(self, value, x):
            value = self._f(x)

    P = P_class(f=f)

elif test_mode == 2:
    class P_class(UserExpression):
        def __init__(self, f):
            self._f = f
            super().__init__()
        def eval(self, value, x):
            value = self._f(x)

    P = P_class(f=f)

a = u * v * dx 
L = P * v * dx

bcs = DirichletBC(V, 0, 'near(x[0], 1)')
solve(a == L, sol, bcs=bcs)